In this post, we will explore the creation of an application event and the process of listening for application events within a Spring Boot application. In Spring Boot, the ApplicationEventPublisher class is used to publish application events. To listen for and execute these events when they occur, the @EventListener annotation is used. Furthermore, the application event listener is capable of executing in either synchronous or asynchronous mode, allowing for parallel execution when configured in asynchronous mode. The provided code includes an example demonstrating how to publish an application event and effectively listen for its occurrence.

The event-driven programming paradigm operates akin to the publisher-subscriber model. When an event is published, all subscribers receive and process it. These events can be processed either synchronously or asynchronously. Implementing event-driven programming in a Spring Boot application involves three essential steps.

  1. The application event
  2. Event Publisher
  3. Event Listener

Step 1: Create an Event Class

The event class functions as a Plain Old Java Object (POJO) with properties accompanied by getter and setter methods. It serves as the conduit for transferring data from the event publisher to the event listeners. Any pertinent data that needs to be communicated from a publisher to all event listeners is encapsulated within the event class. Upon the occurrence of an event, the data set within the event class is disseminated to all registered listener classes.

MyEvent.java

package com.test;

public class MyEvent {
	private String name;

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}
	
}

Step 2: Create Event Publisher Class

The event publisher class is utilized within the Spring Boot application to broadcast an event. To accomplish this, employ the Spring Boot class ApplicationEventPublisher. In your publisher class, autowire the ApplicationEventPublisher class. To publish an event, utilize the publishEvent API within the ApplicationEventPublisher class.

Firstly, establish an event class and assign the values intended for transmission to all listeners. Subsequently, pass the event object to the publishEvent method of the ApplicationEventPublisher class. This action ensures that the event is disseminated to all registered listener classes.

In the ensuing example, a MyEvent class object is instantiated and provided with a value. The listener class invokes the publishEvent method by passing an event object. When the addMyEvent method is called, the listener generates an event object and publishes it within the context of event-driven programming.

MyPublisher.java

package com.test;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.stereotype.Component;

@Component
public class MyPublisher {
	@Autowired
	private ApplicationEventPublisher publisher;

	public void addMyEvent(String name) {

		System.out.println("PUBLISHER: Starting MyEvent - " + name);

		MyEvent event = new MyEvent();
		event.setName(name);
		this.publisher.publishEvent(event);

		System.out.println("PUBLISHER: Starting MyEvent - " + name);
	}
}

Step 3: Create Event Listener Class

The event listener class patiently awaits the occurrence of an event. Upon the event’s initiation, the corresponding listener method within the class is invoked and executed. Each event listener associated with a particular event is summoned in a sequential order, executing one listener at a time. In the event that a listener is configured in asynchronous mode, it runs concurrently, and the publisher doesn’t wait for the listeners’ responses.

A listener class will feature a method designated for listening to events, adorned with the @EventListener annotation. The event class itself is passed as a parameter to the event listener method. When an event transpires, it is broadcast to all registered event listeners. If a listener method is linked to the triggered event class, the associated event listener method is invoked. Consequently, for the triggered event class, all registered event listener methods are executed sequentially.

In the forthcoming example, a listener class encompasses a listener method with the @EventListener annotation. The listener method accepts an Event class parameter. When an event of the specified class is triggered, the corresponding listener method is invoked.

MyListener.java

package com.test;

import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Component;

@Component
public class MyListener {

	@EventListener
	public void handler(MyEvent event) {
		System.out.println("LISTENER: Name of MyEvent - " + event.getName());
	}

}

Step 4: Publish an Event

To publish an event in a Spring Boot application, leverage the publish method. In the provided example, a RESTful web service is established to invoke the publisher method. The REST controller method encompasses an API call to the publisher method. The REST controller class is automatically wired with the publisher class. Consequently, upon calling the REST API, the REST controller utilizes the publisher class to publish the event.

TestController.java

package com.test;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class TestController {

	@Autowired
	MyPublisher publisher;
	
	@GetMapping(value = "/startEvent")
	public String start(@RequestParam String name) {
		publisher.addMyEvent(name);
		return "Event Started";
	}

}

Step 5: Listening an Event

When the publisher is invoked from the RESTful web service, the listener class is automatically triggered, leading to the execution of the listener method. The publisher method will patiently wait until all listener methods have been successfully executed before returning control to the publisher method.

The console log below illustrates the functioning of the event-driven program within the Spring Boot application. Initially, the publisher’s log is displayed, followed by the invocation of the listener method and the corresponding log. Subsequently, control is transferred back to the publisher, concluding with the printing of the final log in the publisher method.

2023-06-09 23:24:16.316  INFO 7864 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat initialized with port(s): 8080 (http)
2023-06-09 23:24:16.344  INFO 7864 --- [           main] o.apache.catalina.core.StandardService   : Starting service [Tomcat]
2023-06-09 23:24:16.344  INFO 7864 --- [           main] org.apache.catalina.core.StandardEngine  : Starting Servlet engine: [Apache Tomcat/9.0.65]
2023-06-09 23:24:16.491  INFO 7864 --- [           main] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring embedded WebApplicationContext
2023-06-09 23:24:16.491  INFO 7864 --- [           main] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 1328 ms
2023-06-09 23:24:16.909  INFO 7864 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat started on port(s): 8080 (http) with context path ''
2023-06-09 23:24:16.923  INFO 7864 --- [           main] c.t.SpringBootEventDrivenApplication     : Started SpringBootEventDrivenApplication in 2.36 seconds (JVM running for 4.141)
2023-06-09 23:25:10.721  INFO 7864 --- [nio-8080-exec-1] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring DispatcherServlet 'dispatcherServlet'
2023-06-09 23:25:10.722  INFO 7864 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet        : Initializing Servlet 'dispatcherServlet'
2023-06-09 23:25:10.722  INFO 7864 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet        : Completed initialization in 0 ms
PUBLISHER: Starting MyEvent - Kim
LISTENER: Name of MyEvent - Kim
PUBLISHER: Starting MyEvent - Kim

Leave a Reply