Uploaded image for project: 'WildFly'
  1. WildFly
  2. WFLY-6885

Exception swallowed by CmtTxInterceptor if transaction has been cancelled by reaper

    Details

    • Steps to Reproduce:
      Hide

      See attached Arquillian project.

      Show
      See attached Arquillian project.

      Description

      The CMTTxInterceptor is responsible for starting a transaction if a public method is called on a session bean, and for ending it (commit or rollback) after the method has returned. If a runtime exception occurs during the execution of the public method, WildFly normally throws an EJBException with the original exception as cause. However, if the transaction has timed out, it swallows the original exception, and throws a EJBTransactionRolledBackException without a root cause. That obscures what actually happened during the execution of the public method.

      I attached a zip with an small Arquillian project that shows (1) what happens in case of an exception in combination with an active transaction (the succeeding test) and (2) what happens if the exception occurs when the transaction has timed out (the failing test).

      I think that the exception swallow is explainable as follows, referring to the 10.0.0.Final version of CMTTxInterceptor, that can be found here

      https://github.com/wildfly/wildfly/blob/10.0.0.Final/ejb3/src/main/java/org/jboss/as/ejb3/tx/CMTTxInterceptor.java

      This happens (I verified by stepping through the code with the debugger):

      • The catch block of invokeInOurTx is entered.
      • The method handleExceptionInOurTx tries to set the "rollback only" status on the transaction. The result is that the transaction, which has already been rolled back, stays in the rolled back state. A new EJBException is thrown, wrapping the original runtime exception.
      • The finally block of invokeInOurTx is entered.
      • The endTransaction method sees that the transaction is in the rolled back state, and concludes that the "reaper canceled (rolled back) tx case" is applicable. It throws a new exception (which replaces the EJBException that just has been thrown), but that new exception doesn't have a cause.

      The desired behavior would be that the interceptor only wraps the original exception in an EJBException in this case. I think that the invokeInOurTx method should only call the endTransaction method, if the transaction is not in the rolled back state.

        Gliffy Diagrams

          Attachments

            Issue Links

              Activity

                People

                • Assignee:
                  dmlloyd David Lloyd
                  Reporter:
                  marcelkolsteren Marcel Kolsteren
                • Votes:
                  0 Vote for this issue
                  Watchers:
                  5 Start watching this issue

                  Dates

                  • Created:
                    Updated:
                    Resolved: