How to implement event driven programming in Spring Boot?

There are several paradigms of programming:

Procedural ,Object Oriented , Functional , Event Oriented etc.

Each of them comes with their own benefits and disadvantages.

Most of the programming done in Java is Object Oriented since the language itself is object oriented.

But what if you want to do event driven programming or at the least implement part of your functionality event driven?

Event driven programming let’s you decouple business logic from the event source.

Say you want to send an email to user whenever they register , you can implement this in an event driven way moving the emailing part to “a listener” which listens to “register” event.

Later if you want you can register a different “listener” without much change in code.

Spring Boot provides this functionality through Spring Events.

Let’s see how to implement it.

We will create a dummy API to add a user to the system.

Let’s say there is a requirement to audit all service calls made to the system.

We can move the auditing part event driven.

You need to have three main components to implement Spring Events

  1. An Event class
  2. A Publisher method
  3. A Subscriber method

Let’s see how to implement them:

STEP1: Create an Event class

This is a simple POJO:

package com.example.spring.event;
public class UserEvent{
	private String name;
	public UserEvent(String name) { = name;
	public String getName() {

This represents the Add User event.

STEP2: Create a publisher method

We need to create a publisher method which will publish the above User Event.

To create this autowire ApplicationEventPublisher bean to your service class:

package com.example.spring.event;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.stereotype.Component;
public class UserService {
	private ApplicationEventPublisher publisher;
	public void addUser(String user) {
		System.out.println("Adding user "+user);
		this.publisher.publishEvent(new UserEvent("User Added"));
		System.out.println("Method ends");

Whenever a user is added in our example , the publisher publishes an User Event as shown above. In the above example I am just passing a string to the User Event , you can also accept custom objects as per the use case.

STEP3: Create a listener method

Once an event is published there should be a listener to handle that event.

Create a method and annotate it with @EventListener annotation:

package com.example.spring.event;
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Component;
public class UserEventListener{
	public void handler(UserEvent event) {
		System.out.println("Auditing the event "+event.getName());

STEP4: Test

Now let’s test our changes.

I created a Test Controller class like below:

package com.example.spring.event;
import java.util.Map;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
public class TestController {
	private UserService service;
	public String addUser(@RequestBody Map<String,String> request) {
		return "success";

It just calls the User Service which emits an “UserEvent”.

The listener “UserListener” listens for the event and does the auditing.

On hitting the above API through postman I got this:

Console logs:

The log which I added in “UserEventListener” got invoked as expected.

That’s it!

Asynchronous Events:

Now what if you want the events to be asynchronous?

You don’t want to block the user for auditing logic, it can happen in a parallel thread.

To do this all you have to do is use the annotation @Async on the Event listener.

In addition you need to enable asynchronous execution by adding the annotation @EnableAsync on a configuration class or to the main class:

package com.example.spring.event;
import org.springframework.context.event.EventListener;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;
public class AuditListener {
	public void handler(AuditEvent event) {
		System.out.println("Auditing the event "+event.getName());

Main class:

package com.example.spring.event;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.annotation.EnableAsync;
public class EventdrivenApplication {
	public static void main(String[] args) {, args);

That’s it!

Now the auditing logic is executed asynchronously without blocking the main thread.

Here is the link to the entire code:

Handling multiple events:

You can also use the same event listener to listen for multiple events.

To do this , just pass the event classes as parameter to the @EventListener annotation:

@EventListener(classes = UserEvent.class,OrderEvent.class)
	public void handler() {
		System.out.println("Auditing the event "+event.getName());

Thus Spring Boot provides a simple interface to handle event driven programming.





Leave a Reply

%d bloggers like this: