Uploaded image for project: 'Weld'
  1. Weld
  2. WELD-2489

TransactionServices and after completion issue

    XMLWordPrintable

Details

    Description

      I'm currently implementing a solution to leverage the transactional event facilities of CDI in Java SE.

      I've implemented:

      • A TransactionServices class and made sure it's loaded via the ServiceLoader
      • A UserTransaction class
      • A Transactional interceptor

      And I have added the weld-jta module to my project.

      Everything is fine until I invoke afterCompletion() of the synchronization observer.

      Test conditions:

          private void onInit(@Observes @Initialized(ApplicationScoped.class) Object event) {
              Schedulers.single().scheduleDirect(this::fireEvent, 1, TimeUnit.SECONDS);
          }
      
          @Transactional
          public void fireEvent() {
              LOGGER.info("firing event");
              events.fire("hello");
              LOGGER.info("event fired");
          }
      
          @Transactional
          private void onEvent(@Observes(during = TransactionPhase.AFTER_SUCCESS) String event) {
              LOGGER.info(() -> String.format("event received after success: %s", event));
          }
      

      Please note that the Transactional annotation in the example above is my interceptor binding annotation, not the JTA's one.

      When afterCompletion is invoked, the transaction related to 'fireEvent' is committed. A new transaction is started when the observer method is invoked.
      When the observer method returns, the later transaction (related to 'onEvent') is committed. But then, a new event is fired again and it's value is null, and in the logs I can see:

      InfraUserTransaction - begin new transaction
      TransactionTest - firing event
      TransactionTest - event fired
      InfraUserTransaction - committing transaction
      InfraUserTransaction - transaction committed
      InfraUserTransaction - notifying after completion - STATUS_COMMITTED
      InfraUserTransaction - begin new transaction
      TransactionTest - event received after success: hello
      InfraUserTransaction - committing transaction
      InfraUserTransaction - transaction committed
      InfraUserTransaction - notifying after completion - STATUS_COMMITTED
      ERROR Event - WELD-000401: Failure while notifying an observer [BackedAnnotatedMethod] private steappe.production.application.TransactionTest.onEvent(@Observes String) of event null.
      java.lang.IllegalAccessError: tried to access method steappe.production.application.TransactionTest.onEvent(Ljava/lang/String;)V from class steappe.production.application.TransactionTest$Proxy$_$$_WeldSubclass
      InfraUserTransaction - after completion notified
      InfraUserTransaction - after completion notified
      

      As you can see, the list of events to distribute after the completion of the first commit seems to contain some remaining of the first distributed event. Then, after the second commit, WELD tries to distribute this event again.

      I had a look to the source code of weld-jta, and I can see that:

      • The synchronization observer is set when an event is fired
      • The synchronization observer is not cleared when a new transaction is started while an AFTER_SUCCESS event is being notified

      I had a look to the CDI specifications, and I could not see anything that would explain the reason why this code should not work.

      Did I misunderstand the specifications? Did I do something wrong? Or is there a bug?

      Attachments

        Activity

          People

            Unassigned Unassigned
            steappe Stéphane Appercel (Inactive)
            Votes:
            0 Vote for this issue
            Watchers:
            2 Start watching this issue

            Dates

              Created:
              Updated:
              Resolved: