(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(){
Relevant parts of the context of my application:
<tx:annotation-driven transaction-manager="transactionManager" proxy-target-class="true"/> <bean class="org.springframework.transaction.support.TransactionTemplate" id="txTemplate"> <constructor-arg name="transactionManager" ref="transactionManager"/> </bean> <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.