Announcement Announcement Module
Collapse
No announcement yet.
TransactionTemplate commits on JTA Timeout Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • TransactionTemplate commits on JTA Timeout

    Hi,

    I have noticed the following behaviour while using TransactionTemplate with Spring JTA Transaction Manager backed up by Atomikos and Hibernate as JPA provider.

    Within a transaction scoped through a transaction template, two entities are persisted into two different data stores, each entity managed by a different entity manager factory. The thread sleeps for a second more than the transaction timeout before exiting. Atomikos clearly marks the transaction coordinator implementation as rollback only as soon as the transaction timeout expires.

    But the transaction template code is unaware of this status and proceeds calling commit() on the transaction manager. In the commit() implementation of Spring's JTATransactionManager, a check is of course implemented to ensure that the underlying user transaction status is not for rollback only. If so, it raises an UnexpectedRollbackException with a message suggesting that it may be due to a timeout.

    However, the entities are persisted into the database successfully. Atomikos logs that the application has done a commit, even though the afterCompletion() logs has all of the transaction statuses as STATUS_ROLLEDBACK.

    The question I have is, is it an appropriate implementation for the TransactionTemplate to call commit() when the underlying transaction has been marked as rollback only? Should it rather not assert the underlying transaction status before making that decision?

  • #2
    Originally posted by rambal
    The question I have is, is it an appropriate implementation for the TransactionTemplate to call commit() when the underlying transaction has been marked as rollback only? Should it rather not assert the underlying transaction status before making that decision?
    Those checks are there (check the source code) I would also expect the underlying implementation (in this case Atomikos) to throw an exception if a commit would be happening.

    So I suspect either something wrong in your setup or a "bug" in Atomikos.

    Comment


    • #3
      Hi Marten,

      Thanks for coming back.

      I can notice the checks are there at two places in the AbstractPlatformTransactionManager and JtaTransactionManager implementations. However, the first check fails, hence the triggerBeforeCompletion() and all of the commit() actions occur. The second check correctly detects it and raises the UnexpectedRollbackExeption with probably due to a time out message. However, it is too late as the transaction is committed and only the afterCompletion() acknowledges that it should have rolled back.

      The stack trace is as below:
      org.springframework.transaction.UnexpectedRollback Exception: JTA transaction unexpectedly rolled back (maybe due to a timeout); nested exception is javax.transaction.RollbackException: Prepare: NO vote
      at org.springframework.transaction.jta.JtaTransaction Manager.doCommit(JtaTransactionManager.java:1029)
      at org.springframework.transaction.support.AbstractPl atformTransactionManager.processCommit(AbstractPla tformTransactionManager.java:709)
      at org.springframework.transaction.support.AbstractPl atformTransactionManager.commit(AbstractPlatformTr ansactionManager.java:678)
      at com.hsbc.eos.multidatasource.prototype.TimeoutMana gingTransactionTemplate.execute(TimeoutManagingTra nsactionTemplate.java:61)
      at com.hsbc.eos.multidatasource.prototype.MultiDataSo urceJTATest.forceTimeout(MultiDataSourceJTATest.ja va:126)
      at com.hsbc.eos.multidatasource.prototype.MultiDataSo urceJTATest.testJTA(MultiDataSourceJTATest.java:98 )
      at sun.reflect.NativeMethodAccessorImpl.invoke0(Nativ e Method)
      at sun.reflect.NativeMethodAccessorImpl.invoke(Native MethodAccessorImpl.java:39)
      at sun.reflect.DelegatingMethodAccessorImpl.invoke(De legatingMethodAccessorImpl.java:25)
      at java.lang.reflect.Method.invoke(Method.java:597)
      at junit.framework.TestCase.runTest(TestCase.java:168 )
      at junit.framework.TestCase.runBare(TestCase.java:134 )
      at org.springframework.test.ConditionalTestCase.runBa re(ConditionalTestCase.java:76)
      at junit.framework.TestResult$1.protect(TestResult.ja va:110)
      at junit.framework.TestResult.runProtected(TestResult .java:128)
      at junit.framework.TestResult.run(TestResult.java:113 )
      at junit.framework.TestCase.run(TestCase.java:124)
      at junit.framework.TestSuite.runTest(TestSuite.java:2 32)
      at junit.framework.TestSuite.run(TestSuite.java:227)
      at org.junit.internal.runners.JUnit38ClassRunner.run( JUnit38ClassRunner.java:81)
      at org.eclipse.jdt.internal.junit4.runner.JUnit4TestR eference.run(JUnit4TestReference.java:46)
      at org.eclipse.jdt.internal.junit.runner.TestExecutio n.run(TestExecution.java:38)
      at org.eclipse.jdt.internal.junit.runner.RemoteTestRu nner.runTests(RemoteTestRunner.java:467)
      at org.eclipse.jdt.internal.junit.runner.RemoteTestRu nner.runTests(RemoteTestRunner.java:683)
      at org.eclipse.jdt.internal.junit.runner.RemoteTestRu nner.run(RemoteTestRunner.java:390)
      at org.eclipse.jdt.internal.junit.runner.RemoteTestRu nner.main(RemoteTestRunner.java:197)
      Caused by: javax.transaction.RollbackException: Prepare: NO vote
      at com.atomikos.icatch.jta.TransactionImp.rethrowAsJt aRollbackException(TransactionImp.java:68)
      at com.atomikos.icatch.jta.TransactionImp.commit(Tran sactionImp.java:222)
      at com.atomikos.icatch.jta.TransactionManagerImp.comm it(TransactionManagerImp.java:501)
      at com.atomikos.icatch.jta.UserTransactionImp.commit( UserTransactionImp.java:130)
      at org.springframework.transaction.jta.JtaTransaction Manager.doCommit(JtaTransactionManager.java:1026)
      ... 25 more

      Caused by: com.atomikos.icatch.RollbackException: Prepare: NO vote
      at com.atomikos.icatch.imp.ActiveStateHandler.prepare (ActiveStateHandler.java:197)
      at com.atomikos.icatch.imp.CoordinatorImp.prepare(Coo rdinatorImp.java:688)
      at com.atomikos.icatch.imp.CoordinatorImp.terminate(C oordinatorImp.java:972)
      at com.atomikos.icatch.imp.CompositeTerminatorImp.com mit(CompositeTerminatorImp.java:82)
      at com.atomikos.icatch.imp.CompositeTransactionImp.co mmit(CompositeTransactionImp.java:336)
      at com.atomikos.icatch.jta.TransactionImp.commit(Tran sactionImp.java:208)
      ... 28 more

      Having looked at atomikos code, when the time out occurs, it signals to the transaction coordinator that a rollback only signal should be recorded. The internal implementation registers a new participant to the transaction which inturn throws a rollback exception upon prepare() call.

      Could you please confirm this is compatible with the JTAtransactionManager implementation?

      Comment

      Working...
      X