Guava EventBus dispatching

While posting to the EventBus does not return until all "subscribers" have been signaled .. those subscribers might NOT have begun execution. That means that when the first bus.post returns, you continue the next post without any intervening subscriber having begun to process.

public void post(Object event) Posts an event to all registered subscribers. This method will return successfully after the event has been posted to all subscribers, and regardless of any exceptions thrown by subscribers. If no subscribers have been subscribed for event's class, and event is not already a DeadEvent, it will be wrapped in a DeadEvent and reposted.

Parameters: event - event to post.


EventBus generally operates on the principle that the code posting an event to the bus shouldn't care about what the subscribers do with the events or when, other than that the order the events were posted in is respected (in the case of a synchronous event bus anyway).

If you want specific methods to be called at specific times in the course of your method and you want to be sure those methods complete before your method continues (as you seem to in your example), why not call those methods directly? When you use an event bus, you're explicitly separating your code from what exactly happens in response to a given event. This is desirable in many cases and is the main reason EventBus exists, but it doesn't seem to be quite what you want here.


I try to summarize Guava's EventBus event delivery behaviour:

If an event E1 is posted at moment t1, all subscribers are notified. If one of the subscribers posts an event itself in it's @Subscribe-method (a tiny moment later), the "new" event E2 is enqueued and delivered afterwards. Afterwards means here: after all @Subscribe-methods for E1 from t1 did return.

Compare this kind of "cascaded" event posting to breadth first tree traversal.

It seems to be the explicit choosen design of EventBus.


I know this question is 4 years old, but I just ran into the same problem today. There is a simple (and counter-intuitive) change to get the behavior you want. Per https://stackoverflow.com/a/53136251/1296767, you can use an AsyncEventBus with a DirectExecutor:

public static EventBus bus = new AsyncEventBus(MoreExecutors.newDirectExecutorService());

Running your test code with the above change, the results are exactly what you want:

Got processing request - starting processing
Processing has started
Generating results
got results
Generating more results
got results
Processing has completed

Tags:

Java

Guava