Affects: \


Spring webflux does not support @TransactionalEventListener to publish event after transaction completed. So what i need to do to publish event only when transaction completed in Spring webflux?

Comment From: jhoeller

As of 6.1, @TransactionalEventListener can work with thread-bound transactions managed by PlatformTransactionManager as well as reactive transactions managed by ReactiveTransactionManager. For the former, as of #30244, listeners are guaranteed to see the current thread-bound transaction. Since the latter uses the Reactor context instead of thread-local variables, the transaction context needs to be included in the published event instance as the event source, e.g.:

TransactionContextManager.currentContext()
    .map(source -> new PayloadApplicationEvent<>(source, "myPayload"))
    .doOnSuccess(this.eventPublisher::publishEvent)

Or via the new TransactionalEventPublisher delegate:

new TransactionalEventPublisher(this.eventPublisher).publishEvent(source -> new PayloadApplicationEvent<>(source, "myPayload"))

new TransactionalEventPublisher(this.eventPublisher).publishEvent("myPayload")

Comment From: koenpunt

It's also possible to use the TransactionSynchronizationManager to perform some code when a transaction finishes.

For example in kotlin:

@Transactional
suspend fun performSomething() {

  userRepository.register()

  val manager = TransactionSynchronizationManager.forCurrentTransaction().awaitSingle()

  manager.registerSynchronization(object : TransactionSynchronization {
      override fun afterCommit(): Mono<Void> = mono {
          sendEmail()
      }
  })
}

Or similar in Java:

@Transactional
public void performSomething() {

    userRepository.register();

    TransactionSynchronization transactionSynchronization =
            TransactionSynchronizationManager.forCurrentTransaction();

    if (transactionSynchronization != null) {
        transactionSynchronization.registerSynchronization(new TransactionSynchronization() {
            @Override
            public void afterCommit() {
                sendEmail();
            }
        });
    }
}