Published

Self-made event dispatcher

In my current project, we are using an event-based architecture in order to communicate between systems. The events are implemented as JMS messages, which we send over an ActiveMQ broker. Each system sends and listens to multiple events. While sending events is pretty easy, on the listener side we quickly ended up with a class explosion:

So we came up with a simple idea to make this kind of boilerplate code superfluous.

Event handler annotation

Our first step was a very tiny one. We created a custom annotation to mark event handler methods. It looks like this:

1

2

3

4

5

@Retention(RetentionPolicy.RUNTIME)

@Target(ElementType.METHOD)

public@interfaceEventHandler{

}

We placed this annotation at service methods which should become our event handlers. In case of the SomeService from the example above, it looks like this:

1

2

3

4

5

6

7

8

@Service

publicclassSomeService{

@EventHandler

publicvoidhandle(MyEvent myEvent){

// ...

}

}

The annotation comes with two conventions:

It can only be placed on methods of Spring beans – not on unmanaged classes!

The method must have exactly one single parameter: the event to handle!

Event handler registry

In the next step, we created an event handler registry in order to pick-up all event handlers annotated with @EventHandler. By using some functionality of Spring, it wasn’t too much work or magic to do this. Our registry looks like this:

So what does this class do? First of all, it implements the ApplicationListener interface and listens for an ApplicationReadyEvent. This simply means, that it is called as soon as the application is ready (== after the boot process). It will then look for any Spring bean which has a method annotated with our @EventHandler annotation. Each method will be wrapped in a EventHandlerProxy which is stored in a list. The EventHandlerProxy simply encapsulates the event handler method in a convenient object:

Event dispatcher

The last piece which is missing is the event dispatcher itself. The dispatcher is a JMS listener which will listen to all events and invoke any event handler which accepts it. To do so, it will ask the event handler registry for all registered handlers for the given event.

Notes

An important detail is the _type property which is expected on every event. This property tells us the type (== Java class!) of the event. For example, whether if it is an MyEvent.java or a YourEvent.java. We need this information in order to map the event (which is plain JSON) to a Java object. So whenever we send an event we set this property: