Batch insertion with Spring MVC and Hibernate 3 - spring

I am using Spring MVC + Hibernate and try to save bulk record using "hibernate batch procession technique" but getting below exception when I am doing session.flush() and session.clear().
org.hibernate.LazyInitializationException: could not initialize proxy - no Session
following is my code sample
DaoImpl method
#SuppressWarnings("unchecked")
#Override
public String transferPsalesDataToMisSales() {
Session session = null;
Transaction tx=null;
String result="failed";
try {session = this.getSessionFactory().openSession();
tx = session.beginTransaction();
Criteria criteria=session.createCriteria(PsalesInfo.class);
List<PsalesInfo> pSalesData=criteria.list();
if(pSalesData.size() >0){
Iterator<PsalesInfo> it=pSalesData.iterator();
int index=0;
MisSalesInfo mis=null;
while(it.hasNext()){
mis=new MisSalesInfo();
PsalesInfo psales=it.next();
StockistInfo stockistInfo=psales.getStockistInfo();
TalukaInfo talukaInfo=stockistInfo.getTalukaInfo();
IsrInfo isr=(IsrInfo) session.get(IsrInfo.class, stockistInfo.getIsrId());
//mis settters
mis.setMisSalesId(psales.getPsalesId());
mis.setStateName(talukaInfo.getDistrictInfo().getStateInfo().getStateName());
mis.setDistName(talukaInfo.getDistrictInfo().getDistName());
mis.setTalukaName(talukaInfo.getTalukaName());
mis.setAsmId(talukaInfo.getAsmInfo().getAsmId());
mis.setTsoId(stockistInfo.getTsoInfo().getTsoId());
if(null!=isr){
mis.setIsrId(isr.getIsrId());
mis.setIsrName(isr.getIsrName());
}
mis.setUnitNo(stockistInfo.getUnitNo());
mis.setBillNo(psales.getBillNo());
session.save(mis);
if(index % 50==0){
//flush a batch of inserts and release memory:
session.flush();
session.clear();
}
index++;
}//end of while
tx.commit();
result=pSalesData.size()+" Psales are Successfully transfered to MIS Sales";
}
else{
result="No Psales is available to transfer since are already available in MIS Sales";
}
} catch (HibernateException e) {
tx.rollback();
logger.error("error in MasterDaoImpl transfer data:"+e);
}finally {
if (null != session)
session.close();
}
return result;
}
POJOs
#Entity
#Table(name = "psales_info", catalog = "secondary_sales")
public class PsalesInfo implements java.io.Serializable {
private static final long serialVersionUID = 5578632011679493005L;
private Integer psalesId;
private StockistInfo stockistInfo;
//and some other attributes
//getter and setters
#Id
#GenericGenerator(name="generator", strategy="increment")
#GeneratedValue(generator="generator")
#Column(name = "psales_id", unique = true, nullable = false)
public Integer getPsalesId() {
return this.psalesId;
}
public void setPsalesId(Integer psalesId) {
this.psalesId = psalesId;
}
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "pcode", nullable = false)
public StockistInfo getStockistInfo() {
return this.stockistInfo;
}
//and others
#Entity
#Table(name = "stockist_info", catalog = "secondary_sales")
public class StockistInfo implements java.io.Serializable {
private String stockistId;
private TalukaInfo talukaInfo;
//and rest attributes
//getters and setters
// Property accessors
#Id
#Column(name = "stockist_id", unique = true, nullable = false, length = 10)
public String getStockistId() {
return this.stockistId;
}
public void setStockistId(String stockistId) {
this.stockistId = stockistId;
}
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "taluka_sid", nullable = false)
public TalukaInfo getTalukaInfo() {
return this.talukaInfo;
}
ServiceImpl
#Service
#Transactional
public class TransactionServiceImpl implements TransactionService {
#Autowired
private TransactionDAO transactionDAO;
#Override
public String transferPsalesDataToMisSales() {
return this.getTransactionDAO().transferPsalesDataToMisSales();
}
}
dispature-servlet.xml
<bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource"></property>
<property name="configLocation" value="classpath:hibernate.cfg.xml"/>
<property name="configurationClass" value="org.hibernate.cfg.AnnotationConfiguration"/>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">${hibernate.dialect}</prop>
<prop key="hibernate.show_sql">${hibernate.show_sql}</prop>
<prop key="hibernate.hbm2ddl.auto">${hibernate.hbm2ddl.auto}</prop>
<prop key="hibernate.default_catalog">${hibernate.default_catalog}</prop>
<prop key="hibernate.jdbc.batch_size">50</prop>
</props>
</property>
</bean>
<tx:annotation-driven transaction-manager="transactionManager"/>
<bean id="transactionManager"
class="org.springframework.orm.hibernate3.HibernateTransactionManager"
p:sessionFactory-ref="sessionFactory"/>
Need help here why it is throwing LazyInitializationException when I'm clearing the session.
But when I'm not clearing the session ie. wihtout session.clear() and session.flush() application is running properly.
but I know it may lead to OutOfMemoryException in case of more bulk record.
so plz tell how to deal with this situation now?

