Spring: @Transactional @Scheduled throws TransactionException method

(A little new to Spring)

I need to have a maintenance method that is @Scheduled and @Transactional at the same time, so I get a DAO call in it.

Declarative transactions are allowed, the transaction manager is org.springframework.orm.hibernate3.HibernateTransactionManager based on a factory sleep session.

The service class does not implement any interface, so the CGLIB proxy is used.

This setting works fine in general (methods called from the web stack, i.e. Struts), but this method throws an exception when the scheduler is called.

Here are the relevant bits of code:

Service Method (a class called ClientWakeAndTerminateManager ):

 @Scheduled(initialDelay = 5000, fixedRateString = "${rmi.server.threads.clientsScheduleManagement.rate}") @Transactional(readOnly = true) public void runCheck(){ //Call a read-only DAO method (the DAO is @Autowired as a class field) //do some stuff with the data loaded from DB } 

Relevant parts of the context of my application:

 <!-- switch on the transactional infrastructure --> <tx:annotation-driven transaction-manager="transactionManager" proxy-target-class="true"/> <!-- Utility class to execute transactional code where use of annotation is not possible --> <bean class="org.springframework.transaction.support.TransactionTemplate" id="txTemplate"> <constructor-arg name="transactionManager" ref="transactionManager"/> </bean> <!-- Transaction manager based on Hibernate --> <bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager"> <property name="sessionFactory" ref="hibernateSessionFactory"/> </bean> 

Exception stack trace:

 [ERROR] : Unexpected error occurred in scheduled task. org.springframework.transaction.TransactionSystemException: Could not commit Hibernate transaction; nested exception is org.hibernate.TransactionException: Transaction not successfully started at org.springframework.orm.hibernate3.HibernateTransactionManager.doCommit(HibernateTransactionManager.java:661) at org.springframework.transaction.support.AbstractPlatformTransactionManager.processCommit(AbstractPlatformTransactionManager.java:755) at org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:724) at org.springframework.transaction.interceptor.TransactionAspectSupport.commitTransactionAfterReturning(TransactionAspectSupport.java:475) at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:270) at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:94) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172) at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:631) at ch.unine.sitel.lis.rmi.shared.ClientWakeAndTerminateManager$$EnhancerByCGLIB$$d8be4f34.runCheck(<generated>) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:601) at org.springframework.scheduling.support.ScheduledMethodRunnable.run(ScheduledMethodRunnable.java:64) at org.springframework.scheduling.support.DelegatingErrorHandlingRunnable.run(DelegatingErrorHandlingRunnable.java:53) at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:471) at java.util.concurrent.FutureTask$Sync.innerRunAndReset(FutureTask.java:351) at java.util.concurrent.FutureTask.runAndReset(FutureTask.java:178) at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$301(ScheduledThreadPoolExecutor.java:178) at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:293) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1110) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:603) at java.lang.Thread.run(Thread.java:722) Caused by: org.hibernate.TransactionException: Transaction not successfully started at org.hibernate.transaction.JDBCTransaction.commit(JDBCTransaction.java:127) at org.springframework.orm.hibernate3.HibernateTransactionManager.doCommit(HibernateTransactionManager.java:657) ... 22 more 

The stack trace seems to tell me that the transactional proxy is actually being used, so I don't understand this exception. Help!

EDIT:

I tried to separate @Transactional and @Scheduled by:

  • Create a new / bean class that supports the @Scheduled method
  • Bring my service to this bean
  • Removed @Scheduled from my original method but left @Transactional

But I still get the same exception. I also tried putting @Transactional in my DAO method and removing it from my service method: same result.

+8
source share
2 answers

create a separate class using the method annotated with @Transactional and call that method in your annotated @Scheduled method. spring makes a call through a proxy and handles @Transactional correctly.

EDIT: Also look at your DAO method and make sure it does not commit transactions or rollback the transaction manually

+14
source

In my case

 @EnableTransactionManagement 

has not been used. After adding this annotation to one of my @Configuration classes, it starts working.

0
source

Source: https://habr.com/ru/post/952346/


All Articles