question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

AFTER_SUCCESS Observers and Events fired from within EntityListeners

See original GitHub issue

There 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:open
  • Created 3 years ago
  • Reactions:2
  • Comments:12 (5 by maintainers)

github_iconTop GitHub Comments

1reaction
manovotncommented, Feb 18, 2021

@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 of TransactionalServices which contains a registerSynchronization method. Technically speaking, I think they could just register interposed transaction instead of standard one, but apparently, no integrator did that.

0reactions
tomjenkinsoncommented, Feb 24, 2021

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:

  1. Could be complex to understand, in that if a user registers the Synchronization during beforeCompletion either we would possibly decide some concept of ordering would now take place and the Synchronization would be called after previously registered ones or perhaps we would decide the beforeCompletion will silently not be called or something else
  2. Might be restricted somehow by distributed use cases where the coordinator implementation is remote

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.

Read more comments on GitHub >

github_iconTop Results From Across the Web

AFTER_SUCCESS Observers and Events fired from within ...
There currently exists an issue where if a event is fired from within an JPA EntityListener (@PostUpdate for example) the event may not...
Read more >
Check whether a JTA transaction is successfully committed
If no transaction is in progress when the event is fired, they are notified at the same time as other observers.
Read more >
Hibernate Community • View topic - CDI events in JPA callbacks
We use @EntityListeners where we fire a CDI event inside a method annotated with @PreUpdate. These are the CDI observer methods listening to ......
Read more >
Events
An observer method is notified if the set of observer qualifiers is a subset of the fired event's qualifiers. Assume the following observers...
Read more >
How to intercept entity changes with Hibernate event listeners
In this article, we are going to see how the Hibernate event listeners work and how you add your ... Registering the custom...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found