DEV Community

Rachid
Rachid

Posted on • Edited on

๐Ÿš€ Spring Boot Pro Tip: The Hidden Power of @TransactionalEventListener!

Did you know that Spring Boot allows you to execute code after a transaction is committed using @TransactionalEventListener? Most developers use @EventListener, but this hidden gem ensures your logic only runs if the transaction succeeds.
Problem: When Events Fire Too Early
Imagine you're saving a user and sending a welcome email before the transaction commits:

public class UserCreatedEvent {
    private final User user;

    public UserCreatedEvent(User user) {
        this.user = user;
    }

    public User getUser() {
        return user;
    }
}
Enter fullscreen mode Exit fullscreen mode
@Component
public class UserEventListener {
    @EventListener
    public void handleUserCreated(UserCreatedEvent event) {
        emailService.sendWelcomeEmail(event.getUser()); //  Runs even if transaction fails!
    }
}
Enter fullscreen mode Exit fullscreen mode

If the database transaction fails, the email is still sent, leading to inconsistencies.

Solution: @TransactionalEventListener

@Component
public class UserEventListener {
    @TransactionalEventListener
    public void handleUserCreated(UserCreatedEvent event) {
        emailService.sendWelcomeEmail(event.getUser()); //  Runs ONLY if the transaction is committed!
    }
}
Enter fullscreen mode Exit fullscreen mode

Now, the event fires only if the transaction succeeds!
How to Use It in a Spring Boot App

  1. Publish an Event Inside a Transaction
@Service
public class UserService {
    @Autowired private ApplicationEventPublisher publisher;
    @Autowired private UserRepository userRepository;

    @Transactional
    public void createUser(String name, String email) {
        User user = userRepository.save(new User(name, email));
        publisher.publishEvent(new UserCreatedEvent(user)); //  Event is published
    }
}
Enter fullscreen mode Exit fullscreen mode
  1. Listen to the Event After Transaction Commits
@Component
public class UserEventListener {
    @TransactionalEventListener
    public void handleUserCreated(UserCreatedEvent event) {
        System.out.println("User created: " + event.getUser().getEmail());
    }
}
Enter fullscreen mode Exit fullscreen mode

Guaranteed execution only if the transaction is successful.
Why is This Useful?
Prevents sending emails, messages, or notifications for failed transactions.
Ensures event-driven logic only executes when the database is consistent.
Perfect for logging, auditing, and triggering external services.

Top comments (0)