(Jeszcze trochę nowych do wiosny)Wiosna: metoda @Transactional @Scheduled rzuca TransactionException
muszę mieć metodę usług, które są jednocześnie @Scheduled
i @Transactional
, tak że mogę zadzwonić w DAO to.
Transakcje deklaracyjne są włączone, menedżer transakcji to org.springframework.orm.hibernate3.HibernateTransactionManager
oparty na fabryce sesji hibernacji.
klasa Usługa nie realizuje żadnego interfejsu tak jest używany serwer proxy CGLIB.
Układ ten działa dobrze w ogóle (metody wywoływane z sieci stos czyli poprzeczne), ale sposób ten zwiększa się wyjątek, kiedy wywoływana przez planistę.
Oto stosowne fragmenty kodu:
Metoda service (klasa nazywa 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
}
Istotne części mojego kontekście aplikacji:
<!-- 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>
Wyjątek stosu ślad:
[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
Stos ślad Wydaje mi powiedzieć, że transakcyjny proxy jest rzeczywiście używany więc nie rozumiem tego wyjątku. Wsparcie !
EDIT:
starałem się oddzielić @Transactional
i @Scheduled
adnotacji przez:
- utworzyć nową klasę/Fasola że contaisn the metoda
@Scheduled
- wstrzyknąć moją służbę do tej fasoli
- Usunięto
@Scheduled
z mojej oryginalnej metodzie ale opuścił@Transactional
Ale nadal uzyskać ten sam wyjątek. Próbowałem również umieścić @Transactional
w mojej metodzie DAO i usunąć ją z mojej metody serwisowej: ten sam wynik.
może się to zdarzyć, gdy już zaangażowani lub wycofana transakcja próbuje popełnić lub wycofania – wedens
można pokazać swoją metodę dao? – wedens
OK, moja metoda DAO była winna. Zaczynałem podejrzewać to i wtedy twój komentarz sprawił, że spojrzałem dwa razy. Metoda zawierała więc ręczny commit sesji po lewej stronie (ostatnio aktualizuję i "tworzę" tę aplikację), więc gdy transakcyjny serwer proxy wywoływał zatwierdzenie, nie udało się, ponieważ został już zatwierdzony! Dziękuję za Twój czas. Jeśli edytujesz swoją odpowiedź, by wspomnieć o metodzie DAO, przyjmuję ją. –