Skip to content

Publish event for @TransactionalEventListener with Spring WebFlux #27515

Closed
@hoangshiva

Description

@hoangshiva

Affects: <Spring Framework 5.3.10>


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?

Activity

added
in: webIssues in web modules (web, webmvc, webflux, websocket)
on Nov 8, 2021
changed the title [-]Publish event after transaction completed in Spring webflux[/-] [+]Publish event for @TransactionalEventListener with Spring WebFlux[/+] on Aug 1, 2023
self-assigned this
on Aug 1, 2023
added
in: dataIssues in data modules (jdbc, orm, oxm, tx)
and removed on Aug 1, 2023
added this to the 6.1.0-M4 milestone on Aug 1, 2023
jhoeller

jhoeller commented on Aug 1, 2023

@jhoeller
Contributor

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")
koenpunt

koenpunt commented on Aug 1, 2023

@koenpunt
Contributor

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();
            }
        });
    }
}
changed the title [-]Publish event for @TransactionalEventListener with Spring WebFlux[/-] [+]Publish event for `@TransactionalEventListener` with Spring WebFlux[/+] on Aug 2, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

in: dataIssues in data modules (jdbc, orm, oxm, tx)in: webIssues in web modules (web, webmvc, webflux, websocket)type: enhancementA general enhancement

Type

No type

Projects

No projects

Relationships

None yet

    Development

    No branches or pull requests

      Participants

      @koenpunt@rstoyanchev@jhoeller@spring-projects-issues@hoangshiva

      Issue actions

        Publish event for `@TransactionalEventListener` with Spring WebFlux · Issue #27515 · spring-projects/spring-framework