1. If see this error as follows,
org.hibernate.cfg.jdbcbinder Exception and it says Duplicate class name 'Syscatalog' generated for 'org.hibernate.mapping.Table(SYS.SYSCATALOG_)'. Same name where generated for org.hibernate.mapping.Table(SYS.SYSCATALOG_)
just add property 'hibernate.default_schema' in hibernate.cfg.xml, for example,
<property name="hibernate.default_schema">ABC</property>
2. configure @Id for oracle sequence
CREATE TABLE MY_TABLE(
ID NUMBER NOT NULL,
CONSTRAINT MY_TABLE_PK PRIMARY KEY(ID)
);
CREATE SEQUENCE mytable_seq START WITH 1 INCREMENT BY 1 CACHE 10 NOCYCLE;
@SequenceGenerator(name = "SEQGEN_MYTABLE", sequenceName = "mytable_seq",
allocationSize = 1, initialValue = 1)
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "SEQGEN_MYTABLE")
@Column(name = "ID")
public long getId() {
return this.id;
}
Wang Xiang's Blog
Monday, January 11, 2016
Tuesday, October 13, 2015
spring boot, mockito, spring rest, junit
This is sample code to do junit test for spring rest/spring boot with mockito.
package com.demo.app.web.api.v1;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.List;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;
import org.springframework.boot.test.SpringApplicationConfiguration;
import org.springframework.http.MediaType;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.web.WebAppConfiguration;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.result.MockMvcResultMatchers;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import com.demo.app.WebApplication;
import com.demo.app.repository.entity.Stock;
import com.demo.app.service.StockService;
import static org.hamcrest.Matchers.*;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;
import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print;
@RunWith(SpringJUnit4ClassRunner.class)
@WebAppConfiguration
@SpringApplicationConfiguration(classes = { WebApplication.class })
public class StockControllerTest {
private static final MediaType APP_ContentType = new MediaType(MediaType.APPLICATION_JSON.getType(),
MediaType.APPLICATION_JSON.getSubtype(), Charset.forName("utf8"));
private MockMvc mvc;
@Mock
private StockService stockService;
@InjectMocks
private StockController controller;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
mvc = MockMvcBuilders.standaloneSetup(controller).build();
}
@After
public void tearDown() throws Exception {
}
@Test
public void testStocks() throws Throwable {
// prepare test data
List<Stock> stocks = new ArrayList<Stock>();
// stock1
Stock stock1 = new Stock();
stock1.setStockCode("code 1");
stock1.setStockName("name 1");
stock1.setStockPrice(1.111);
stock1.setStockPriceChange(-0.111);
stocks.add(stock1);
// stock2
Stock stock2 = new Stock();
stock2.setStockCode("code 2");
stock2.setStockName("name 2");
stock2.setStockPrice(2.222);
stock2.setStockPriceChange(-0.222);
stocks.add(stock2);
// stock3
Stock stock3 = new Stock();
stock3.setStockCode("code 3");
stock3.setStockName("name 3");
stock3.setStockPrice(3.333);
stock3.setStockPriceChange(-0.333);
stocks.add(stock3);
Mockito.when(stockService.findAll()).thenReturn(stocks);
mvc.perform(get("/api/v1/stocks")).andDo(print()).andExpect(MockMvcResultMatchers.status().isOk())
.andExpect(content().contentTypeCompatibleWith(APP_ContentType)).andExpect(jsonPath("$", hasSize(3)))
.andExpect(jsonPath("$[0].stockCode", is(stock1.getStockCode())))
.andExpect(jsonPath("$[0].stockName", is(stock1.getStockName())))
.andExpect(jsonPath("$[0].stockPrice", is(stock1.getStockPrice())))
.andExpect(jsonPath("$[0].stockPriceChange", is(stock1.getStockPriceChange())))
.andExpect(jsonPath("$[1].stockCode", is(stock2.getStockCode())))
.andExpect(jsonPath("$[1].stockName", is(stock2.getStockName())))
.andExpect(jsonPath("$[1].stockPrice", is(stock2.getStockPrice())))
.andExpect(jsonPath("$[1].stockPriceChange", is(stock2.getStockPriceChange())))
.andExpect(jsonPath("$[2].stockCode", is(stock3.getStockCode())))
.andExpect(jsonPath("$[2].stockName", is(stock3.getStockName())))
.andExpect(jsonPath("$[2].stockPrice", is(stock3.getStockPrice())))
.andExpect(jsonPath("$[2].stockPriceChange", is(stock3.getStockPriceChange())));
}
@Test
public void testGetStock() throws Throwable {
// prepare test data
Stock stock = new Stock();
stock.setStockCode("abc");
stock.setStockName("name 1");
stock.setStockPrice(1.111);
stock.setStockPriceChange(-0.111);
Mockito.when(stockService.findByStockCode(stock.getStockCode())).thenReturn(stock);
mvc.perform(get("/api/v1/stocks/{code}", stock.getStockCode())).andDo(print())
.andExpect(MockMvcResultMatchers.status().isOk())
.andExpect(content().contentTypeCompatibleWith(APP_ContentType))
.andExpect(jsonPath("$.stockCode", is(stock.getStockCode())))
.andExpect(jsonPath("$.stockName", is(stock.getStockName())))
.andExpect(jsonPath("$.stockPrice", is(stock.getStockPrice())))
.andExpect(jsonPath("$.stockPriceChange", is(stock.getStockPriceChange())));
}
}
package com.demo.app.web.api.v1;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.List;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;
import org.springframework.boot.test.SpringApplicationConfiguration;
import org.springframework.http.MediaType;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.web.WebAppConfiguration;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.result.MockMvcResultMatchers;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import com.demo.app.WebApplication;
import com.demo.app.repository.entity.Stock;
import com.demo.app.service.StockService;
import static org.hamcrest.Matchers.*;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;
import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print;
@RunWith(SpringJUnit4ClassRunner.class)
@WebAppConfiguration
@SpringApplicationConfiguration(classes = { WebApplication.class })
public class StockControllerTest {
private static final MediaType APP_ContentType = new MediaType(MediaType.APPLICATION_JSON.getType(),
MediaType.APPLICATION_JSON.getSubtype(), Charset.forName("utf8"));
private MockMvc mvc;
@Mock
private StockService stockService;
@InjectMocks
private StockController controller;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
mvc = MockMvcBuilders.standaloneSetup(controller).build();
}
@After
public void tearDown() throws Exception {
}
@Test
public void testStocks() throws Throwable {
// prepare test data
List<Stock> stocks = new ArrayList<Stock>();
// stock1
Stock stock1 = new Stock();
stock1.setStockCode("code 1");
stock1.setStockName("name 1");
stock1.setStockPrice(1.111);
stock1.setStockPriceChange(-0.111);
stocks.add(stock1);
// stock2
Stock stock2 = new Stock();
stock2.setStockCode("code 2");
stock2.setStockName("name 2");
stock2.setStockPrice(2.222);
stock2.setStockPriceChange(-0.222);
stocks.add(stock2);
// stock3
Stock stock3 = new Stock();
stock3.setStockCode("code 3");
stock3.setStockName("name 3");
stock3.setStockPrice(3.333);
stock3.setStockPriceChange(-0.333);
stocks.add(stock3);
Mockito.when(stockService.findAll()).thenReturn(stocks);
mvc.perform(get("/api/v1/stocks")).andDo(print()).andExpect(MockMvcResultMatchers.status().isOk())
.andExpect(content().contentTypeCompatibleWith(APP_ContentType)).andExpect(jsonPath("$", hasSize(3)))
.andExpect(jsonPath("$[0].stockCode", is(stock1.getStockCode())))
.andExpect(jsonPath("$[0].stockName", is(stock1.getStockName())))
.andExpect(jsonPath("$[0].stockPrice", is(stock1.getStockPrice())))
.andExpect(jsonPath("$[0].stockPriceChange", is(stock1.getStockPriceChange())))
.andExpect(jsonPath("$[1].stockCode", is(stock2.getStockCode())))
.andExpect(jsonPath("$[1].stockName", is(stock2.getStockName())))
.andExpect(jsonPath("$[1].stockPrice", is(stock2.getStockPrice())))
.andExpect(jsonPath("$[1].stockPriceChange", is(stock2.getStockPriceChange())))
.andExpect(jsonPath("$[2].stockCode", is(stock3.getStockCode())))
.andExpect(jsonPath("$[2].stockName", is(stock3.getStockName())))
.andExpect(jsonPath("$[2].stockPrice", is(stock3.getStockPrice())))
.andExpect(jsonPath("$[2].stockPriceChange", is(stock3.getStockPriceChange())));
}
@Test
public void testGetStock() throws Throwable {
// prepare test data
Stock stock = new Stock();
stock.setStockCode("abc");
stock.setStockName("name 1");
stock.setStockPrice(1.111);
stock.setStockPriceChange(-0.111);
Mockito.when(stockService.findByStockCode(stock.getStockCode())).thenReturn(stock);
mvc.perform(get("/api/v1/stocks/{code}", stock.getStockCode())).andDo(print())
.andExpect(MockMvcResultMatchers.status().isOk())
.andExpect(content().contentTypeCompatibleWith(APP_ContentType))
.andExpect(jsonPath("$.stockCode", is(stock.getStockCode())))
.andExpect(jsonPath("$.stockName", is(stock.getStockName())))
.andExpect(jsonPath("$.stockPrice", is(stock.getStockPrice())))
.andExpect(jsonPath("$.stockPriceChange", is(stock.getStockPriceChange())));
}
}
=================== ==========================
with eclipse, if encounter this exception as follows,
java.lang.SecurityException: class "org.hamcrest.Matchers"'s signer information does not match signer information of other classes in the same package
open "Configure Build Path" and select "Library" tab, remove "Junit" from the build path. The root cause is jar conflict with plug in "Hamctest" inside eclipse.
Tuesday, September 22, 2015
Autowired not working for repository in spring boot
in spring boot, beside @SpringBootApplication, need to add the following 3 annotations to make @Autowired to init jpa repository objects.
@SpringBootApplication
@ComponentScan(basePackages = { "com.abc" })
@EnableJpaRepositories(basePackages = { "com.abc.repository" })
@EntityScan(basePackages = "com.abc.repository.entity")
public class WebApplication extends SpringBootServletInitializer {
@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
return application.sources(WebApplication.class);
}
public static void main(String[] args) throws Exception {
SpringApplication.run(WebApplication.class, args);
}
}
@SpringBootApplication
@ComponentScan(basePackages = { "com.abc" })
@EnableJpaRepositories(basePackages = { "com.abc.repository" })
@EntityScan(basePackages = "com.abc.repository.entity")
public class WebApplication extends SpringBootServletInitializer {
@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
return application.sources(WebApplication.class);
}
public static void main(String[] args) throws Exception {
SpringApplication.run(WebApplication.class, args);
}
}
Friday, January 9, 2015
Maven Jetty PermGen space
before run "mvn jetty:run"
run this command in window env
set MAVEN_OPTS=-Xmx1024m -XX:MaxPermSize=512m
or unix-like env
run this command in window env
set MAVEN_OPTS=-Xmx1024m -XX:MaxPermSize=512m
or unix-like env
export MAVEN_OPTS="-Xmx1024m -XX:MaxPermSize=512m"
Friday, January 2, 2015
Spring MVC read properties in the class
This is sample code:
@Component( "emailService" )
public class EmailService {
@Value( "${mail.server.url}" )
private String url;
@Component( "emailService" )
public class EmailService {
@Value( "${mail.server.url}" )
private String url;
....
}
in the property file
mail.server.ur=http://abc/def
Monday, December 29, 2014
Android dev study notes - 1
- Dailer
String number = tv.getText().toString(); // get No from an edittext
Intent it = new Intent(Intent.ACTION_DIAL);
it.setData(Uri.parse("tel:"+number));
this.startActivity(it);
------- permission ------
<uses-permission android:name="android.permission.CALL_PHONE"/>
- SMS
String mNo = evMobileNo.getText().toString();
String content = evSMSContent.getText().toString();
SmsManager sm = SmsManager.getDefault();
ArrayList<String> text = sm.divideMessage(content); // just in case message is too long
for (String s : text) {
sm.sendTextMessage(mNo, null, s, null, null);
}
Toast.makeText(MainActivity.this, "sent success",
Toast.LENGTH_LONG).show();
------- permission ------
<uses-permission android:name="android.permission.SEND_SMS" />
- Save/Read File to/from memory card
public void savePrivateMode(String fileName, String fileContent)
throws Exception {
FileOutputStream out = context.openFileOutput(fileName,
Context.MODE_PRIVATE);
out.write(fileContent.getBytes());
out.close();
}
The mode is Context.MODE_PRIVATE, only the app who created the file is allowed to access the file, no one else is allowed to access it.
The file permission is -rw-rw----
If save the same file name again and again, the content will be overwrited.
And the location of this file is /data/data/<app package name>/files/<file name> in the memory card.
public void saveAppendMode(String fileName, String fileContent)
throws Exception {
FileOutputStream out = context.openFileOutput(fileName,
Context.MODE_APPEND);
out.write(fileContent.getBytes());
out.close();
}
The mode is Context.MODE_APPEND, only the app who created the file is allowed to access the file, no one else is allowed to access it.
The file permission is -rw-rw----
If save the same file name again and again, the content will be appended.
And the location of this file is /data/data/<app package name>/files/<file name> in the memory card.
FileInputStream input = context.openFileInput(fileName);
ByteArrayOutputStream out = new ByteArrayOutputStream();
byte[] buffer = new byte[1024];
int len = 0;
while ((len = input.read(buffer)) != -1) {
out.write(buffer, 0, len);
}
// omit i/o close() method
return new String(out.toByteArray());
}
This method is allowed to read file under /data/data/<app package name>/files/<file name> at the same app.
If another app needs to access this file in this app, the code is as follows,
public String read(String fileName) throws Exception {
String fn = "/data/data/<package name>/files/"+fileName;
File file = new File(fn);
// should NOT be context.openFileInput(fileName); it is for memory card
FileInputStream input = new FileInputStream(file);
ByteArrayOutputStream out = new ByteArrayOutputStream();
byte[] buffer = new byte[1024];
int len = 0;
while ((len = input.read(buffer)) != -1) {
out.write(buffer, 0, len);
}
// omit i/o close() method
return new String(out.toByteArray());
}
If the mode is Context.MODE_PRIVATE or Context.MODE_APPEND, cannot read file from external app, unless the external app set the mode as Context.MODE_WORLD_READABLE when saving the file.
If an app is open the file to be read/write for external apps, when save a file, the file mode need to set as Context.MODE_WORLD_READABLE + Context.MODE_WORLD_WRITEABLE
- Save/Read File to/from SD card
if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED))
file location:
File file = new File(Environment.getExternalStorageDirectory(),fileName);
Enviroment.getExternalStorageDirectory() points to /mnt/sdcard for current android os, and points to /sdcard for very older os version.
- SharedPreferences
public void save(String color, int fontSize) {
SharedPreferences sf = context.getSharedPreferences("custprefer",
Context.MODE_PRIVATE);
Editor edit = sf.edit();
edit.putString("color", color);
edit.putInt("fontSize", fontSize);
edit.commit();
}
in the end, a new file custprefer.xml will be generated at folder /data/data/<package>/shared_prefs/custprefer.xml as follows,
<?xml version='1.0' encoding='utf-8' standalone='yes' ?>
<map>
<int name="fontSize" value="12" />
<string name="color">red</string>
</map>
- SQLite
package com.example.dbdemo;
import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
public class DBHelper extends SQLiteOpenHelper {
public DBHelper(Context context) {
super(context, "demo.db", null, 1);
}
@Override
public void onCreate(SQLiteDatabase db) {
db.execSQL("create table person(pid integer primary key autoincrement,name varchar(20))");
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
}
}
From the constructor, set db version is 1, and db file name is demo.db, onCreate() will be triggered if demo.db does not exit.
This is a test class to trigger onCreate() method.
package com.example.dbdemo.test;
import com.example.dbdemo.DBHelper;
import android.test.AndroidTestCase;
public class DBHelperTester extends AndroidTestCase {
public void testDB() throws Exception {
DBHelper helper = new DBHelper(this.getContext());
helper.getWritableDatabase();
}
}
then the new demo.db file will be found in folder /data/data/<package>/databases/demo.db, use the tools sqlite expert to check the table is created successfully.
Now change above code to make the version to 2 in the constructor,and add some db changes in method onUpgrade() which will be triggered if db version changes
package com.example.dbdemo;
import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
public class DBHelper extends SQLiteOpenHelper {
public DBHelper(Context context) {
super(context, "demo.db", null, 2);
}
@Override
public void onCreate(SQLiteDatabase db) {
db.execSQL("create table person(pid integer primary key autoincrement,name varchar(20))");
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
db.execSQL("create table teacher(tid integer primary key autoincrement,name varchar(20))");
db.execSQL("alter table person add address varchar(20) null");
}
}
run above test method again, found a new table and a new field are created.
This is a simple class to insert a record
public class MyDbService {
private DBHelper dbHelper;
public MyDbService(DBHelper dbHelper) {
this.dbHelper = dbHelper;
}
public void save() {
SQLiteDatabase db = dbHelper.getWritableDatabase();
db.execSQL("insert into person (name) values (?)",
new Object[] { "testuser" });
}
}
- TBC
Spring MVC restful tips - 406 error, cannot put email in the url
- 406 not acceptable error
need to add the following configuration
<mvc:annotation-driven
content-negotiation-manager="contentNegotiationManager">
</mvc:annotation-driven>
<bean id="contentNegotiationManager"
class="org.springframework.web.accept.ContentNegotiationManagerFactoryBean">
<property name="favorPathExtension" value="false" />
<property name="favorParameter" value="true" />
<property name="mediaTypes">
<value>
json=application/json
xml=application/xml
</value>
</property>
</bean>
<!-- resolve not acceptable issue -->
<bean id="jacksonMessageConverter"
class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter">
<property name="supportedMediaTypes">
<list>
<value>text/html;charset=UTF-8</value>
<value>text/xml;charset=UTF-8</value>
<value>application/json;charset=UTF-8</value>
</list>
</property>
</bean>
this is jackson dependencies:
<dependency>
<groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-core-asl</artifactId>
<version>${jackson.version}</version>
</dependency>
<dependency>
<groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-mapper-asl</artifactId>
<version>${jackson.version}</version>
</dependency>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.6</maven.compiler.source>
<maven.compiler.target>1.6</maven.compiler.target>
<spring.core.version>3.2.4.RELEASE</spring.core.version>
<log.version>1.2.17</log.version>
<hibernate.version>3.6.10.Final</hibernate.version>
<jackson.version>1.9.13</jackson.version>
</properties>
- avoid URI using dots to be truncated
Subscribe to:
Posts (Atom)