Spring Boot Exception Handler not working with EventHandler TransactionPhase.AFTER_COMMIT

In Spring Boot, when there is an exception thrown in a event handler, it is not correctly handled by my exception handler This occurs only if the event handler is annotated with

@TransactionPhase.AFTER_COMMIT 

My Code:

Controller

@PostMapping("/endpoint")
public ResponseEntity<?> doStuff() {
service.doStuff();
}
 

Service

@Transactional
public void doStuff() {
 eventPublisher.publishEvent(new MyAwesomeEvent());
}

Event Handler

@TransactionalEventListener(phase = TransactionPhase.AFTER_COMMIT)
@Transactional(propagation = Propagation.REQUIRES_NEW)
public void handleAwesomeEvent(MyAwesomeEvent event) {
// Wont be caught !
throw new RuntimeException();
}

Exception Handler

@ExceptionHandler({Exception.class}) 
public ResponseEntity<Object> fallbackHandler(Exception ex, HttpServletRequest request) {
//Won't be called
}

Interestingly enough when I change the annotation from

@TransactionalEventListener(phase = TransactionPhase.AFTER_COMMIT)

to

@TransactionalEventListener(phase = TransactionPhase.BEFORE_COMMIT)

the exception handler works.

  • please refer the TransactionalEventListener if the TransactionPhase is set to AFTER_COMMIT (the default), AFTER_ROLLBACK, or AFTER_COMPLETION, the transaction will have been committed or rolled back already. Try to add Event Handler AFTER_ROLLBACK, or AFTER_COMPLETION

    – 

  • Say I want to send an email once the transaction is completed successfully (TransactionPhase.AFTER_COMMIT) and during the email sending there is an exception. After_Rollback and After_Completion are incorrect in this case

    – 




  • My view is you are mixing two different responsibilities. 1st action- performing some business logic and 2nd action is sending email. If 1st action completed we need to commit the transaction and 2nd action failed we don’t want to rollback 1st action. My suggestion is set noRollbackFor for email exception and handle email exception separately and take required actions @Transactional(noRollbackFor = { EmailException.class })

    – 

Leave a Comment