Spring Modulith Events

228 views Asked by At

I am publishing an Event in a method that is annotated with the annotation @Transactional. The Listener is a annotated with @TransactionalEventListener.

The above setup results in sync(We can use @Async to change it) event processing and the Event is also stored into the Database by spring modulith eventing itself(I am using postgres).

However If I make the publisher non-transactional(i.e remove the @Transactional annotation) The Listener does not listen and execute the event that was meant for it. Nor do we get a database entry since no listener was able to process it.

I can change the Listener to @EventListener to listen a non-transactional event but I loose DB event persistence in this case

I want the publisher to be free to decide if it wants to be transactional/non-transactional. The Listener must listen and execute the event meant for it regardless and persist the event into DB.

HELP PLEASE!

Listener

    @TransactionalEventListener
    public void notificationEvent(ProductEvent event) {
        System.out.println("Listener 1 Start");
        System.out.println("Listener 1 End");
    }

Publisher

//    @Transactional
    public void publishEvent() {
        System.out.println("Publisher Start");
        ProductEvent productEvent = new ProductEvent("Product A", "THIS IS PRODUCT", 777);
        applicationEventPublisher.publishEvent(productEvent);
        System.out.println("Publisher End");
    }
1

There are 1 answers

0
Ish Mahajan On

It is important to understand why it is not working in the first place.

  1. Nature of @TransactionalEventListener

    • It's specifically designed to handle events within a transactional context.
    • It ensures event listeners execute within the same transaction as the publishing method.
    • This guarantee is essential for consistency and data integrity.
  2. Transaction Synchronization

    • Spring's transaction infrastructure relies on transaction synchronization. Events published within a transaction are synchronized with its lifecycle.
    • Listeners are invoked only when the transaction is committed successfully.
  3. Non-Transactional Context

    • When events are published outside a transaction, there's no transaction to synchronize with.
    • The @TransactionalEventListener mechanism doesn't apply.

I am not aware of any Spring boot feature that can do it for you out of the box. However, You can initiate a new transaction after capturing non-transactional events and persist it manually in the database.