Multi Transaction Manager Spring Configuration with Annotations - spring

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";
}

Related

populate enum fields with application.properties and java configuration

with spring xml configuration, it is possible to define the following in app context xml to populate the status field in the TestEnum:
app context xml
<bean id="blue" class="com.example.demo.test.TestEnum" factory-method="valueOf">
<property name="status" value="${testnum.blue.status}"/>
<constructor-arg>
<value>BLUE</value>
</constructor-arg>
</bean>
<bean id="red" class="com.example.demo.test.TestEnum" factory-method="valueOf">
<property name="status" value="${testnum.red.status}"/>
<constructor-arg>
<value>RED</value>
</constructor-arg>
</bean>
enum class
public enum TestEnum {
BLUE,
RED;
private String status;
public String getStatus() {
return status;
}
public void setStatus(String status) {
this.status = status;
}
}
mystatus.properties
testnum.blue.status=good
testnum.red.status=bad
Is this possible with spring boot using application.properties + java configuration without xml?
Yes, a simple environment configuration class (annotated with #ConfigurationProperties for example), will map and do the conversion of your enum automatically.
Example:
#Configuration
#Validated
#ConfigurationProperties(prefix = "my.property.path")
public class TestConfiguration{
public enum TestEnum {
BLUE, RED
}
#NotNull
private TestEnum type;
public TestConfiguration() {
}
public #NotNull TestEnum getType() {
return this.type;
}
public void setType(#NotNull TestEnum type) {
this.type = type;
}
}

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.

Batch insertion with Spring MVC and Hibernate 3

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";
}
}

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.

How should I use #CachePut and #CacheEvict annotations with ehCache (ehCache 2.4.4, Spring 3.1.1)

I tried some new Spring features and I found out that #CachePut and #CacheEvict annotations has no effect. May be I do something wrong. Could you help me?
My applicationContext.xml.
<cache:annotation-driven />
<!--also tried this-->
<!--<ehcache:annotation-driven />-->
<bean id="cacheManager"
class="org.springframework.cache.ehcache.EhCacheCacheManager"
p:cache-manager-ref="ehcache"/>
<bean id="ehcache"
class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean"
p:config-location="classpath:ehcache.xml"/>
This part works well.
#Cacheable(value = "finders")
public Finder getFinder(String code)
{
return getFinderFromDB(code);
}
#CacheEvict(value = "finders", allEntries = true)
public void clearCache()
{
}
But if I want remove single value from cache or override it I can't do that. What I tested:
#CacheEvict(value = "finders", key = "#finder.code")
public boolean updateFinder(Finder finder, boolean nullValuesAllowed)
{
// ...
}
/////////////
#CacheEvict(value = "finders")
public void clearCache(String code)
{
}
/////////////
#CachePut(value = "finders", key = "#finder.code")
public Finder updateFinder(Finder finder, boolean nullValuesAllowed)
{
// gets newFinder that is different
return newFinder;
}
I found the reason why it didn't work. I called this methods from other method in the same class. So this calls didn't get through Proxy object therefore the annotations didn't work.
Correct example:
#Service
#Transactional
public class MyClass {
#CachePut(value = "finders", key = "#finder.code")
public Finder updateFinder(Finder finder, boolean nullValuesAllowed)
{
// gets newFinder
return newFinder;
}
}
and
#Component
public class SomeOtherClass {
#Autowired
private MyClass myClass;
public void updateFinderTest() {
Finder finderWithNewName = new Finder();
finderWithNewName.setCode("abc");
finderWithNewName.setName("123");
myClass.updateFinder(finderWithNewName, false);
}
}

Resources