When firing an CDI event from another transaction synchronisation, the {{TransactionalObserverNotifier}} fails to defer the notification, because registering the {{TransactionSynchronizedRunnable}} fails with an "ARJUNA016082: Synchronizations are not allowed".
In my case this for example happens when I fire the event from a JPA Lifecycle listener, which is triggered by the flush call on the {{EntityManager}} through Hibernates {{JtaTransactionCoordinatorImpl}} bound in the {{JCAOrderedLastSynchronizationList}}.
The current behaviour has one very odd side effect: namely, the exception is swallowed in the {{TransactionalObserverNotifier}}, which then notifies a filtered set of observers, assuming that a rollback exception must have occurred. As a result, the {{AFTER_FAILURE}} observers are invoked and not the {{AFTER_SUCCESS}} observers, even though the transaction commits successfully (because the {{IllegalStateException}} was caused by not being able to register the synchronisation, and not due to the fact that the transaction failed altogether).
I think the error handling should be fixed, because it seems odd that {{AFTER_FAILURE}} observers get invoked for a successful transaction.
Furthermore it would be nice to actually support events with transactional observers to be fired from another synchronisation. I am not entirely sure whether it is feasible to support, but I am having a couple of ideas:
* an implementation where we just register a synchronisation by default and handle the synchronisation from there, rather than registering the synchronisation on the transaction just in time * Hook on the {{JCAOrderedLastSynchronizationList}} instead of the Transaction, just as Hibernate seems to do * Register an _interposed_ synchronisation with the {{TransactionSynchronizationRegistry}} rather than a regular synchronisation.
Some more background (a stack trace) can be found in the Stackoverflow issue: https://stackoverflow.com/questions/47953827/defer-transactionalobservernotifier-fails-with-arjuna016082-synchronizations-ar Also of interest can be the blogpost describing how to fire CDI events from JPA lifecycle listeners: http://blogs.bytecode.com.au/glen/2014/01/09/firing-cdi-events-from-a-jpa-entitylistener.html . Keep in mind that this has become much more natural to do since CDI injection is since allowed into {{EntityListeners}} as of JPA 2.1. |
|