-
Bug
-
Resolution: Won't Do
-
Major
-
None
-
3.0.3.Final
-
None
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?