Your dao code is flawed... Don't open new sessions yourself and don't mess aroudn with transactions yourself either. Remove the transaction stuff from your dao method and the call to openSession should be replaced with getCurrentSession.
#SuppressWarnings("unchecked")
#Override
public String transferPsalesDataToMisSales() {
Session session = this.getSessionFactory().getCurrentSession();
Criteria criteria=session.createCriteria(PsalesInfo.class);
List<PsalesInfo> pSalesData=criteria.list();
int index=0;
for (PsalesInfo psales : pSalesData) {
MisSalesInfo mis=new MisSalesInfo();
StockistInfo stockistInfo=psales.getStockistInfo();
TalukaInfo talukaInfo=stockistInfo.getTalukaInfo();
IsrInfo isr=(IsrInfo) session.get(IsrInfo.class, stockistInfo.getIsrId());
//mis settters
mis.setMisSalesId(psales.getPsalesId());
mis.setStateName(talukaInfo.getDistrictInfo().getStateInfo().getStateName());
mis.setDistName(talukaInfo.getDistrictInfo().getDistName());
mis.setTalukaName(talukaInfo.getTalukaName());
mis.setAsmId(talukaInfo.getAsmInfo().getAsmId());
mis.setTsoId(stockistInfo.getTsoInfo().getTsoId());
if(null!=isr){
mis.setIsrId(isr.getIsrId());
mis.setIsrName(isr.getIsrName());
}
mis.setUnitNo(stockistInfo.getUnitNo());
mis.setBillNo(psales.getBillNo());
session.save(mis);
if(index % 50==0){
//flush a batch of inserts and release memory:
session.flush();
session.clear();
}
index++;
}//end of loop
if (pSalesData.isEmpty() ) {
return "No Psales is available to transfer since are already available in MIS Sales";
} else {
return pSalesData.size()+" Psales are Successfully transfered to MIS Sales";
}
}

Related

Spring JPA with Eclipselink save operation does not persist

