Uploaded image for project: 'TomEE'
  1. TomEE
  2. TOMEE-1379

TransactionSynchronizationRegistry not found in JNDI for EJB Timer started transactions

    XMLWordPrintableJSON

Details

    • Bug
    • Status: Closed
    • Major
    • Resolution: Fixed
    • 1.7.1
    • 1.7.2, 7.0.0-M1
    • None
    • None
    • TomEE Plus, Windows 7 x64, Oracle JDK 1.7.0_67

    Description

      To reproduce:
      1. Create EJB class and JSF page from the source pasted below.
      2. Clicking JSF page button "Test EJB business method transaction" gives correct output:

      TEST TIMER BEGIN:
      timerFired(): txKey = [Xid:globalId=15000000047544d4944000000000000000000000000000000000000000000000000000,length=64,branchId=0000000000000000000000000000000000000000000000000000000000000000,length=64]
      TEST TIMER END
      afterCompletion(): txKey = [Xid:globalId=15000000047544d4944000000000000000000000000000000000000000000000000000,length=64,branchId=0000000000000000000000000000000000000000000000000000000000000000,length=64]
      

      3. Clicking JSF page button "Test EJB timer transaction" shows that in method "afterCompletion()" TransactionSynchronizationRegistry is not found in JNDI:

      TEST TIMER BEGIN:
      timerFired(): txKey = [Xid:globalId=e000000047544d4944000000000000000000000000000000000000000000000000000,length=64,branchId=0000000000000000000000000000000000000000000000000000000000000000,length=64]
      TEST TIMER END
      afterCompletion(): errorMessage = Name [TransactionSynchronizationRegistry] is not bound in this Context. Unable to find [TransactionSynchronizationRegistry].
      

      WHY I need all this I have implemented TransactionScoped CDI context, that listens for afterCompletion() events and destroyes TransactionScoped beans. Well, I have memory leak currently for transactions started by EJB timers...

      Source code:
      JSF:

                  <h:form>
                      <h:commandButton value="Test EJB Timer transaction"
                                       actionListener="#{testEjbTimerTx.setTimerNow}"/>
                      <h:commandButton value="Test EJB business method transaction"
                                       actionListener="#{testEjbTimerTx.timerFired}"/>
                  </h:form>
      

      EJB class:

      import org.joda.time.LocalTime;
      
      import javax.annotation.Resource;
      import javax.ejb.*;
      import javax.inject.Named;
      import javax.naming.InitialContext;
      import javax.naming.NamingException;
      import javax.transaction.Synchronization;
      import javax.transaction.TransactionSynchronizationRegistry;
      
      @Named
      @Singleton
      public class TestEjbTimerTx {
      
          @Resource
          private TimerService timerService;
      
          public static final String TRANSACTION_SYNCHRONIZATION_REGISTRY_JNDI_NAME = "java:comp/TransactionSynchronizationRegistry";
      
          @Timeout
          public void timerFired() {
              System.out.println("TEST TIMER BEGIN:");
              try {
                  TransactionSynchronizationRegistry txRegistry = (TransactionSynchronizationRegistry) new InitialContext().lookup(
                          TRANSACTION_SYNCHRONIZATION_REGISTRY_JNDI_NAME
                  );
                  System.out.println("timerFired(): txKey = " + txRegistry.getTransactionKey());
                  txRegistry.registerInterposedSynchronization(new TxListener());
              } catch (NamingException e) {
                  System.out.println("timerFired(): errorMessage = " + e.getMessage());
              }
              System.out.println("TEST TIMER END");
          }
      
          public void setTimerNow() {
              LocalTime localTime = new LocalTime().plusSeconds(3);
              ScheduleExpression schedule = new ScheduleExpression().second(localTime.getSecondOfMinute())
                      .minute(localTime.getMinuteOfHour()).hour(localTime.getHourOfDay());
      
              TimerConfig timerConfig = new TimerConfig();
              timerConfig.setPersistent(false);
      
              timerService.createCalendarTimer(schedule, timerConfig);
          }
      
          public static class TxListener implements Synchronization {
              @Override
              public void beforeCompletion() {}
      
              @Override
              public void afterCompletion(int i) {
                  try {
                      TransactionSynchronizationRegistry txRegistry = (TransactionSynchronizationRegistry) new InitialContext().lookup(
                              TRANSACTION_SYNCHRONIZATION_REGISTRY_JNDI_NAME
                      );
                      System.out.println("afterCompletion(): txKey = " + txRegistry.getTransactionKey());
                  } catch (NamingException e) {
                      System.out.println("afterCompletion(): errorMessage = " + e.getMessage());
                  }
              }
          }
      }
      

      Attachments

        Activity

          People

            romain.manni-bucau Romain Manni-Bucau
            donatasc Donatas Ciuksys
            Votes:
            0 Vote for this issue
            Watchers:
            3 Start watching this issue

            Dates

              Created:
              Updated:
              Resolved: