Why people use message/event buses in their code?

JavaEventsDesign PatternsEvent Handling

Java Problem Overview


I think that you have heard of message/event buses, it's the single place when all events in the system flow. Similar architectures are found in computer's motherboards and LAN networks. It's a good approach for motherboards and networks as it reduces the number of wires, but is it good for software development? We don't have such restrictions as electronics does.

The simplest implementation of message bus/event bus can be like:

class EventBus {
    void addListener(EventBusListener l}{...}
    void fireEvent(Event e) {...}
}

Posting events is done with bus.fireEvent(event), receiving messages is enabled by bus.addListener(listener). Such architectures are sometimes used for software development, for example MVP4G implements similar message bus for GWT.

Active projects:

Dormant/Dead projects:

It's just the popular Observer (Listener) pattern made 'globally' - each object in the system can listen to each message, and I think it's bad, it breaks the Encapsulation principle (each object knows about everything) and Single Responsibility principle (eg when some object needs to a new type of message, event bus often needs to be changed for example to add a new Listener class or a new method in the Listener class).

For these reasons I think, that for most software, Observer pattern is better than event bus. What do you think about event bus, does it make any good sense for typical applications?

EDIT: I'm not talking about 'big' enterprise solutions like ESB - they can be useful (what's more ESB offers much, much more than just an event bus). I'm asking about usefulness of using message bus in 'regular' Java code for object-to-object connection - some people do it, check the links above. Event bus is probably best solution for telephone-to-telephone communication or computer-to-computer communication because each telefone (or computer) in a network can typically talk to each other, and bus reduces the number of wires. But objects rarely talk to each other - how many collaborators one object can have - 3, 5?

Java Solutions


Solution 1 - Java

I am considering using a In memory Event Bus for my regular java code and my rationale is as follows

> Each object in the system can listen to each message, and I think it's > bad, it breaks the Encapsulation principle (each object knows about > everything)

I am not sure if this is really true, I class needs to register with the event bus to start with, similar to observer pattern, Once a class has registered with the Event Bus, only the methods which have the appropriate signature and annotation are notified.

> and Single Responsibility principle (eg when some object needs to a > new type of message, event bus often needs to be changed for example > to add a new Listener class or a new method in the Listener class).

I totally disagree with

> event bus often needs to be changed

The event bus is never changed

I agree with

add a new Listener class or a new method in the Listener class

How does this break SRP ?, I can have a BookEventListener which subscribes to all events pertaining to my Book Entity, and yes I can add methods to this class but still this class is cohesive ...

Why I plan to use it ? It helps me model the "when" of my domain ....

Usually we hear some thing like send a mail "when" book is purchased

we go write down

book.purchase();
sendEmail()

Then we are told add a audit log when a book is purchased , we go to the above snippet

book.purchase();
sendEmail();
**auditBook();**

Right there OCP violated

I Prefer

book.purchase();
EventBus.raiseEvent(bookPurchasedEvent);

Then keep adding handlers as needed Open for Extension Closed for Modification

Thanks

Solution 2 - Java

Some people like it because it is the embodiment of the Facade pattern or Mediator pattern. It centralizes cross-cutting activities like logging, alerting, monitoring, security, etc.

Some people don't like it because it is often a Singleton point of failure. Everyone has to know about it.

Solution 3 - Java

I use it heavily in JavaScript. There can be so many various widgets that all need to do some sort of action whenever something else happens -- there is no real hierarchy of ownership of objects. Instead of passing references of every object to every object, or just making every object global, when something significant happens inside a particular widget, I can just publish "/thisWidget/somethingHappened" -- instead of filling that widget with all kinds of code specific to the API of other widgets. The I have a single class that contains all the "wiring", or "plubming" as they like to call it in the Java Spring framework. This class contains references to all of my widgets, and has all of the code for what happens after each various event fires.

It is centralized, easy to access and maintain, and if one thing changes or I want a new process to occur on a specific event, I don't have to search through every single class/object/widget to try to find out where something is being handled. I can just go to my "operator" class -- the one that handles all the "wiring" when a particular event happens, and see every repercussion of that event. In this system, every individual widget is completely API agnostic of the other widgets. It simply publishes what has happened to it or what it is doing.

Solution 4 - Java

