Spring Events With Grails
Hi,
There arise several situations where you need to implement a certain flow comprising of various tasks. These tasks may be executed independent of each other and it gives us an opportunity to separate out the different parts of a flow into separate threads that can be executed “asynchronously”.
I had a very similar use case wherein I had to save a user as part of the registration flow and consequently update the user’s account with information and perform other trivial tasks like sending an email.
A colleague of mine suggested the use of Spring Events, which I could use in this process in such a way that saving the user and performing other trivial tasks like update account, send email etc. could be done in separate threads. These subsequent tasks are performed in another daemon thread, using custom Spring events and event listeners so that the ‘save user’ request is served well on time which improves response time.
In Spring Events library, an “Event” is triggered because of a state change or some activities with in the container. Spring provides an “ApplicationEvent” class and “ApplicationListener” interface to support event handling. Here in our use case, we will create an “UserSubTaskEvent” (our custom event) and a “UserSubTaskListener” (our custom event listener) which will listen to our custom event to perform all the tasks.
Lets see how to create custom event and its listener!
- Create a custom event:
Create a class “UserSubTaskEvent” and extend Spring’s “ApplicationEvent” class as follows.
[java]
import org.springframework.context.ApplicationEvent
class UserSubTaskEvent extends ApplicationEvent {
String message // Sample metadata for event
UserSubTaskEvent(String message) {
super(message)
this.message = message
}
}
[/java]
- Create a listener:
Now we will create a listener for “UserSubTaskEvent“. For that, we will create a “UserSubTaskListener” class and implement Spring’s “ApplicationListener” interface. After implementing “ApplicationListener” interface, we override the “onApplicationEvent” method of “ApplicationListener” interface as per our requirement.
[java]
import org.springframework.context.ApplicationListener
class UserSubTaskListener
implements ApplicationListener<UserSubTaskEvent> {
@Override
void onApplicationEvent(UserSubTaskEvent event) {
log.info("Message from UserSubTaskEvent: ${event.message}")
mailHelperService.sendMail(message)
// you can perform many other tasks here…
}
}
[/java]
- Publish an event:
Now we will see how to publish “UserSubTaskEvent“. The custom events are published through the “ApplicationContext”
[java]
def saveUser(){
userService.saveUser(params)
String message = "Hi This message is from UserSubTaskEvent."
applicationContext.publishEvent(new UserSubTaskEvent(message))
}
[/java]
This is just an example but you can use Spring Events in an extensive way to implement asynchronous behaviour. Grails 2.4.3 also provides concept of “Promises” and “Task” to achieve asynchronous programming.