I've been trying for some couple of days now I just can't seem to figure out why my Eclipselink persistence unit does not perform write operations on my DB. We used to be running OpenJPA and everything was working fine, but with the new EclipseLink config, only thing entities are capable of doing is read data. Write operations do not occur. I'm hoping someone with a better understanding of this can help me out. Maybe I'm missing something.
This is my persistence.xml
<persistence version="2.0"
xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd">
<persistence-unit name="EclipseLink-PU" transaction-type="RESOURCE_LOCAL">
<provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
<exclude-unlisted-classes>false</exclude-unlisted-classes>
<shared-cache-mode>ALL</shared-cache-mode>
<properties>
<!--
<property name="eclipselink.ddl-generation.output-mode" value="database"/>
<property name="eclipselink.target-database" value="org.eclipse.persistence.platform.database.MySQLPlatform" />
Optimization - avoid auto flush cost on query execution -->
<!-- property name="eclipselink.batch.size" value="100"/-->
<property name="javax.persistence.validation.group.pre-persist" value=""/>
<property name="javax.persistence.validation.group.pre-update" value="none"/>
<property name="eclipselink.cache.shared.default" value="false"/>
<property name="eclipselink.persistence-context.close-on-commit" value="true"/>
<property name="eclipselink.persistence-context.flush-mode" value="commit"/>
<property name="eclipselink.weaving" value="static"/>
<property name="eclipselink.logging.level" value="ALL"/>
<property name="eclipselink.logging.parameters" value="true"/>
<property name="eclipselink.logging.level.sql" value="ALL"/>
<property name="eclipselink.logging.thread" value="true"/>
<property name="eclipselink.jdbc.batch-writing" value="JDBC"/>
</properties>
</persistence-unit>
My infrastructure.xml with configs for transactionManager
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:jdbc="http://www.springframework.org/schema/jdbc"
xmlns:jee="http://www.springframework.org/schema/jee"
xsi:schemaLocation="http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc-3.0.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-3.0.xsd">
<!-- Necessary to get the entity manager injected into the factory bean -->
<bean class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor" />
<!-- Define EclipseLink JPA Vendor Adapter -->
<bean id="eclipseLinkAdapter"
class="org.springframework.orm.jpa.vendor.EclipseLinkJpaVendorAdapter">
<property name="generateDdl" value="false" />
<property name="showSql" value="true" />
</bean>
<bean id="entityManagerFactory"
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"
depends-on="tenantDatabaseUpgradeService">
<property name="dataSource" ref="routingDataSource" />
<property name="persistenceUnitName" value="EclipseLink-PU" />
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.EclipseLinkJpaVendorAdapter">
<property name="generateDdl" value="false" />
<property name="showSql" value="true" />
<property name="databasePlatform" value="org.eclipse.persistence.platform.database.MySQLPlatform"/>
</bean>
</property>
<!--
<property name="loadTimeWeaver">
<bean class="org.springframework.instrument.classloading.InstrumentationLoadTimeWeaver" />
<bean class="org.springframework.instrument.classloading.tomcat.TomcatLoadTimeWeaver" />
</property>-->
</bean>
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory"/>
</bean>
<!-- Create instance of transaction template for programmatic transaction manipulation -->
<bean id="txTemplate" class="org.springframework.transaction.support.TransactionTemplate">
<property name="transactionManager" ref="transactionManager"/>
</bean>
Here I have a sample entity I want to persist
#Entity
#Table(name = "m_office", uniqueConstraints = { #UniqueConstraint(columnNames = { "name" }, name = "name_org"),
#UniqueConstraint(columnNames = { "external_id" }, name = "externalid_org") })
public class Office extends AbstractPersistableCustom implements Serializable {
#OneToMany(fetch = FetchType.LAZY)
#JoinColumn(name = "parent_id")
private List<Office> children = new LinkedList<>();
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "parent_id")
private Office parent;
#Column(name = "name", nullable = false, length = 100)
private String name;
#Column(name = "hierarchy", nullable = true, length = 50)
private String hierarchy;
#Column(name = "opening_date", nullable = false)
#Temporal(TemporalType.DATE)
private Date openingDate;
#Column(name = "external_id", length = 100)
private String externalId;
public static Office headOffice(final String name, final LocalDate openingDate, final String externalId) {
return new Office(null, name, openingDate, externalId);
}
public static Office fromJson(final Office parentOffice, final JsonCommand command) {
final String name = command.stringValueOfParameterNamed("name");
final LocalDate openingDate = command.localDateValueOfParameterNamed("openingDate");
final String externalId = command.stringValueOfParameterNamed("externalId");
return new Office(parentOffice, name, openingDate, externalId);
}
protected Office() {
this.openingDate = null;
this.parent = null;
this.name = null;
this.externalId = null;
}
private Office(final Office parent, final String name, final LocalDate openingDate, final String externalId) {
this.parent = parent;
this.openingDate = openingDate.toDateTimeAtStartOfDay().toDate();
if (parent != null) {
this.parent.addChild(this);
}
if (StringUtils.isNotBlank(name)) {
this.name = name.trim();
} else {
this.name = null;
}
if (StringUtils.isNotBlank(externalId)) {
this.externalId = externalId.trim();
} else {
this.externalId = null;
}
}
private void addChild(final Office office) {
this.children.add(office);
}
public Map<String, Object> update(final JsonCommand command) {
final Map<String, Object> actualChanges = new LinkedHashMap<>(7);
final String dateFormatAsInput = command.dateFormat();
final String localeAsInput = command.locale();
final String parentIdParamName = "parentId";
if (command.parameterExists(parentIdParamName) && this.parent == null) { throw new RootOfficeParentCannotBeUpdated(); }
if (this.parent != null && command.isChangeInLongParameterNamed(parentIdParamName, this.parent.getId())) {
final Long newValue = command.longValueOfParameterNamed(parentIdParamName);
actualChanges.put(parentIdParamName, newValue);
}
final String openingDateParamName = "openingDate";
if (command.isChangeInLocalDateParameterNamed(openingDateParamName, getOpeningLocalDate())) {
final String valueAsInput = command.stringValueOfParameterNamed(openingDateParamName);
actualChanges.put(openingDateParamName, valueAsInput);
actualChanges.put("dateFormat", dateFormatAsInput);
actualChanges.put("locale", localeAsInput);
final LocalDate newValue = command.localDateValueOfParameterNamed(openingDateParamName);
this.openingDate = newValue.toDate();
}
final String nameParamName = "name";
if (command.isChangeInStringParameterNamed(nameParamName, this.name)) {
final String newValue = command.stringValueOfParameterNamed(nameParamName);
actualChanges.put(nameParamName, newValue);
this.name = newValue;
}
final String externalIdParamName = "externalId";
if (command.isChangeInStringParameterNamed(externalIdParamName, this.externalId)) {
final String newValue = command.stringValueOfParameterNamed(externalIdParamName);
actualChanges.put(externalIdParamName, newValue);
this.externalId = StringUtils.defaultIfEmpty(newValue, null);
}
return actualChanges;
}
public boolean isOpeningDateBefore(final LocalDate baseDate) {
return getOpeningLocalDate().isBefore(baseDate);
}
public boolean isOpeningDateAfter(final LocalDate activationLocalDate) {
return getOpeningLocalDate().isAfter(activationLocalDate);
}
public LocalDate getOpeningLocalDate() {
LocalDate openingLocalDate = null;
if (this.openingDate != null) {
openingLocalDate = LocalDate.fromDateFields(this.openingDate);
}
return openingLocalDate;
}
public void update(final Office newParent) {
if (this.parent == null) { throw new RootOfficeParentCannotBeUpdated(); }
if (identifiedBy(newParent.getId())) { throw new CannotUpdateOfficeWithParentOfficeSameAsSelf(getId(), newParent.getId()); }
this.parent = newParent;
generateHierarchy();
}
public boolean identifiedBy(final Long id) {
return getId().equals(id);
}
public void generateHierarchy() {
if (this.parent != null) {
this.hierarchy = this.parent.hierarchyOf(getId());
} else {
this.hierarchy = ".";
}
}
private String hierarchyOf(final Long id) {
return this.hierarchy + id.toString() + ".";
}
public String getName() {
return this.name;
}
public String getHierarchy() {
return this.hierarchy;
}
public Office getParent() {
return this.parent;
}
public boolean hasParentOf(final Office office) {
boolean isParent = false;
if (this.parent != null) {
isParent = this.parent.equals(office);
}
return isParent;
}
public boolean doesNotHaveAnOfficeInHierarchyWithId(final Long officeId) {
return !hasAnOfficeInHierarchyWithId(officeId);
}
private boolean hasAnOfficeInHierarchyWithId(final Long officeId) {
boolean match = false;
if (identifiedBy(officeId)) {
match = true;
}
if (!match) {
for (final Office child : this.children) {
final boolean result = child.hasAnOfficeInHierarchyWithId(officeId);
if (result) {
match = result;
break;
}
}
}
return match;
}
public void loadLazyCollections() {
this.children.size() ;
}
}
Any help will be much appreciated.
Using saveAndFlush where appropriate did the trick for me.