I'm having trouble understanding what you're really asking in your question. You give an example of a simple event bus which is actually just Observable with a different name, then you say;

> For these reasons I think, that for > most software, Observer pattern is > better than event bus. What do you > think about event bus, does it make > any good sense for typical > applications?

..but given your example, they are the same. This makes me wonder if you have ever used something like a Enterprise Service Bus. At a base level an ESB logically does the same thing as the observer pattern, but commercial products add much, much more. Its like an event bus on steroids. They are complicated software products and offer;

Message pickup
Generate events by listening to various endpoints. The endpoint can be a listener (such as a HTTP server), a messaging system (such as JMS), a database or pretty much anything else you want.

Message routing
Take your event and send it to one/many endpoint. Routing can be pretty smart, the bus might route the message depending on the message type, the message contents or any other criteria. Routing can be intelligent and dynamic.

Message Transformation
Transforms your message into another format, this can be as simnple as from XML to JSON or from a row on a database table to a HTTP request. Transformation can occur within the data itself, for example swapping date formats.

Data Enrichment
Adds or modifies data in your message by calling services along the way. For example if a message has a postcode in it the bus might use a postcode lookup service to add in address data.

..and lots, lots more. When you start looking into the details you can really start to see why people use these things.

Solution 5 - Java

Because it can be an important step in the way to decouple the application modules to a service based architecture.

So in your case if you have not the intention to decouple the modules of your application into isolated services then the native implementation of the Observer pattern will make it a simpler solution.

But If you want to build lets say a micro-services architecture the event-bus will allow to get the benefits of this architecture style so you could for instance update and deploy just some part of your application without affect others, because they are just connected through the event-bus.

So the main question here is the desired level of application components decoupling.

Some references about it:

Solution 6 - Java

A good analogy is that of a telephone exchange, where every handset can dial to every other handset. A compromised handset can tune into other conversations. Program control flows like wires(cyclomatic complexity anyone!) This is similar to the requirement of having a connection/physical medium between two end points. This is So for N handsets instead of having NC2 (Combinatorial logic) flows for every new handset we tend to get N flows.

A reduction in complexity implies easy to understand code. Lets start with the prominent points you have highlighted: 1. Global knowledge 2. Intrusive modifications.

Global Knowledge: Consider message event to be an envelop. From event handler/sender perspective there is no data being exposed, it is seeing an envelop (unless an derived class tries to do some inspection using 'instanceof' checks). In a good OOP design, this would never occur.

Intrusive modifications: Instead of having a event specific listener approach, one can use a global event handling approach. As such we have a global event type (on which data is piggy backed and down-casted). This is much like the PropertyBeanSupport model in Java. With a single event type we are required to have a single sender and listener types. This implies you need not modify the bus/listeners every time you see something new. The ugly down-casting can be soothened using Adapter pattern (Please don't start that another level of redirection quote!). Programmers can write assembly in any language. So need for commonsense and smartness can not be substituted. All I intend to state is it can be a effective tool.

The actual event receivers can use the listeners (composition/proxy) easily. In such a Java code base, listeners would look like stand alone inner class declarations (with unused warning being flagged in certain IDEs). This is akeen to two players on the beach playing a ball game, the players don't react until they see the ball.

'@duffymo' points out another interesting aspect: 'Single point of failure'. This would/can in theory effect any object residing in memory(RAM) and not specific to MessageHandlers.

Solution 7 - Java

As a practical example, our app sync's with a web service every x number of minutes, and if any new data is received, we need to update the GUI. Now, because the SyncAdapter runs on a background thread, you can't simply point to a textview and modify its properties, you have to bubble up an event. And the only way to make sure you catch that event is if you have a shared (static,singleton) object passing that event around for subscribers to handle.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestioniirekmView Question on Stackoverflow
Solution 1 - JavaSudarshanView Answer on Stackoverflow
Solution 2 - JavaduffymoView Answer on Stackoverflow
Solution 3 - JavaBalView Answer on Stackoverflow
Solution 4 - JavaQwerkyView Answer on Stackoverflow
Solution 5 - JavabrunocrtView Answer on Stackoverflow
Solution 6 - JavaquestzenView Answer on Stackoverflow
Solution 7 - JavaCaptain KenpachiView Answer on Stackoverflow