"no transaction is in progress" error while using @Transactional
All, I am trying to use the annotational transaction in Spring and getting the javax.persistence.TransactionRequiredException: no transaction is in progress
error all the time.
Eror stacktrace:
[22:40:11:354] 00000024 SystemErr R javax.persistence.TransactionRequiredException: no transaction is in progress
[22:40:11:354] 00000024 SystemErr R at org.hibernate.ejb.AbstractEntityManagerImpl.flush(AbstractEntityManagerImpl.java:301)
[22:40:11:354] 00000024 SystemErr R at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
[22:40:11:354] 00000024 SystemErr R at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:60)
[22:40:11:354] 00000024 SystemErr R at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:37)
[22:40:11:354] 00000024 SystemErr R at java.lang.reflect.Method.invoke(Method.java:611)
[22:40:11:354] 00000024 SystemErr R at org.springframework.orm.jpa.ExtendedEntityManagerCreator$ExtendedEntityManagerInvocationHandler.invoke(ExtendedEntityManagerCreator.java:365)
[22:40:11:354] 00000024 SystemErr R at $Proxy45.flush(Unknown Source)
[22:40:11:354] 00000024 SystemErr R at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
[22:40:11:354] 00000024 SystemErr R at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:60)
[22:40:11:354] 00000024 SystemErr R at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:37)
[22:40:11:354] 00000024 SystemErr R at java.lang.reflect.Method.invoke(Method.java:611)
[22:40:11:354] 00000024 SystemErr R at org.springframework.orm.jpa.SharedEntityManagerCreator$SharedEntityManagerInvocationHandler.invoke(SharedEntityManagerCreator.java:240)
[22:40:11:354] 00000024 SystemErr R at $Proxy42.flush(Unknown Source)
[22:40:11:354] 00000024 SystemErr R at com.test.MyDAO.saveOrUpdateData
.
.
.
Please note that, the same code runs fine when I use AOP.
The technology stack looks like this:
Spring 3.0.5
Struts 2.2.1.1
Hibernate 3.3.2GA
JPA 1.0
JBPM 4.4
Here are my application configurations:
applicationContext.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:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx" xmlns:jee="http://www.springframework.org/schema/jee"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-3.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd">
<bean
class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor" />
<!-- <bean-->
<!-- class="org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor" />-->
<jee:jndi-lookup id="dataSource" jndi-name="jdbc/my_dataSource1.1"
cache="true" resource-ref="true" lookup-on-startup="true"
proxy-interface="javax.sql.DataSource" />
<bean id="entityManagerFactory"
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="persistenceXmlLocation" value="META-INF/my-persistence.xml" />
</bean>
<!--
Also tried the JTA transaction manager....
<bean id="transactionManager" class="org.springframework.transaction.jta.JtaTransactionManager">
-->
<bean id="transactionManager" class="org.springframework.transaction.jta.WebSphereUowTransactionManager"/>
<tx:annotation-driven/>
<!-- <tx:advice id="txAdvice" transaction-manager="transactionManager">-->
<!-- <tx:attributes>-->
<!-- <tx:method name="get*" read-only="true" />-->
<!-- <tx:method name="saveOrUpdate*" propagation="REQUIRES_NEW" read-only="false"/>-->
<!-- </tx:attributes>-->
<!-- </tx:advice>-->
<!-- <aop:config>-->
<!-- <aop:pointcut id="daoOperations"-->
<!-- expression="execution(* com.honda.naps.dao..*.*(..))" />-->
<!-- <aop:advisor advice-ref="txAdvice" pointcut-ref="daoOperations" />-->
<!-- </aop:config>-->
<!-- This is the DAO that's injected -->
<bean id="myDAO" class="com.test.MyDAO" />
<bean id="myBaseDAO" class="com.test.BaseDAO" />
<!--
This is the struts action that's created .. in struts.xml I have used
<constant name="struts.objectFactory" value="spring" />
-->
<bean id="myAction" scope="prototype" class="com.test.MyAction">
</bean>
<!-- My BO instance -->
<bean id="myBO" class="com.test.MyBOImpl">
<property name="myDAO" ref="myDAO" />
<property name="myBaseDAO" ref="myBaseDAO" />
</bean>
</beans>
Also in struts.xml, I invoke the saveOrUpdateData() on the MyDAO class.
web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app id="WebApp_ID" version="2.5"
xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" metadata-complete="true">
<display-name>NAPSWeb</display-name>
<context-param>
<param-name>
org.apache.tiles.impl.BasicTilesContainer.DEFINITIONS_CONFIG</param-name>
<param-value>/WEB-INF/tiles.xml</param-value>
</context-param>
<context-param>
<param-name>log4jConfigLocation</param-name>
<param-value>/WEB-INF/resources/log4j.properties</param-value>
</context-param>
<context-param>
<param-name>log4jRefreshInterval</param-name>
<param-value>1000</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.util.Log4jConfigListener</listener-class>
</listener>
<listener>
<listener-class>org.apache.struts2.tiles.StrutsTilesListener</listener-class>
</listener>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring_config/applicationContext.xml</param-value>
</context-param>
<filter>
<filter-name>struts2</filter-name>
<filter-class>
org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>struts2</filter-name>
<url-pattern&g开发者_JAVA百科t;*.action</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>struts2</filter-name>
<url-pattern>/struts/*</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>struts2</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<distributable></distributable>
</web-app>
my-persistence.xml
http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd" version="1.0"> org.hibernate.ejb.HibernatePersistence jdbc/my_dataSource1.1
<class>com.test.MyTbl1</class>
<class>com.test.MyTbl2</class>
<class>com.test.MyTbl3</class>
<properties>
<!-- HIBERNATE properties -->
<property name="hibernate.transaction.factory_class" value="org.hibernate.transaction.CMTTransactionFactory"/>
<!-- <property name="hibernate.transaction.manager_lookup_class" value="org.hibernate.transaction.WebSphereExtendedJTATransactionLookup"/> -->
<property name="hibernate.transaction.manager_lookup_class" value="org.hibernate.transaction.WebSphereTransactionManagerLookup"/>
<property name="jta.UserTransaction" value="java:comp/UserTransaction"/>
<property name="hibernate.dialect" value="org.hibernate.dialect.SQLServerDialect"/>
<!-- <property name="hibernate.cache.provider_class" value="org.hibernate.cache.NoCacheProvider"/>-->
<property name="hibernate.showsql" value="true"/>
<!-- <property name="hibernate.cache.use_second_level_cache" value="false"/> -->
<!-- <property name="jta.UserTransaction" value="java:comp/UserTransaction"/> -->
<property name="databasePlatform" value="org.hibernate.dialect.SQLServerDialect"/>
</properties>
</persistence-unit>
The DAO method class that uses @Transactional looks like this:
//Class MyDAO
public class MyDAO extends BaseDAO
{
@Transactional(propagation=Propagation.REQUIRES_NEW, readOnly=false)
public void saveOrUpdateData()
{
MyTbl1 mt1 = new MyTbl1();
//do something with mt1
getEntityManager().persist(mt1);
getEntityManager().flush();
}
}
BaseDAO class:
public class BaseDAO {
/**
* Variable which stores the injected
* JPA Entity Manager.
*/
private EntityManager entityManager;
public EntityManager getEntityManager() {
System.out.println("getting the entity manager.");
return entityManager;
}
@PersistenceContext(unitName="MY_JPA")
public void setEntityManager(EntityManager entityManager) {
logger.debug("Setting the entity manager.");
this.entityManager = entityManager;
}
}
Libraries used:
ejb3-persistence.jar
hibernate-annotations.jar
hibernate-commons-annotations.jar
hibernate-entitymanager.jar
hibernate3.3.2.GA.jar
antlr-2.7.6.jar
aopalliance-1.0.jar
asm-1.5.3.jar
asm-all-2.2.3.jar
aspectjrt.jar
aspectjweaver.jar
cglib-nodep-2.1_3.jar
commons-beanutils-1.8.0.jar
commons-collections-3.1.jar
commons-digester-1.8.1.jar
commons-io-1.3.2.jar
commons-logging-1.0.4.jar
commons-logging-api-1.1.jar
dom4j-1.6.1.jar
freemarker-2.3.8.jar
javassist-3.12.0.GA.jar
jbpm.jar
juel-api.jar
juel-engine.jar
juel-impl.jar
log4j-1.2.16.jar
ognl-3.0.jar
org.springframework.aop-3.0.5.RELEASE.jar
org.springframework.asm-3.0.5.RELEASE.jar
org.springframework.aspects-3.0.5.RELEASE.jar
org.springframework.beans-3.0.5.RELEASE.jar
org.springframework.context-3.0.5.RELEASE.jar
org.springframework.context.support-3.0.5.RELEASE.jar
org.springframework.core-3.0.5.RELEASE.jar
org.springframework.expression-3.0.5.RELEASE.jar
org.springframework.jdbc-3.0.5.RELEASE.jar
org.springframework.orm-3.0.5.RELEASE.jar
org.springframework.transaction-3.0.5.RELEASE.jar
org.springframework.web-3.0.5.RELEASE.jar
slf4j-api-1.6.1.jar
slf4j-nop-1.6.1.jar
struts2-convention-plugin-2.2.1.1.jar
struts2-core-2.2.1.1.jar
struts2-dojo-plugin-2.2.1.1.jar
struts2-json-plugin-2.2.1.jar
struts2-spring-plugin-2.2.1.1.jar
struts2-tiles-plugin-2.1.6.jar
tiles-api-2.1.2.jar
tiles-compat-2.1.2.jar
tiles-core-2.1.2.jar
tiles-jsp-2.1.2.jar
tiles-servlet-2.1.2.jar
xwork-core-2.2.1.1.jar
System confiuration:
Websphere App server TE 7.0.0.15 in RAD IDE 7.5
OS: Windows XP SP3
DB: MS SQL Server 2008 enterprise edition
I have parent_last class loading enabled and assigned the default JPA provider as "org.hibernate.ejb.HibernatePersistence" in my Websphere app server.
Any help is appreciated.
Thanks
=======================================
Adding this for everybody's usage...
I had to finally go woth AOP based transaction management. I could not find a way to get @Transactional working in my application.
Adding below the part I added for AOP integration to my application (in the applicationContext.xml):
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<tx:attributes>
<tx:method name="get*" read-only="true" />
<tx:method name="saveOrUpdate*" propagation="REQUIRES_NEW" read-only="false"/>
</tx:attributes>
</tx:advice>
<aop:config>
<aop:pointcut id="daoOperations"
expression="execution(* com.test..*.*(..))" />
<aop:advisor advice-ref="txAdvice" pointcut-ref="daoOperations" />
</aop:config>
Hope this helps,
The app context should be wrapping myDao with an advised proxy. The stacktrace cuts off at the invocation of dao.saveOrUpdateData. If you investigate the stack trace beyond this call in the stack trace, you should find a proxy of the DAO wrapping the real DAO method invocation in a transactionTemplate.doInTransaction call. If this is not the case, then this problem may be manifesting because you are directly injecting the myDao bean into you BO. Autowiring the myDao into BO might work.
精彩评论