Setter Dependency Injection with Array of String

To test the setter dependency injection with an Array of string, I wrote the below-given code -
Pojo class is -
package com.abhishek.ioc.array;
public class Person {
private int id;
private String name;
private String[] hobbies;
public void showHobbies() {
System.out.println("Person name is - "+name+", id is - "+id);
for (int i = 0; i < hobbies.length; i++) {
System.out.println(hobbies[i]);
}
}
public void setId(int id) {
this.id = id;
}
public void setName(String name) {
this.name = name;
}
public void setHobbies(String[] hobbies) {
this.hobbies = hobbies;
}
}
spring.xml file is -
<beans>
<bean id="person" class="com.abhishek.ioc.array.Person">
<property name="id" value="1"></property>
<property name="name" value="Abhisshek"></property>
<property name="hobbies">
<set>
<value>Playing cricket</value>
<value>Coding</value>
<value>Reading books</value>
</set>
</property>
</bean>
</beans>
Client code is -
package com.abhishek.ioc.array;
public class Client {
public static void main(String[] args) {
ApplicationContext applicationContext=new ClassPathXmlApplicationContext("resources/spring.xml");
System.out.println("Creating Person object");
Person person = (Person)applicationContext.getBean("person");
System.out.println("Person object created");
person.showHobbies();
}
}
In spring.xml file, I tried tags <array>, <list> and <set> to inject data in array and all three tags are giving the correct result. How?

