AFTER_SUCCESS Observers and Events fired from within EntityListeners
See original GitHub issueThere currently exists an issue where if a event is fired from within an JPA EntityListener (@PostUpdate
for example) the event may not be reliably observed via an @Observes(during = TransactionPhase.AFTER_SUCCESS)
The issue comes down to what state Transaction is in when the entityManager.flush is called (trigging the post update for example). If the entityManager.flush is called manually then the @PostUpdate
is run while the transaction is active and things will work fine. If however, the flush is automatically called via the ending of an @Transactional
method then when the @PostUpdate
is run the transaction has moved past the ACTIVE status and the synchronization cannot be added to the transaction. No error is thrown and the event will silently not be observed.
Possible thoughts were having the the CDI event registered with an TransactionSynchronizationRegistry#registerInterposedSynchronization
It appears that you could do something like
@PostUpdate
public void postUpdate(Ticket entity) {
try {
TransactionSynchronizationRegistry registery = (TransactionSynchronizationRegistry) new InitialContext().lookup("java:comp/TransactionSynchronizationRegistry");
registery.registerInterposedSynchronization(new MySyncronization());
}
catch (NamingException e) {
throw new RuntimeException(e);
}
}
public class MySyncronization implements javax.transaction.Synchronization {
static final Logger log = Logger.getLogger(MySyncronization.class);
@Override
public void beforeCompletion() {
}
@Override
public void afterCompletion(int status) {
if (status==3){
CDI.current().getBeanManager().fireEvent(EntityEvent.updated(entity));
}
}
}
This appears to accomplish what we want, but obviously is not friendly to use.
The current thought is to potentially clarify in the spec that CDI events should use an Interposed Synchronization either all the time or only if a standard synchronization cannot be obtained, but that may have ramifications that I am not considering.
This jumps off from https://issues.redhat.com/browse/WELD-2444
Issue Analytics
- State:
- Created 3 years ago
- Reactions:2
- Comments:12 (5 by maintainers)
@codylerum thanks for creating the issue and restarting the discussion.
I did re-read the issue and all other links but I am not JTA expert (so apply a pinch of salt, please) - from this discussion that @ochaloup started after WELD-2444 I got the impression that using interposed synchronization would be against some of the bits in JTA spec. Maybe @ochaloup could confirm or deny that 😉
That being said, the way Weld implements
Synchronization
registration now is that integrators (such as WildFly) need to provide an impl ofTransactionalServices
which contains aregisterSynchronization
method. Technically speaking, I think they could just register interposed transaction instead of standard one, but apparently, no integrator did that.So it seems that at least some implementations in Weld which needs beforeCompletion.
I don’t think it will be easy to make Jakarta Transactions such that it allows adding in more Synchronizations during beforeCompletion but you could ask on the Jakarta Transactions mailing list for input. I am thinking that this feature:
If there are a discrete set of observers identified that only have the need for informing after the transaction completes then a smaller Jakarta Transactions change to allow a new synchronization type that be registered that is only called after a transaction completes and that can be registered while before completion is executing could be helpful and possibly added to that specification.
I think discussing the use case on the Jakarta Transactions mailing list would be useful.