A guide to creating and triggering events in Spring Boot applications.
Introduction
In the Spring Boot application, the Application Events allow you to trigger or
send an ApplicationEvent to other components so they can interact with
other components in a specific scenario.
What are application events?
Application can handle various events, such as application startup and
shutdown. For example, we may need to initialize certain resources or send
alerts when the system goes down. The Spring Framework provides support for
application events, publishing events, listening events, and handling
events.
We can trigger events based on specific conditions. We can trigger an event when we delete a record from the database, or we can send a mail when we complete a transaction.
These events can be used to perform tasks like logging, auditing, caching, or even sending notifications.
We can trigger events based on specific conditions. We can trigger an event when we delete a record from the database, or we can send a mail when we complete a transaction.
These events can be used to perform tasks like logging, auditing, caching, or even sending notifications.
Publish-subscribe model
Spring Boot follows the publish-subscribe model. The publishing component notifies all subscribers about the occurrence of an event, allowing them to react accordingly. The event publication occurs synchronously.The publisher publishes the event without knowing who the receiver will be. Similarly, the receiver does not know who the sender is. This loosely couples the publisher and receiver enabling maintenance and flexibility.
The event receiver or event listener can listen to multiple events from different publishers at the same time.
Create an event
We can create a model class that extends the ApplicationEvent class. This model class acts as a custom event that stores information about the event. The handler can use this information to perform various tasks
import org.springframework.context.ApplicationEvent;
// before 4.2
public class AlertEvent extends ApplicationEvent {
private String eventType;
public AlertEvent(String eventType) {
super(eventType);
this.eventType = eventType;
}
public String getEventType() {
return eventType;
}
}
If you are using Spring 4.2, we don't need to extend the
ApplicationEvent class.
public class AlertEvent {
private String eventType;
public AlertEvent(String eventType) {
super(eventType);
this.eventType = eventType;
}
}
Publish an event
We will create a Publisher class that @Autowired the ApplicationEventPublisher and use the publishEvent() method to publish the event.
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.stereotype.Component;
import com.springboot.example.model.AlertEvent;
@Component
public class AlertEventPublisher {
@Autowired
private ApplicationEventPublisher publisher;
public void publish(String message) {
AlertEvent event = new AlertEvent(message);
publisher.publishEvent(event);
}
}
Handle Event
The listener class must implement ApplicationListener and override the onApplicationEvent() method, which handles the event. By default, Spring Boot sends all events to the listener. Thus, we have to filter and handle the events accordingly.The ApplicationListener takes the generics class, so Spring will send an event that matches the generics class. Here, AlertEvent is the generic class, so whenever an alert event occurs, the Spring Boot will notify the AlertEventListener.
import org.springframework.context.ApplicationListener;
import org.springframework.stereotype.Component;
import com.springboot.example.model.AlertEvent;
@Component
public class AlertEventListener implements ApplicationListener < AlertEvent > {
@Override
public void onApplicationEvent(AlertEvent event) {
System.out.println("Inside the Listener, got Alert Event " + event.getEventType());
}
}
Using Annotation
With Spring 4.1, we can easily register an event listener by annotating a method with @EventListener.The generic class can be defined either in the annotation or as a method argument. This allows the method to handle only the specified event. If we want our method to handle multiple events, then we can define them in the annotation.
import org.springframework.context.event.AlertEventListener;
import org.springframework.stereotype.Component;
import com.springboot.example.model.AlertEvent;
@Component
public class AlertEventListener {
@EventListener
void handleAlertEvent(AlertEvent event) {
System.out.println("Inside the Listener, got Alert Event " + event.getEventType());
}
}
How to handle events in asynchronous
Application events are published and handled in a synchronous way. Publishers block until all listeners have finished processing events.In some cases, we want an event handler to handle the events in an async way. We need to add @Async to the event listener method.
import org.springframework.context.event.AlertEventListener;
import org.springframework.stereotype.Component;
import org.springframework.scheduling.annotation.Async;
import com.springboot.example.model.AlertEvent;
@Component
public class AlertEventListener {
@Async
@EventListener
void handleAlertEvent(AlertEvent event) {
System.out.println("Inside the Listener, got Alert Event " + event.getEventType());
}
}
For the @Async annotation to work, we need to add one more annotation to our @SpringBootApplication class with @EnableAsync.
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.annotation.EnableAsync;
@SpringBootApplication
@EnableAsync
public class SpringBootCustomEventExample {
public static void main(String[] args) {
SpringApplication.run(SpringBootCustomEventExample.class, args).close();
}
}