Hibernate Oracle Create table

I have a problem while creating table in oracle via hibernate.
I get these two error:
Could not execute JDBC batch update
and
ORA-00942: table or view does not exist
This is my hibernate.cfg.xml
<hibernate-configuration>
<session-factory>
<property name="hibernate.connection.driver_class">oracle.jdbc.driver.OracleDriver</property>
<property name="hibernate.connection.url">jdbc:oracle:thin:#localhost:1521:ORCL</property>
<property name="hibernate.connection.username">system</property>
<property name="hibernate.connection.password">mypass</property>
<property name="hibernate.dialect">org.hibernate.dialect.Oracle10gDialect</property>
<property name="hibernate.default_schema">SamTest</property>
<property name="hibernate.connection.pool_size">5</property>
<property name="show_sql">true</property>
<property name="hibernate.hbm2ddl.auto">update</property>
<mapping class="com.sam.Teacher" />
</session-factory>
</hibernate-configuration>
Teacher entity
#Table(schema="SamTest")
public class Teacher {
#Id
//#GenericGenerator(name = "generator", strategy = "increment")
private int teacher_Id;
#Column
private int teacher_No;
#Column
private String teacher_Name;
#Column
private String teacher_Surname;
#Column
private String department;
public String getDepartment() {
return department;
}
public void setDepartment(String department) {
this.department = department;
}
public int getTeacher_Id() {
return teacher_Id;
}
public void setTeacher_Id(int teacher_Id) {
this.teacher_Id = teacher_Id;
}
public int getTeacher_No() {
return teacher_No;
}
public void setTeacher_No(int teacher_No) {
this.teacher_No = teacher_No;
}
public String getTeacher_Name() {
return teacher_Name;
}
public void setTeacher_Name(String teacher_Name) {
this.teacher_Name = teacher_Name;
}
public String getTeacher_Surname() {
return teacher_Surname;
}
public void setTeacher_Surname(String teacher_Surname) {
this.teacher_Surname = teacher_Surname;
}
public Teacher() {
}
public Teacher(int teacher_No, String teacher_Name, String teacher_Surname, String department) {
this.teacher_No = teacher_No;
this.teacher_Name = teacher_Name;
this.teacher_Surname = teacher_Surname;
this.department=department;
}
}
Exception
Exception in thread "main" org.hibernate.exception.SQLGrammarException: Could not execute JDBC batch update
at org.hibernate.exception.SQLStateConverter.convert(SQLStateConverter.java:92)
at org.hibernate.exception.JDBCExceptionHelper.convert(JDBCExceptionHelper.java:66)
at org.hibernate.jdbc.AbstractBatcher.executeBatch(AbstractBatcher.java:275)
at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:268)
at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:184)
at org.hibernate.event.def.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:321)
at org.hibernate.event.def.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:51)
at org.hibernate.impl.SessionImpl.flush(SessionImpl.java:1216)
at org.hibernate.impl.SessionImpl.managedFlush(SessionImpl.java:383)
at org.hibernate.transaction.JDBCTransaction.commit(JDBCTransaction.java:133)
at com.sam.RunHiber.main(RunHiber.java:23)
Caused by: java.sql.BatchUpdateException: ORA-00942: table or view does not exist
at oracle.jdbc.driver.OraclePreparedStatement.executeBatch(OraclePreparedStatement.java:10500)
at oracle.jdbc.driver.OracleStatementWrapper.executeBatch(OracleStatementWrapper.java:230)
at org.hibernate.jdbc.BatchingBatcher.doExecuteBatch(BatchingBatcher.java:70)
at org.hibernate.jdbc.AbstractBatcher.executeBatch(AbstractBatcher.java:268)
... 8 more
It appears you're creating getters and setters in Hibernate, but I'm pretty sure you're not creating a table. This is only the reference to an Oracle table that obviously does not exist (yet). Hence the error "Table or view does not exists".

