Table of contents

Given problem

In the section Some problems with Command Bus pattern of the article Command bus pattern, we discussed about their Command bus pattern’s arduous and its solution. It is to use Event Bus pattern to decouple between the primary action and the secondary action in Command Bus pattern.

This way makes our code satisfy Single Responsibility Principle and extends our functionality in the future time.

So how do we implement the Event Bus pattern?

Solution with Event bus pattern

Below is the diagram that describes how Event Bus pattern works.

Some components in this pattern:

  1. Event Publisher

    Event Publisher is a component that is responsible for publish an Event to the Event Bus.

  2. Event Bus

    After the Event Bus received an Event from Event Publisher, the Event Subscriber components that have subscribed to that Event will get notified.

  3. Event Subscriber

    The Event Subscriber receives an Event, and it will start to do its behavior.

    The relationship between Event and Event Publisher is that an Event can be sent to the multiple Event Subscribers.

Source code

Belows are some steps that we need to implement Event Bus pattern with Spring framework.

  1. Definition of Event class that will pass to EventBus

    In this Event class’s object, it will contain all data that we want to pass an EventSubscriber object.

     public class Event {
         private final String eventName;
         private final Map<String, String> data = new HashMap();
         public Event(String eventName) {
             this.eventName = eventName;
         public void setData(String key, String value) {
   , value);
         public String getData(String key) {
         // other getter/setter method for each data types
         // ...
  2. Definition of EventDataObject class that will take data from Event class’s object.

     public interface EventDataObject {
         default void restoreFromEvent(Event event) {
             // nothing to do
         default Event getEvent() {
             return null;
  3. Definition of EventBus interface and its implementation.

     public interface EventBus {
         void initialize();
         void publish(Event event);

    Because with each event, we have a list of subscribers. So, we will use Hash Map data structure to save them.

     public class EventBusImpl {
         private boolean hasInitialized = false; 
         private Map<String, List<EventSubscriber>> eventWithSubscribers;
         private ApplicationContext context;
         public EventBusImpl(ApplicationContext context) {
             this.context = context;
         public void initialize() {
             Map<String, EventSubscriber> subscribers =
             this.eventWithSubscribers = subscribers.values().stream()
                                                 .collect(Collectors.groupingBy(subscriber -> {
                                                     EventHandler annotation = subscriber.getClass().getAnnotation(EventHandler.class);
                                                     if (Objects.isNull(annotation)) {
                                                         throw new RuntimeException();
                                                     return annotation.value();
             this.hasInitialized = true;
         public void publish(Event event) {
             if (!this.hasInitialized) {
                 throw new RuntimeException();
             List<EventSubscriber> eventSubscribers = this.eventWithSubscribers.getOrDefault(event.getEventName(), new ArrayList<>());
             eventSubscribers.forEach(subscriber -> {
         public void destroy() {
             this.hasInitialized = false;

    In Spring framework, we will use all beans in IoC container to access EventSubscriber objects.

  4. Definition of EventPublisher class

     public class EventPublisher {
         private static ApplicationContext context;
         public setContext(ApplicationContext context) {
             EventPublisher.context = context;
         public static void publish(Event event) {
  5. Definition of EventSubscriber class, EventDataObjectHandler class and EventtHandler annotation.

     @Target(value = {ElementType.TYPE})
     public @interface EventHandler {
         String value();
     public interface EventSubscriber {
         void handleEvent(Event event);
     public abstract class EventDataObjectHandler<T extends EventDataObject>
                                         implements EventSubscriber {
         private Class<T> eventClazzType;
         public EventDataObjectHandler(Class<T> eventClazzType) {
             this.eventClazzType = eventClazzType;
         public void handleEvent(Event event) {
             try {
                 T eventObject = this.eventClazzType.newInstance();
             } catch(InstantiationException | IllegalAccessException ex) {
                 throw new RuntimeException();
         protected abstract void handle(T event);
  6. Assuming that there is someone has just registered as a user in our application, after RegisterUserCommand completed, a RegisteredUserEvent will be fired. This event will responsible for sending an email to that user.

     public class RegisteredUserEventDataObject implements EventDataObject {
         public static final String EVENT_NAME = "RegisteredUserEventDataObject";
         private String username;
         private String password;
         private String phoneNumber;
         public RegisteredUserEventDataObject() {}
         public Event getEvent() {
             GlobalEvent event = new GlobalEvent(EVENT_NAME);
             event.setString("UserName", this.userName);
             event.setString("Password", this.password);
             event.setString("PhoneNumber", this.phoneNumber);
             return event;
         public void restoreFromEvent(Event event) {
             this.username = event.getData("UserName");
             this.username = event.getData("Password");
             this.username = event.getData("PhoneNumber");
     public class RegisteredUserEventSubscriber extends EventDataObjectHandler<RegisteredUserEventDataObject>
                                      implements EventSubscriber {
         public RegisteredUserEventSubscriber() {
         protected void handle(RegisteredUserEventDataObject eventDataObject) {
             // do something
     public static void main(String[] args) {
         Event registeredUserEvent = new Event(RegisteredUserEventDataObject.EVENT_NAME);
         registeredUserEvent.setData("UserName", "Something");
         registeredUserEvent.setData("Password", "Something");
         registeredUserEvent.setData("PhoneNumber", "Something");

Benefits and Drawbacks

  1. Benefits

    • Decoupling between Event Publishers and Event Subscribers. Then it makes our project easy to maintain, scale when we have to receive new requirements.
  2. Drawbacks

    • All weird things in the Event Bus pattern’s implementation will be hidden in Event Bus component. Sometimes, it’s difficult to understand.

    • In the Source code section, we find that each event was fired, we will create an EventDataObject object to pass the corresponding Subscriber object. It means that we replicate the event data to subscribers. So memory will increase when we have lots of Subscribers.

      Solution for this problem is that we should use local cache or using the same reference with EventDataObject object.

The relationship with other patterns

  1. Event Bus pattern and Publisher/Subscriber pattern

    • Publisher/Subscriber pattern also want some other components to be aware of certain events taking place. But the Publisher does not want to know who the events will be received.

      And a message that is sent by Publisher, will be processed in the future time. It means that it is in the asynchronous way.

    • Event Bus pattern need to know which Event Subscribers that subscribed some specific events.

      An event will be process in the synchronous way. It means that Event Subscribers will be implement its logic immediately after taken that event.

  2. Event Bus pattern and Mediator pattern

    The Event Bus pattern is an instance of Mediator pattern. But Event Bus in Guava framework is an implementation of the Observer pattern.

Wrapping up

  • Understanding about how to implement Event Bus pattern from scratch, and build it based on Guava and Vert.x library.


Open source from github

Event Bus in Guava