We are seeing a strange error while using JTA in JBoss 4.3 EAP. We have a POJO configured with the Spring Tx interceptor. Before the interceptor is invoked, a Tx is associated with the thread and Spring's interceptor happily works with it (propagation required). Successful execution allows everything to proceed and the Tx is committed successfully.
However, when an exception occurs, for some reason, things go horribly wrong.
Here's the output we see in the log, mostly from Spring as far as we can tell:
16:12:48,061 INFO [STDOUT] 16:12:48,061 DEBUG [TransactionInterceptor] Completing transaction for [...controller.ITaskController.completeTasks] after exception: org.jbpm.JbpmException: [snip] 16:12:52,545 INFO [STDOUT] 16:12:52,545 DEBUG [RuleBasedTransactionAttribute] Applying rules to determine whether transaction should rollback on org.jbpm.JbpmException: [snip] 16:12:52,561 INFO [STDOUT] 16:12:52,561 DEBUG [RuleBasedTransactionAttribute] Winning rollback rule is: null 16:12:52,561 INFO [STDOUT] 16:12:52,561 DEBUG [RuleBasedTransactionAttribute] No relevant rollback rule found: applying superclass default 16:13:11,249 INFO [STDOUT] 16:13:11,249 DEBUG [JtaTransactionManager] Triggering beforeCompletion synchronization 16:13:11,249 INFO [STDOUT] 16:13:11,249 DEBUG [TransactionSynchronizationManager] Removed value [org.springframework.orm.hibernate3.SessionHolder@151f2a9] for key [org.hibernate.impl.SessionFactoryImpl@6a641d] from thread [http-127.0.0.3-8080-2] 16:13:11,265 INFO [STDOUT] 16:13:11,249 DEBUG [TransactionSynchronizationManager] Removed value [org.springframework.jdbc.datasource.ConnectionHolder@79c26] for key [org.jboss.resource.adapter.jdbc.WrapperDataSource@b6dff] from thread [http-127.0.0.3-8080-2] 16:13:11,265 INFO [STDOUT] 16:13:11,265 DEBUG [JtaTransactionManager] Participating transaction failed - marking existing transaction as rollback-only 16:13:11,265 INFO [STDOUT] 16:13:11,265 DEBUG [JtaTransactionManager] Setting JTA transaction rollback-only 16:13:11,265 INFO [STDOUT] 16:13:11,265 DEBUG [JtaTransactionManager] Registering after-completion synchronization with existing JTA transaction 16:13:11,280 INFO [STDOUT] 16:13:11,280 DEBUG [TransactionSynchronizationManager] Clearing transaction synchronization 16:13:32,828 INFO [STDOUT] 16:13:32,812 ERROR [TransactionInterceptor] Application exception overridden by rollback exception
The last line indicates a rollback exception. That exception is as follows.
org.springframework.transaction.NoTransactionException: No active JTA transaction at org.springframework.transaction.jta.JtaTransactionManager.registerAfterCompletionWithExistingTransaction(JtaTransactionManager.java:903) at org.springframework.transaction.support.AbstractPlatformTransactionManager.triggerAfterCompletion(AbstractPlatformTransactionManager.java:885) at org.springframework.transaction.support.AbstractPlatformTransactionManager.processRollback(AbstractPlatformTransactionManager.java:782) at org.springframework.transaction.support.AbstractPlatformTransactionManager.rollback(AbstractPlatformTransactionManager.java:730) at org.springframework.transaction.interceptor.TransactionAspectSupport.completeTransactionAfterThrowing(TransactionAspectSupport.java:332) at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:111) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:161) at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:204) at $Proxy70.completeTasks(Unknown Source)
So, apparently somewhere in the process of handling the exception, the JTA transaction is no longer associated with the thread?! We are a bit at a loss here ... the level of the application where this is occuring shouldn't be manipulating if the JTA transaction (parent) is associated with the thread or not ... since it is only participating, it didn't create the transaction. So how can it be disassociated?
Any help on how to get to the bottom of this would be greatly appreciated. For example, where could I set a breakpoint to figure out what is invoking the presumed suspend() on the parent transaction, which would disassociate it from the thread?