HttpMessageConverter not found in Spring restTemplate

I have got error when I retrieve JSON using String restTempate. Error says
Could not extract response: no suitable HttpMessageConverter found for response type [class au.org.jeenee.mdm.models.PhoneResponse] and content type [application/json]
at org.springframework.web.client.HttpMessageConverterExtractor.extractData(HttpMessageConverterExtractor.java:107)
at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:492)
at org.springframework.web.client.RestTemplate.execute(RestTemplate.java:447)
at org.springframework.web.client.RestTemplate.postForObject(RestTemplate.java:295)
at au.org.jeenee.mdm.services.EccClientServiceImpl.findPhoneByImei(EccClientServiceImpl.java:51)
at au.org.jeenee.mdm.controllers.DeviceController.showEditForm(DeviceController.java:308)
I found out the message means there is no JSON converter registered but I have Jackson message converter in my xml.
applicationContext.xml
<bean id="jacksonMessageConverter"
class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter" />
<bean
class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
<property name="messageConverters">
<list>
<ref bean="jacksonMessageConverter" />
</list>
</property>
</bean>
<bean id="restTemplate" class="org.springframework.web.client.RestTemplate">
<constructor-arg>
<bean class="org.springframework.http.client.HttpComponentsClientHttpRequestFactory">
<constructor-arg ref="httpClient"/>
</bean>
</constructor-arg>
<property name="messageConverters">
<list>
<ref bean="jacksonMessageConverter" />
</list>
</property>
</bean>
And here is my code to use RestTemplate.
public class MyRestClientService {
#Override
public List<DeviceHolder> findDeviceHoldersByUserId(String userId) {
String uri = "/web/getpersonlist?userId=" + userId;
try {
DeviceHolderResponse response = restClient.getRestTemplate().postForObject(restClient.createUrl(uri), "", DeviceHolderResponse.class);
if (response!=null && response.isOk() && response.getResult()!=null){
DeviceHolder[] deviceHolders = response.getResult();
return Arrays.asList(deviceHolders);
}
} catch (Exception e) {
e.printStackTrace();
}
return Collections.emptyList();
}
#Override
public Phone findPhoneByImei(String imei) {
log.info("findPhoneByImei:" + imei);
Phone phone = null;
String uri = "/ecc/getphoneplan?imei=" + imei;
try {
PhoneResponse response = restClient.getRestTemplate().postForObject(restClient.createUrl(uri), "", PhoneResponse.class);
if (response.getResult()!=null)
phone = response.getResult();
} catch (Exception e) {
e.printStackTrace();
}
return phone;
}
}
PhoneResponse.java
public class Phone implement Serializable {
private boolean ok;
private String message;
private Phone result;
//getters and setters
}
Phone.java
public class Phone implements Serializable {
#JsonProperty(value="phoneid")
private long phoneId;
private Plan plan;
private String sim;
private String imei;
#JsonProperty(value="phonetype")
private String phoneType;
#JsonProperty(value="phonenumber")
private String phoneNumber;
private String label;
#JsonProperty(value="connecteddate")
private String connectedDate;
//getters and setters
}
Plan.java
public class Plan implements Serializable {
#JsonProperty(value="planid")
private long planId;
#JsonProperty(value="planname")
private String planName;
private double billingIncrement;
private double owiStdUnitCost;
private double owiFlagFall;
private double stdCap;
private double dataCap;
private double smsCap;
private double owiDataUnitCost;
private double owiSms;
//getters and setters
}
And the response packet is like following:
{
"ok": true,
"message": "",
"result":
{
"phoneid": 600003,
"phonenumber": 478439503,
"phonetype": "Samsung Galaxy S2",
"imei": "1111111111",
"sim": "1111111111",
"label": "Person name",
"connecteddate": "2012-09-19 00:00:00.0",
"plan":
{
"planid": 34,
"planname": "$59 Plan",
"billingIncrement": 30,
"owiStdUnitCost": 81.8181818181818,
"owiFlagFall": 0,
"stdCap": 636.3636,
"dataCap": 227.2665,
"smsCap": 1363.638,
"owiDataUnitCost": 0.022194,
"owiSms": 22.7272727272727
}
}
}
Strangely, there is no error when I call findDeviceHoldersByUserId method but error for findPhoneByImei method. And this has been working up to just before.
I tried again and again but I still have the error. Please help to fix the problem.
Thanks.
Couple of reasons, I found, that can cause this issue are -
Data type of the setters/getters are different from that of the actual properties (also mentioned in comment of sunghun)
If there are overloaded methods that may look like setter/getter of a field - same name as setField or getField where field is a property of the class.
I had a field private boolean success and 2 setter methods -
public void setSuccess(List<Object> dataList);
public void setSuccess(boolean success);
On debugging, I found that class com.fasterxml.jackson.databind.deser.BeanDeserializerFactory was throwing an exception. This exception was suppressed within Jackson's lib and the exception thrown by the RestTemplate was the same as the subject.
java.lang.IllegalArgumentException: Conflicting setter definitions for property "failure": com.test.dto.JsonResponse#setFailure(1 params) vs com.test.dto.JsonResponse#setFailure(1 params)
I changed the method to public void setSuccessData(List<Object> dataList); and it worked fine.
Hope this helps someone.

