Search code examples
springspring-bootspring-transactions

How to make event listener synchronous to publish of application event in Spring Boot


I have some method which is publishing an application event (MyEvent) and then I am logging "done publishing". The problem I am having is log statement is executed first and then MyEvent listener is getting invoked. How do i make sure execution order is like following:-

  1. publish event

  2. listen event

  3. executing log statement [see code below]

    @Transactional(propagation = Propagation.REQUIRES_NEW)
    public void method() {
    
           //save something in db
          applicationEventPublisher.publishEvent(new MyEvent(...params));
          log.info("done publishing");
        });
    
      }
    
      @TransactionalEventListener
      @Order(2)
      public void handle(MyEvent myEvent) {
        //do something
      }
    
    

Solution

  • The @TransactionalEventListener is an event listener that is bound to the current transaction. It will execute the event at the given phase, the default is AFTER_COMMIT.

    So in your case the event will be executed after the execution of method(). So the event will be fired, but not yet executed by the said listener. Hence the behaviour you see.

    The event is in fact, by default, already delivered synchronously and not a-synchronously (which you expect due to the behaviour you see).

    If you want to execute the event directly use a regular @EventListener instead of an @TransactionalEventListener.

    @EventListener
    @Order(2)
    public void handle(MyEvent myEvent) {
      //do something
    }
    

    Now the code will behave as you expect and want.