(Quick Reference)

11.3 Events

Version: 3.2.9

11.3 Events

Grails 3.0 introduces a new Events API based on Reactor.

All services and controllers in Grails 3.0 implement the Events trait.

The Events trait allows the ability to consume and publish events that are handled by Reactor.

The default Reactor configuration utilises a thread pool backed event bus. You can however configure Reactor within application.yml, for example:

reactor:
    dispatchers:
        default: myExecutor
        myExecutor:
            type: threadPoolExecutor
            size: 5
            backlog: 2048

11.3.1 Consuming Events

There are several ways to consume an event. As mentioned previously services and controllers implement the Events trait.

The Events trait provides several methods to register event consumers. For example:

on("myEvent") {
    println "Event fired!"
}

Note that if you wish a class (other than a controller or service) to be an event consumer you simply have to implement the Events trait and ensure the class is registered as a Spring bean.

For example given the following class:

import grails.events.*
import javax.annotation.*

class MyClass implements Events {

        @PostConstruct
        void init() {
                on("myEvent") {
                    println "Event fired!"
                }
        }
}

You can override doWithSpring in your Application class to register it as a Spring bean (or annotate it with Component):

Closure doWithSpring() {
        {->
                    myClass(MyClass)
        }
    }

11.3.2 Event Notification

The Events trait also provides methods for notifying of events. For example:

notify "myEvent", "myData"
sendAndReceive "myEvent", "myData", {
    println "Got response!"
}

11.3.3 Reactor Spring Annotations

Reactor provides a few useful annotations that can be used for declaratively consuming events in a Grails service.

To declare an event consumer use the Consumer annotation:

import reactor.spring.context.annotation.*

@Consumer
class MyService {

}

Then to register to listen for an event use the Selector annotation:

import reactor.spring.context.annotation.*

@Consumer
class MyService {
        @Selector('myEvent')
        void myEventListener(Object data) {
                println "GOT EVENT $data"
        }
}

11.3.4 Events from GORM

GORM defines a number of useful events that you can listen for.

Each event is translated into a key that starts with gorm:. For example:

import org.grails.datastore.mapping.engine.event.*
...

on("gorm:preInsert") { PreInsertEvent event ->
        println "GOT EVENT $event"
}
These events are triggered asynchronously, and so cannot cancel or manipulate the persistence operations. If you want to do that see the section on Events & Auto Timestamping in the GORM docs

11.3.5 Events from Spring

Spring also fires a number of useful events. All events in the org.springframework package are prefixed with spring:.

For example:

import org.springframework.web.context.support.*
import org.springframework.boot.context.event.*
...

on("spring:applicationStarted") { ApplicationStartedEvent event ->
        // fired when the application starts
}

on("spring:servletRequestHandled") { RequestHandledEvent event ->
        // fired each time a request is handled
}