Spring Events

Introduction to Spring Events

In this post, we will be covering Spring Events which is a way to loosely couple component in your application for better design and easy exchange of information.

 

1. Introduction

Spring Events are part of the Spring Framework for the very easy phase of the framework, however, I believe that this is one of the most overlooked features of the Spring Framework. Spring Events provide a lot of features and capabilities and one of the most interesting among those are event publishing provided by ApplicationContext.

Application events are not used that frequently in the real world application, however, Spring Framework internally use a lot of these events to communicate various events, with the introduction of the Spring Boot, it has become more interesting.

Spring 4.1 introduced @EventListener,  annotation driven event Listener which removed all the complexities of defining your EventListner.@EventListener is a core annotation that is handled transparently in a similar fashion as @Autowired and others: no extra configuration is necessary with java config

 

2. Custom Events

To understand it more clearly, we will create and publish a custom Spring Event. Spring provides flexibility to create and publish custom events which by default will be synchronous.

We will work on a  simple example of customer registration, we will publish a simple CustomerRegistration event whenever a new customer registers with our application. We will let all listeners handle this event and perform applicable action (e.g sending email on customer registrations)

2.1 Custom Events

In this example, we will create simple CustomerRegistrationEvent which will be used to store customer data (in our case just customer name)

public class CustomerRegistrationEvent {

    private String name;

    public CustomerRegistrationEvent(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }
}

Before Spring 4.2, we were required to extend ApplicationEvent which is no longer required, this change has its own merits as it is much easier to publish events while it can be hard to trek events in large applications.

 

2.2 Custom Events Listener

As part of our example, we need a listener which should listen to the event being published and make sure to act accordingly in case event published by the service is of interest (if given listener is registered for the given event) 

 

@Component
public class CustomerRegistrationEventListener {

    @EventListener
    void handleRegistration(CustomerRegistrationEvent event){
        System.out.println("Registration event got triggered for customer::  " + event.getName());
    }
}

 

With Spring 4.2, you are not required to implement ApplicationListener or something similar but a simple @EventListener annotation is sufficient to declare it as a Listener.

Spring will create an ApplicationListener instance for the event with a type taken from the method argument. There is no limitation on the number of annotated methods in one class – all related event handlers can be grouped into one class.

 

2.3 Publishing Events

We will create a publisher which will be responsible for the following tasks

  1. It will create an event object.
  2. It will publish that event to all who are listening to this event.

We need ApplicationEventPublisher in our code to simply publish given event.

@Autowired
private ApplicationEventPublisher publisher;

public void publishEvent(final String name) {
    publisher.publishEvent(new CustomerRegistrationEvent(name));
}

 

3. Async Events

As mentioned earlier, these events work in Async mode, which means publisher thread will block until all the listeners (who are listing to this event) have finished processing this event.This can lead to a certain issue in terms of application scaling where we want to run these events in Async mode and let rest of the application to work normally.

To allow Spring to handle events asynchronously, we need to redefine ApplicationEventMulticaster with an executor.

@Bean(name = "applicationEventMulticaster")
ApplicationEventMulticaster applicationEventMulticaster() {
    SimpleApplicationEventMulticaster eventMulticaster = new SimpleApplicationEventMulticaster();
    eventMulticaster.setTaskExecutor(new SimpleAsyncTaskExecutor());
    eventMulticaster.setErrorHandler(TaskUtils.LOG_AND_SUPPRESS_ERROR_HANDLER);
    return eventMulticaster;
}

This will enable asynchronously mode at the global level (at the ApplicationContext level), this means that all method annotated with @EventListener will be executed asynchronously.

Another most easier way is to use @Async annotation

@Async
@EventListener
void handleRegistration(CustomerRegistrationEvent event){
    System.out.println("Registration event got triggered for customer::  " + event.getName());
}

We need to make to enable asynchronous method execution by enabling @EnableAsync

 

4. Filtering

We can also use condition attribute on our listener to filter certain events.Let’s say we want to listen to only CustomerRegistration event if this is a B2B customer.

 

@EventListener(condition = "#event.customerType=B2C")
void handleRegistration(CustomerRegistrationEvent event){
    System.out.println("Registration event got triggered for customer::  " + event.getName());
}

 

5. Transaction bound events

Spring provides a way to bound events to a certain phase of a transaction (e.g. publish an event when a transaction is complete). We can use @TransactionalEventListener annotation to achieve this behavior. When @TransactionalEventListener is present, Spring will automatically register this in place of default one.

To put it in simple words, this Listener will only invoke if there is a transaction running, in case of no running transaction, this will not be invoked at all.

 

Summary

In this post, we got an introduction to Spring Events.We learned how we can create custom events and how to use publish Spring events synchronously and asynchronously.We briefly covered as to how to use condition to filter events and transaction capabilities of the Spring Framework event system.

JavaDevJournal

Hello!! I am Umesh- an engineer by profession and a photographer by passion.I like to build stuff on the web using OSS and love to capture the world through my lens.

Leave a Reply

Be the First to Comment!

Notify of
avatar
wpDiscuz