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

Lookup of txn:LocalUserTransaction makes it possible to illegally use UserTransaction in a CMT context

XMLWordPrintable

    • Hide

      The below works (but should not) in a CMT NOT_SUPPORTED context

                              userTransaction = UserTransaction.class.cast(new javax.naming.InitialContext().lookup("txn:LocalUserTransaction"));
                              log.info("userTransaction = " + userTransaction);
      
                              log.info("Starting user transaction");
                              tm.begin();
      
                              ...
      
                              log.info("Committing user transaction");
                              tm.commit();
      

      The below executed in a REQUIRED context causes a failure when the stack unwinds but may violate transactional integrity:

                              userTransaction = UserTransaction.class.cast(new javax.naming.InitialContext().lookup("txn:LocalUserTransaction"));
                              log.info("userTransaction = " + userTransaction);
      
                              ...
      
                              log.info("Committing user transaction");
                              tm.commit();
      
                              ...
      

      The problem is that anything done before the tx.commit() will be successfully committed and anything done afterward will not be part of the same transaction. If the lookup and commit are a few layers deeper in the call stack, it may not be clear what part of the unit of work completed and what portion of the unit of work failed (the outcome from a logical standpoint may be similar to a heuristic outcome).

      The causal exception trace (raised during unwind of the stack) is below.

      java.lang.IllegalStateException: WFLYEJB0060: Wrong tx on thread: expected Local transaction (delegate=TransactionImple < ac, BasicAction: 0:ffff7f000101:c49a7c4:6086e856:e status: ActionStatus.COMMITTED >, owner=Local transaction context for provider JBoss JTA transaction provider), actual null
      	at org.jboss.as.ejb3.tx.CMTTxInterceptor.endTransaction(CMTTxInterceptor.java:81)
      	at org.jboss.as.ejb3.tx.CMTTxInterceptor.invokeInOurTx(CMTTxInterceptor.java:280)
      	at org.jboss.as.ejb3.tx.CMTTxInterceptor.requiresNew(CMTTxInterceptor.java:412)
      	at org.jboss.as.ejb3.tx.LifecycleCMTTxInterceptor.processInvocation(LifecycleCMTTxInterceptor.java:68)
      	at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:422)
      	at org.jboss.as.weld.injection.WeldInjectionContextInterceptor.processInvocation(WeldInjectionContextInterceptor.java:43)
      	at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:422)
      	at org.jboss.as.ejb3.component.interceptors.CurrentInvocationContextInterceptor.processInvocation(CurrentInvocationContextInterceptor.java:41)
      	at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:422)
      	at org.jboss.as.ee.concurrent.ConcurrentContextInterceptor.processInvocation(ConcurrentContextInterceptor.java:45)
      	at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:422)
      	at org.jboss.invocation.ContextClassLoaderInterceptor.processInvocation(ContextClassLoaderInterceptor.java:60)
      	at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:422)
      	at org.jboss.as.ejb3.component.singleton.StartupCountDownInterceptor.processInvocation(StartupCountDownInterceptor.java:25)
      	at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:422)
      	at org.jboss.invocation.ChainedInterceptor.processInvocation(ChainedInterceptor.java:53)
      	at org.jboss.as.ee.component.BasicComponent.constructComponentInstance(BasicComponent.java:161)
      	...
      
      Show
      The below works (but should not) in a CMT NOT_SUPPORTED context userTransaction = UserTransaction. class. cast ( new javax.naming.InitialContext().lookup( "txn:LocalUserTransaction" )); log.info( "userTransaction = " + userTransaction); log.info( "Starting user transaction" ); tm.begin(); ... log.info( "Committing user transaction" ); tm.commit(); The below executed in a REQUIRED context causes a failure when the stack unwinds but may violate transactional integrity: userTransaction = UserTransaction. class. cast ( new javax.naming.InitialContext().lookup( "txn:LocalUserTransaction" )); log.info( "userTransaction = " + userTransaction); ... log.info( "Committing user transaction" ); tm.commit(); ... The problem is that anything done before the tx.commit() will be successfully committed and anything done afterward will not be part of the same transaction. If the lookup and commit are a few layers deeper in the call stack, it may not be clear what part of the unit of work completed and what portion of the unit of work failed (the outcome from a logical standpoint may be similar to a heuristic outcome). The causal exception trace (raised during unwind of the stack) is below. java.lang.IllegalStateException: WFLYEJB0060: Wrong tx on thread: expected Local transaction (delegate=TransactionImple < ac, BasicAction: 0:ffff7f000101:c49a7c4:6086e856:e status: ActionStatus.COMMITTED >, owner=Local transaction context for provider JBoss JTA transaction provider), actual null at org.jboss.as.ejb3.tx.CMTTxInterceptor.endTransaction(CMTTxInterceptor.java:81) at org.jboss.as.ejb3.tx.CMTTxInterceptor.invokeInOurTx(CMTTxInterceptor.java:280) at org.jboss.as.ejb3.tx.CMTTxInterceptor.requiresNew(CMTTxInterceptor.java:412) at org.jboss.as.ejb3.tx.LifecycleCMTTxInterceptor.processInvocation(LifecycleCMTTxInterceptor.java:68) at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:422) at org.jboss.as.weld.injection.WeldInjectionContextInterceptor.processInvocation(WeldInjectionContextInterceptor.java:43) at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:422) at org.jboss.as.ejb3.component.interceptors.CurrentInvocationContextInterceptor.processInvocation(CurrentInvocationContextInterceptor.java:41) at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:422) at org.jboss.as.ee.concurrent.ConcurrentContextInterceptor.processInvocation(ConcurrentContextInterceptor.java:45) at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:422) at org.jboss.invocation.ContextClassLoaderInterceptor.processInvocation(ContextClassLoaderInterceptor.java:60) at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:422) at org.jboss.as.ejb3.component.singleton.StartupCountDownInterceptor.processInvocation(StartupCountDownInterceptor.java:25) at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:422) at org.jboss.invocation.ChainedInterceptor.processInvocation(ChainedInterceptor.java:53) at org.jboss.as.ee.component.BasicComponent.constructComponentInstance(BasicComponent.java:161) ...
    • Undefined

      It is possible to illegally access and use UserTransaction in a container managed transaction (CMT) context when using the txn:LocalUserTransaction based lookup. This may lead to violations of transactional integrity. The EJB specification prohibits access to or use of UserTransaction in such contexts.

              tadamski@redhat.com Tomasz Adamski
              rhn-support-sfikes Stephen Fikes (Inactive)
              Votes:
              0 Vote for this issue
              Watchers:
              7 Start watching this issue

                Created:
                Updated:
                Resolved: