#Transactional annotation doesn't work - java

ok, enough. I couldn't make this work. I am a newbie to Spring transactions and using the #Transactional annotation in my service to manage transactions. Below is my spring bean configuration file.
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:jee="http://www.springframework.org/schema/jee"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-2.0.xsd">
<tx:annotation-driven transaction-manager="txManager"/>
<bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
<jee:jndi-lookup id="dataSource" jndi-name="jdbc/myapp"/>
<!-- other <bean/> definitions here -->
</beans>
and I annotate my service:
#Transactional
public class MyServiceImpl implements MyService {
...
}
I notice two things
The connection that I get in my DAO [using DataSourceUtils.getConnection(dsName)] has the autocommit enabled [true].
As far as I debugged there doesn't look to be any transaction that has begun during my service method invocation.
Anyone had this problem?

I use Hibernate with the HibernateTransactionManager myself, so I'm not too familiar with how the JDBC transaction manager works. Have you inspected the callstack to see whether or not TransactionInterceptor is in there ? If it is, then the transactional annotation is working, and you may just be missing something else. If you haven't looked for it, what makes you think that it's not working ? To eliminate the obvious, have you explicitly set a setting in your JDBC configuration to disable autocommit ?

Related

Cache interceptor call is ignored

I am working on cache implementation (exstremescale)for maven multi module project, where i have added below maven dependency
<dependency>
<groupId>com.ibm.extremescale</groupId>
<artifactId>ogclient</artifactId>
<version>8.6.0.20150901-215917</version>
</dependency>
Added caching annotation on
#Override
#Cacheable(value = "productDetails", key = "#productId + #orgId")
public Product productRead(final String productId, final String productKey, final String orgId, final CRApplicationEnum sourceSystem) throws IntegrationException {
cache-manager.xml
<?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
xmlns:cache="http://www.springframework.org/schema/cache"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/cache http://www.springframework.org/schema/cache/spring-cache.xsd">
<cache:annotation-driven />
<bean id="cacheManager" class="org.springframework.cache.support.SimpleCacheManager" primary="true">
<property name="caches">
<set>
<bean class="com.ibm.websphere.objectgrid.spring.ObjectGridCache"
p:name="eventDetails" p:map-name="${iev.eventDetails.mapName}"
p:object-grid-client-ref="wxsGridClient" />
<bean class="com.ibm.websphere.objectgrid.spring.ObjectGridCache"
p:name="eventValidationDetails" p:map-name="${iev.eventValidationDetails.mapName}"
p:object-grid-client-ref="wxsGridClient" />
<bean class="com.ibm.websphere.objectgrid.spring.ObjectGridCache"
p:name="productDetails" p:map-name="${ipr.productDetails.mapName}"
p:object-grid-client-ref="wxsGridClient" />
</set>
</property>
</bean>
<bean id="wxsCSDomain"
class="com.ibm.websphere.objectgrid.spring.ObjectGridCatalogServiceDomainBean"
p:catalog-service-endpoints="${xscale.catalogServiceEndpoint}" />
<bean id="wxsGridClient"
class="com.ibm.websphere.objectgrid.spring.ObjectGridClientBean"
p:catalog-service-domain-ref="wxsCSDomain" p:objectGridName="${wxs.objectGridName}" />
Caching is working for only one maven module of the project, i can see the cache interceptor call and for rest of the maven module it is ignoring the #cacheable annotation(it is not going to the interceptor).
We dont have PostConstructor or Self invokation
We are using atomikos as transaction manager and CXF -interceptors which will be executed before coming to caching methods.
Please help me on this
Your comment about JdkDynamixAopProxy and looking at the code makes me think that the method you have annotated with #Cacheable is in a concrete class. And for the annotation on a concrete class to exhibit proper behavior; you need to enable the cglib proxying in your application.
This can be done by adding proxy target class parameter to your cache annotation driven tag.
<cache:annotation-driven proxy-target-class="true"/>
If you dont want to enable class based proxying for your overall application; you can specify the behavior for a particular class by annotating it with this annotation:
#Scope(proxyMode = ScopedProxyMode.TARGET_CLASS)
Calling methods in the same class bypasses the dynamic proxy and any cross cutting concern like caching, transaction etc which is part of the dynamic proxies logic is also bypassed. So could your problem be Spring cache #Cacheable method ignored when called from within the same class ?
If so, the fix is to use AspectJ compile time or load time weaving.

Autowired spring bean null for cacheManager using ehcache spring annotations

I'm still new to spring and I'm trying to get ehcache spring annotations setup correctly. I'm using Spring 3.2.3 ehCache 2.4 and ehcache-spring-annotations-1.2.
When I try to access the reference to the cacheManager, it is always null. All the jars are on the build path, ehcache.xml is in the classpath and there are no xml errors. I've tried also including the classes in the component scan and using #Resource instead of Autowired. I'm stuck!
Application context:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:ehcache="http://ehcache-spring-annotations.googlecode.com/svn/schema/ehcache-spring"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://ehcache-spring-annotations.googlecode.com/svn/schema/ehcache-spring
ehcache-spring-1.1.xsd">
<context:component-scan base-package="org.springframework.cache.ehcache.EhCacheManagerFactoryBean,com .defaultPackage,net.sf.ehcache.CacheManager" />
<!-- ehCache Annotation settings -->
<ehcache:annotation-driven cache-manager="ehCacheManager" />
<bean id="ehCacheManager" class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean">
<property name="configLocation" value="classpath:ehcache.xml" />
<property name="shared" value="true"/>
</bean>
Wrapper
#Component
public final class MyCache implements Serializable {
#Autowired
private CacheManager ehCacheManager;
private getCacheManager() {
return ehCacheManger; // this is always null
}...}
It seems you are trying to use the EhCacheManagerFactoryBean as your cache manager.
Looking at Spring caching documentation, you need to declare another bean to be your CacheManager created from the factory.

Mbean JMX Spring Framework

I have a web application which has more than 40 Mbean. I used Spring Framework.
I am doing good and its working well. But i have 40 Mbean, so want to generalize the thing.
#Component
#ManagedResource(objectName="ProjectCache:name=XMBean", log=true, logFile="jmx.log")
public class XMBean extends AbstractCacheMBean<String, XCO, XCache> {
#ManagedOperation(description ="ProjectCache XCO key")
#Override
public List<String> showAllKeys(){
return super.getKey();
}
#ManagedOperation(description ="ProjectCache XCO")
public List<String> showAllElements(){
return super.findAll();
}
#Override
public XCache getCache() {
return getFacadeCache().getXCache();
}
#ManagedOperation(description ="ProjectCache XCO by key)
#Override
public String ShowbyKey(String key) {
return super.findbyKey(key);
}
}
Now i have Same way Class YMbean, AMBean and so.
I configured the Spring in application mbean.xml.
<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/beans"
xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:jee="http://www.springframework.org/schema/jee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/jee
http://www.springframework.org/schema/jee/spring-jee.xsd">
<!-- this bean must not be lazily initialized if the exporting is to happen -->
<bean id="exporter" class="org.springframework.jmx.export.MBeanExporter" lazy-init="false">
<property name="server" ref="mbeanServer"/>
<property name="assembler" ref="assembler" />
<property name="namingStrategy" ref="namingStrategy" />
</bean>
<bean id="jmxAttributeSource" class="org.springframework.jmx.export.annotation.AnnotationJmxAttributeSource" />
<!-- will create management interface using annotation metadata -->
<bean id="assembler" class="org.springframework.jmx.export.assembler.MetadataMBeanInfoAssembler">
<property name="attributeSource" ref="jmxAttributeSource" />
</bean>
<!-- will pick up the ObjectName from the annotation -->
<bean id="namingStrategy" class="org.springframework.jmx.export.naming.MetadataNamingStrategy">
<property name="attributeSource" ref="jmxAttributeSource" />
</bean>
<bean id="xMBean"
class="in.projet.business.mbean.XMBean">
<property name="memoryCache" ref="repository" />
</bean>
And same way i am going to preapre YMbean Class and in xml going to initialise.
What should i do that not require modification in XML Whatsoever or number of class i create ,dont require to update XML.
property is same in all Mbean which i am going to use.
All ideas or input are welcome.
Thanks
Remove all of your configuration and replace with the use of the namespace and only once. Also your MBeans are #Components so you can simply scan for them. Which only would leave you with the following lines of xml
<context:component-scan base-package="in.projet.business.mbean" />
<context:mbean-export/>
Or if you want to keep your current configuration instead of the namespace replace it at least with the following and remove all other beans. This enables autodetection of MBeans in your application context (this is basically the same as the <context:mbean-export /> does.
For more information I strongly suggest the JMX chapter of the reference guide.

Inconsistent NoSuchBeanDefinitionException since upgrading from Spring 3.0 to Spring 3.1

We've been seeing inconsistent NoSuchBeanDefinitionException since upgrading from Spring 3.0 to Spring 3.1. It happens to only about 2% of our hosts and even then the problem is not consistent in a single host since it might not happen after restarting the same server.
Here's the error :
nested exception is org.springframework.beans.factory.BeanCreationException: Could
not autowire field: private com.google.common.util.concurrent.ListeningExecutorService
com.amazon.ms3.container.impl.ExecutionEnvironmentImpl.functionThreadPool;
nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException:
No matching bean of type [com.google.common.util.concurrent.ListeningExecutorService]
found for dependency: expected at least 1 bean which qualifies as
autowire candidate for this dependency. Dependency annotations:
{#org.springframework.beans.factory.annotation.Autowired(required=true),
#org.springframework.beans.factory.annotation.Qualifier(value=functionThreadPool)}
| at org.springframework.beans.factory.annotation
.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues...
Here's the bean code (irrelevant code removed):
public class ExecutionEnvironmentImpl extends ExecutionEnvironment {
#Autowired
#Qualifier("functionThreadPool")
private ListeningExecutorService functionThreadPool;
public ExecutionEnvironmentImpl() {
}
public void setFunctionThreadPool(ListeningExecutorService functionThreadPool) {
this.functionThreadPool = functionThreadPool;
}
}
And here's the configuration file (irrelevant configuration removed):
<?xml version="1.0" encoding="UTF-8"?>
<beans
xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:util="http://www.springframework.org/schema/util"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd
">
<bean id="executionEnvironment" class="com.amazon.ms3.container.impl.ExecutionEnvironmentImpl" scope="prototype"/>
<!-- ThreadPool for executing tenant functions asynchronously -->
<bean id="functionThreadPool" class="com.google.common.util.concurrent.MoreExecutors" factory-method="listeningDecorator">
<constructor-arg>
<bean class="java.util.concurrent.Executors" factory-method="newCachedThreadPool"/>
</constructor-arg>
</bean>
</beans>
The Qualifier annotation isn't much of use anymore since we don't have other ListeningExecutorService defined but I don't believe it should be causing any problem.
Any ideas of what might be causing this? I've been thinking about removing the autowiring completely but I'd like to understand why this is happening in the first place.
Thanks!
This is possibly some timing-related issue in the order that Spring brings up beans in the application context. It may be worth explicitly telling Spring to create the functionThreadPool first to ensure that it is available for autowiring into the executionEnvironment. To do that, you can use the depends-on attribute:
<bean id="executionEnvironment"
class="com.amazon.ms3.container.impl.ExecutionEnvironmentImpl"
scope="prototype"
depends-on="functionThreadPool"/>
<!-- ThreadPool for executing tenant functions asynchronously -->
<bean id="functionThreadPool" class="com.google.common.util.concurrent.MoreExecutors" factory-method="listeningDecorator">
<constructor-arg>
<bean class="java.util.concurrent.Executors" factory-method="newCachedThreadPool"/>
</constructor-arg>
</bean>
</beans>
If you intend to use autowiring then you should have the <context:annotation-config> element in the configuration also - so that Spring knows to autowire the functionThreadPool into the executionEnvironment.
After trying depends-on and even wiring the bean directly like shown below :
<bean id="executionEnvironment" class="com.amazon.ms3.container.impl.ExecutionEnvironmentImpl" scope="prototype">
<property name="functionThreadPool" ref="functionThreadPool"/>
</bean>
<!-- ThreadPool for executing tenant functions asynchronously -->
<bean id="functionThreadPool" class="com.google.common.util.concurrent.MoreExecutors" factory-method="listeningDecorator">
<constructor-arg>
<bean class="java.util.concurrent.Executors" factory-method="newCachedThreadPool"/>
</constructor-arg>
</bean>
we were still seeing the same error on some occasions. The only thing that fixed it was to remove the #Autowired annotation in the ExecutionEnvironmentImpl class.
We didn't really fix the problem but more like avoiding it. I wish I could provide a better answer.

JPA .persist() doesn't save the data to the database while read works properly

I have a Spring/JPA (with Hibernate as the JPA provider) with MySQL as the database provider.
I can't seem to be able to persist the data successfully even though I can read the data from the database.
I have searched through stackoverflow and most of the solutions dealt with decorating the save method with #Transactional (also the class). I verified the overall configuration but I can't seem to find out where I'm going wrong.
Here is my configuration
persistence.xml
<?xml version="1.0" encoding="UTF-8"?>
<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/ p ersistence/persistence_2_0.xsd"
version="2.0" xmlns="http://java.sun.com/xml/ns/persistence">
<persistence-unit name="brPersistenceUnit" transaction-type="RESOURCE_LOCAL">
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<jta-data-source>java:comp/env/jdbc/brDS</jta-data-source>
<class>com.uhsarp.br.domain.Bill</class>
<properties>
<property name="hibernate.hbm2ddl.auto" value="validate"/>
<property name="hibernate.dialect" value="org.hibernate.dialect.MySQLDialect" />
</properties>
</persistence-unit>
</persistence>
spring application context
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.0.xsd">
<!-- JPA Entity Manager Factory -->
<!-- <bean id="entityManagerFactory"
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"
p:dataSource-ref="brDS"/>-->
<bean id="entityManagerFactory"
class="org.springframework.orm.jpa.LocalEntityManagerFactoryBean">
<property name="persistenceUnitName" value="brPersistenceUnit"/>
</bean>
<bean class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor" />
<!-- Database LOB Handling -->
<bean id="defaultLobHandler" class="org.springframework.jdbc.support.lob.DefaultLobHandler" />
<!-- Read in DAOs from the JPA package -->
<context:component-scan base-package="com.uhsarp.br.dao.framework.impl" />
<!-- Transaction Config -->
<bean id="transactionManager"
class="org.springframework.orm.jpa.JpaTransactionManager"
p:entityManagerFactory-ref="entityManagerFactory"/>
<tx:annotation-driven/>
</beans>
snippet of the DAO class
#Repository("billDAO")
#Transactional
public class BillDAOImpl implements BillDAO{
#PersistenceContext
private EntityManager em;
#Transactional(propagation=Propagation.REQUIRED, rollbackFor=Exception.class)
public Bill save(Bill bill) {
if (bill.getId() == null) {
em.persist(bill);
return bill;
} else {
return em.merge(bill);
}
}
}
The problem was not with JPA.
I had the data coming in from the Frontend (as JSON). Spring MVC did the data binding and created the 'Bill' object. Even though the object structure was formed without showing any errors, the ids were not being populated properly and that made JPA fail the .persist query.
The hibernate logs (show_sql in persistence.sql) did show that the transaction is being rolled back. But the hibernate logs are one of the worst logs I've ever come across (or I might be going blind). They are so verbose and hard to find the errors. I do however accept that I'm not a Hibernate veteran.
Also another challenge I faced is that I designed the database and objects separately and tried to validate the objects with the tables (Other ways are to let Hibernate generate the tables or let it generate the Entities from the tables). Although this is not a bad practice by any means, it is important to ensure that the design of the database and the Entities is proper and legit for everything to work properly. The application may build fine, JPA may validate the tables but that doesn't necessarily mean that your datamodel is legible. There are some hard experiences that I've learned through my initial adventure with JPA but I thank fellow devs from Stackoverflow for their wisdom in this process.

Categories

Resources