Multi Transaction Manager Spring Configuration with Annotations

There are two bean JpaTransactionManager.
Can Manage them with Qualifier notation.
<bean id="transactionManagerConstant" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="constant"/>
<qualifier value="first"/>
</bean>
<bean id="transactionManagerRelative" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="relative"/>
<qualifier value="second"/>
</bean>
Java code:
#Transactional("first")
public String saveWork(){
em1.persist(work);
work = (Work) ctx.getBean("work");
return "/workLists.xhtml";
}
#Transactional("second")
public String saveEvent(){
em2.persist(event);
event = (Event) ctx.getBean("event");
return "/eventLists.xhtml";
}
The problem is: how do I use the level of isolation or readOnly assignment? #Qualifier annotations does not work:
#Transactional(isolation = Isolation.SERIALIZABLE, propagation=Propagation.REQUIRED, readOnly = false)
#Qualifier("first")
public String saveWork(){
em1.persist(work);
work = (Work) ctx.getBean("work");
return "/workLists.xhtml";
}
#Transactional(isolation = Isolation.SERIALIZABLE, propagation=Propagation.REQUIRED, readOnly = false)
#Qualifier("second")
public String saveEvent(){
em2.persist(event);
event = (Event) ctx.getBean("event");
return "/eventLists.xhtml";
}
How can I solve this problem?
You should be putting the #Qualifier annotation on the member that is the TransactionManager, not on the method that uses it.
The following assumes that em1 and em2 are the TransactionManager's defined in the spring configuration above.
#Autowired
#Qualifier("first")
private TransactionManager em1;
#Autowired
#Qualifier("second")
private TransactionManager em2;
#Transactional(isolation = Isolation.SERIALIZABLE, propagation=Propagation.REQUIRED, readOnly = false)
public String saveWork(){
em1.persist(work);
work = (Work) ctx.getBean("work");
return "/workLists.xhtml";
}
#Transactional(isolation = Isolation.SERIALIZABLE, propagation=Propagation.REQUIRED, readOnly = false)
public String saveEvent(){
em2.persist(event);
event = (Event) ctx.getBean("event");
return "/eventLists.xhtml";
}

Resources