10 Replies Latest reply on Mar 27, 2009 11:48 AM by Mark Little

    Transaction Status.STATUS_ROLLEDBACK

    Arto Huusko Newbie

      When a transaction timeout or some other unexpected situation occurs, the new JBoss transaction manager (in JBoss 4.2.1.GA) marks the transaction into state Status.STATUS_ROLLEDBACK.

      I would argue, from the point of view of bean managed transactions EJB session application code, that this is not quite productive. (note that this is almost the same as JBAS-4481, but this issue concerns application code that wants to clean up a transaction, so that it may try to begin again.)

      Trying to code a BMT EJB session, that is able to recover from transaction errors, and reading javax.transaction.Status javadocs, I would never expect to see Status.STATUS_ROLLEDBACK. The only status codes my application code would expect (in case of single resource only) are STATUS_ACTIVE, STATUS_NO_TRANSACTION and STATUS_MARKED_ROLLBACK. Even JTA javadocs suggest this, saying that in stead of STATUS_ROLLEDBACK, NO_TRANSACTION should be returned.

      JBoss TM further complicates this issue, because trying to call rollback() on transaction marked STATUS_ROLLEDBACK just throws an IllegalStateException. Thus there is no way an application code can "gracefully" handle the error situation.

      Previously my tx handling code looked more or less like this:

      UserTransaction tx = sessionContext.getUserTransaction();
      try {
       tx.begin();
       work();
       tx.commit();
      } finally {
       if ((tx.getStatus() == STATUS_ACTIVE) || (tx.getStatus() == STATUS_MARKED_ROLLBACK))
       tx.rollback();
      }
      


      Now this needs to change to:

      UserTransaction tx = sessionContext.getUserTransaction();
      try {
       tx.begin();
       work();
       tx.commit();
      } finally {
       if ((tx.getStatus() == STATUS_ACTIVE) || (tx.getStatus() == STATUS_MARKED_ROLLBACK))
       tx.rollback();
       else if (tx.getStatus() == STATUS_ROLLEDBACK) {
       try {
       tx.rollback();
       } catch (IllegalStateException ex) {
       /* ignore */
       }
       }
      }
      


      That is the only way to get the tx back to state NO_TRANSACTION, so that I can call begin() on the transaction again.

      Reading JBAS-4481, I get the impression that it is for some reason almost impossible for current implementation to mark the transaction into status NO_TRANSACTION in case of timeout. Fair enough (not really), but could the implementation at least refrain from throwing the IllegalStateException if I rollback a transaction marked STATUS_ROLLEDBACK.

        • 1. Re: Transaction Status.STATUS_ROLLEDBACK
          Mark Little Master

           

          "huuskart" wrote:
          When a transaction timeout or some other unexpected situation occurs, the new JBoss transaction manager (in JBoss 4.2.1.GA) marks the transaction into state Status.STATUS_ROLLEDBACK.


          Have you read the transaction standards with which we comply? They make it very clear that on a timeout you MUST roll back the transaction. They also make it very clear that data consistency is very important for transaction systems. So any low-level system exception, for instance, should force the transaction to roll back.

          You should read the OTS specification as well as the JTA BTW. You can have those statuses on the thread in a multi-threaded environment where a different thread terminates the transaction.

          You can always call suspend to remove the thread-to-transaction association. That's pretty simple to do and avoids worrying about breaking data consistency guarantees.

          And finally: we throw IllegalStateException to allow a caller to know that someone else has terminated the transaction. In a multi-threaded transaction that can be pretty important. But if you want to see a change, feel free to raise a Feature Request in JIRA.

          • 2. Re: Transaction Status.STATUS_ROLLEDBACK
            Jonathan Halliday Master

            > I get the impression that it is for some reason almost impossible for current implementation to mark the transaction into status NO_TRANSACTION in case of timeout.

            It's not impossible to implement, it's a clear design choice on our part that a timeout should not disassociate the business logic thread from the transaction context. And by the way if it did you would still need just as much exception handling, since the tx.commit/tx.rollback calls would potentially throw IllegalState, there being no transaction to commit/rollback. You have to write the exception handling code either way so changing the design decision would not help you.

            > could the implementation at least refrain from throwing the IllegalStateException if I rollback a transaction marked STATUS_ROLLEDBACK.

            It could, but then we would get complaints from users who can no longer programatically distinguish timeout cases. In essence such a change in behaviour would cause the transaction manager to mask information that is actually useful for some users.

            P.S. your finally block is not thread safe, since the tx status may change between your call to getStatus and your call to rollback. Async rollback is fun, isn't it :-)

            • 3. Re: Transaction Status.STATUS_ROLLEDBACK
              Mark Little Master

              Which version of TS are you using BTW? A case of deja vu made me check the code and it seems that now we won't throw IllegalStateException.

              http://jira.jboss.com/jira/browse/JBTM-56

              • 4. Re: Transaction Status.STATUS_ROLLEDBACK
                Arto Huusko Newbie

                 

                "mark.little@jboss.com" wrote:
                "huuskart" wrote:
                When a transaction timeout or some other unexpected situation occurs, the new JBoss transaction manager (in JBoss 4.2.1.GA) marks the transaction into state Status.STATUS_ROLLEDBACK.


                Have you read the transaction standards with which we comply? They make it very clear that on a timeout you MUST roll back the transaction. They also make it very clear that data consistency is very important for transaction systems. So any low-level system exception, for instance, should force the transaction to roll back.


                My point was not at all to complain about the transaction getting rolled back. It is blindingly obvious that it must be rolled back.

                My point was that in BMT EJB code, seeing Status.STATUS_ROLLEDBACK is very puzzling, and even more so because you can't commit() nor rollback() the transaction (both throw an exception), nor can you call begin() on it again.

                "mark.little@jboss.com" wrote:
                You can always call suspend to remove the thread-to-transaction association.


                No, I can't. In EJB code, all I have to work with is javax.transaction.UserTransaction, and it does not give me that kind of control (nor would I wish to see such controls in EJB session code).

                Sorry, I forgot to mention the version: I'm using JBoss AS 4.2.1.GA.

                • 5. Re: Transaction Status.STATUS_ROLLEDBACK
                  Mark Little Master

                  Well like I said, in the current code you can call rollback and it won't throw an exception if the transaction has already rolled back.

                  I'm not sure which version of TS is in 4.2.1GA though. Maybe Jonathan can answer?

                  • 7. Re: Transaction Status.STATUS_ROLLEDBACK
                    Mark Little Master

                    You are so much quicker than me consulting my docs ;-)

                    • 8. Re: Transaction Status.STATUS_ROLLEDBACK
                      Jörg von Frantzius Newbie

                       

                      "mark.little@jboss.com" wrote:
                      Well like I said, in the current code you can call rollback and it won't throw an exception if the transaction has already rolled back.

                      I'm not sure which version of TS is in 4.2.1GA though. Maybe Jonathan can answer?


                      I'm seeing the exact same problem with JBoss AS 4.2.3.GA, i.e. I cannot rollback the UserTransaction once its status has become STATUS_ROLLEDBACK (after a timeout).

                      So that would be a bug then?