Any help with this will be greatly appreciated. Iam using Spring, Jetty(Eclipse Jetty Plugin). It seems like declarative transaction management @Transactional is not working.
Confirmed this isn't working in two ways:
1. The newly created entity is not flushed into the database after the method call.
2. TransactionSynchronizationManager.isActualTransactionActive(); returns false
Note the method below is apart for @Controller class, where a http request calls eventually calls this save method. The controller class does not implement any interfaces.
Actual Code:
@Transactional(propagation = Propagation.REQUIRES_NEW)
public void save(PERule peRule) {
boolean inTransaction = TransactionSynchronizationManager.isActualTransactionActive();
peRuleDAOImpl.persist(peRule);
}
The lack of transaction is also confirm by the Log Output:
DEBUG: org.hibernate.internal.SessionImpl - Opened session at timestamp: 13762325621
DEBUG: org.hibernate.engine.transaction.internal.TransactionCoordinatorImpl - Skipping
JTA sync registration due to auto join checking
DEBUG: org.hibernate.ejb.AbstractEntityManagerImpl - Looking for a JTA transaction to join
DEBUG: org.hibernate.ejb.AbstractEntityManagerImpl - Unable to join JTA transaction
DEBUG: org.hibernate.event.internal.AbstractSaveEventListener - Delaying identity-insert due to no transaction in progress
However when I programatically define explicit transaction boundaries and commit the transaction, the entity is is flushed in to the database. E.g:
@Resource
private PlatformTransactionManager txManager;
private void save(PERule peRule) {
DefaultTransactionDefinition def = new DefaultTransactionDefinition();
TransactionStatus status = txManager.getTransaction(def);
def.setName("SomeTxName");
def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
try {
peRuleDAOImpl.persist(peRule);
} catch (Exception ex) {
txManager.rollback(status);
}
txManager.commit(status);
}
Hence this doesn't seem to be a problem with the way I defined my transactionManager, since it can be inject into the object as defined above.
ContextConfig: root-context.xml
<aop:aspectj-autoproxy />
<context:annotation-config />
<context:component-scan
base-package="org.springframework.samples.mvc, com.project.*" />
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location">
<value>/WEB-INF/spring/proddatabase.properties</value>
</property>
</bean>
<bean id="dataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName" value="jdbc/myds" />
</bean>
<bean id="entityManagerFactory"
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="persistenceUnitName" value="EconDatesDB" />
<property name="persistenceXmlLocation" value="/WEB-INF/spring/jpa-prod-persistence.xml" />
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
<property name="generateDdl" value="false" />
<property name="databasePlatform" value="org.hibernate.dialect.MySQLDialect" />
</bean>
</property>
<property name="jpaProperties">
<props>
<prop key="hibernate.format_sql">false
</prop>
<prop key="hibernate.use_sql_comments">false
</prop>
<prop key="hibernate.generate_statistics">false
</prop>
<prop key="hibernate.transaction.factory_class">org.hibernate.engine.transaction.internal.jta.CMTTransactionFactory
</prop>
<!-- The following line is what's used in Hibernate 4 instead of a TransactionManagerLookup
class -->
<prop key="hibernate.transaction.manager_lookup_class">com.atomikos.icatch.jta.hibernate3.TransactionManagerLookup
</prop>
</props>
</property>
</bean>
<tx:annotation-driven mode="aspectj" proxy-target-class="true" transaction-manager="transactionManager"/>
<bean id="transactionManager"
class="org.springframework.transaction.jta.JtaTransactionManager">
<property name="transactionManager" ref="atomikosTransactionManager" />
<property name="userTransaction" ref="atomikosUserTransaction" />
</bean>
<bean id="atomikosUserTransaction" class="com.atomikos.icatch.jta.UserTransactionImp">
<property name="transactionTimeout" value="300" />
</bean>
<!-- Construct Atomikos UserTransactionManager, needed to configure Spring -->
<bean id="atomikosTransactionManager" class="com.atomikos.icatch.jta.UserTransactionManager"
init-method="init" destroy-method="close">
<!-- when close is called, should we force transactions to terminate or
not? -->
<property name="forceShutdown" value="false" />
<property name="transactionTimeout" value="300" />
</bean>
<mvc:annotation-driven />
<beans:bean id="conversionService"
class="org.springframework.format.support.FormattingConversionServiceFactoryBean">
<beans:property name="formatters">
<beans:bean
class="org.springframework.samples.mvc.convert.MaskFormatAnnotationFormatterFactory" />
</beans:property>
</beans:bean>
<!-- Controllers.xml Only contains routes from path to view name, and has no other spring config
<mvc:view-controller path="showcase/" view-name="/WEB-INF/views/home" /> -->
<beans:import resource="/appServlet/controllers.xml" />
servlet-context:
<resources mapping="/resources/**" location="/resources/" />
<resources mapping="/sharedResources/**" location="/parkingEngine/resources/" />
<beans:bean id="viewResolver"
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<beans:property name="order" value="1" />
<!-- <beans:property name="prefix" value="/WEB-INF/views/" /> -->
<beans:property name="prefix" value="" />
<beans:property name="suffix" value=".jsp" />
</beans:bean>
web.xml:
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring/root-context.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<servlet>
<servlet-name>appServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring/appServlet/servlet-context.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>appServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
pom.xml relevant dependencies:
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib-nodep</artifactId>
<version>2.2</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.6.10</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>1.6.10</version>
</dependency>
I have also attempted following variations of tx:annotation-driven in my root-context.xml:
<tx:annotation-driven mode="aspectj" proxy-target-class="true" transaction-manager="transactionManager"/>
<tx:annotation-driven proxy-target-class="true" transaction-manager="transactionManager"/>
<tx:annotation-driven proxy-target-class="true" transaction-manager="transactionManager"/>
<tx:annotation-driven />