Reputation: 160
i have a service and two TransactionalEventListeners with phase BEFORE_COMMIT, one listens for EventA, the other for EventB. Service publishes EventA -> EventAListener is invoked and publishes another event - EventB. EventBListener is not invoked and the event is ignored. Example code:
@Service
@Transactional
public class ExampleService {
private ExampleEntityRepository repository;
private ApplicationEventPublisher applicationEventPublisher;
public void exampleMethod() {
repository.save(new ExampleEntity("entity"));
applicationEventPublisher.publishEvent(new EventA(this));
}
}
//==================================================
@Service
@Transactional
public class EventAListener {
private ExampleEntityRepository repository;
private ApplicationEventPublisher applicationEventPublisher;
@TransactionalEventListener(value = EventA.class, phase = TransactionPhase.BEFORE_COMMIT)
public void handle(EventA event) {
repository.save(new ExampleEntity("entityA"));
applicationEventPublisher.publishEvent(new EventB(this));
}
}
//==================================================
@Service
@Transactional
public class EventBListener {
private ExampleEntityRepository repository;
@TransactionalEventListener(value = EventB.class, phase = TransactionPhase.BEFORE_COMMIT)
public void handle(EventB eventB) {
repository.save(new ExampleEntity("entityB"));
}
}
//==================================================
// Alternative EventAListener version
@Service
@Transactional
public class EventAListener {
private ExampleEntityRepository repository;
@TransactionalEventListener(value = EventA.class, phase = TransactionPhase.BEFORE_COMMIT)
public EventB handle(EventA event) {
repository.save(new ExampleEntity("entityA"));
return new EventB(this);
}
}
After service method is executed, there are 2 rows in database - "entity" and "entityA".
Alternative EventAListener version works the same way.
Setting EventBListener fallbackExecution to 'true' does not make any change - EventBListener is not invoked.
Changing EventBListener phase to AFTER_COMMIT works - EventB is processed, but in another transaction.
Why is EventB not processed?
Upvotes: 6
Views: 6375
Reputation: 1216
I think your problem might be related to the one posted by Wojtek here: https://spring.io/blog/2015/02/11/better-application-events-in-spring-framework-4-2
To which the Spring developer answers as follows:
BEFORE_COMMIT
is not "anytime you want during the transaction". It's really before commit. What you're doing is using the transaction like nothing asked for a commit. Something did.
So it seems the chaining of BEFORE_COMMIT events is not possible, and perhaps performing another transactional operation during that phase is not supported (even though it appears to work)?
I think this area could be documented better, because to most people "before commit" simply means "before something was committed", and it isn't really clear what operations can be performed when that event handler is invoked.
Upvotes: 7