Guava EventBus dispatching2019 Community Moderator ElectionGuava EventBus delaying handler execution of nested eventsGoogle Guava vs. Apache CommonsAre static variables shared between threads?Guava EventBus: How to return result from event handlerCompile all files in src?EDT queue cuttingWhy Guava eventbus (the module) is not extensible?Guava eventbus dispatching errorJava - Method executed prior to Default ConstructorWhen use java regular-expression pattern.matcher(), source does not match regex.But, my hope result is ,source matches regex

Is Gradient Descent central to every optimizer?

Should I tell my boss the work he did was worthless

How do I express some one as a black person?

infinitive telling the purpose

How to create a hard link to an inode (ext4)?

Why is this plane circling around the Lucknow airport every day?

Why does Deadpool say "You're welcome, Canada," after shooting Ryan Reynolds in the end credits?

Do f-stop and exposure time perfectly cancel?

PTIJ: How can I halachically kill a vampire?

Algorithm to convert a fixed-length string to the smallest possible collision-free representation?

What to do when during a meeting client people start to fight (even physically) with each others?

Why is there a voltage between the mains ground and my radiator?

Can't find the Shader/UVs tab

What do you call the air that rushes into your car in the highway?

How could our ancestors have domesticated a solitary predator?

How are such low op-amp input currents possible?

Why would a jet engine that runs at temps excess of 2000°C burn when it crashes?

Why is Beresheet doing a only a one-way trip?

What Happens when Passenger Refuses to Fly Boeing 737 Max?

What are some noteworthy "mic-drop" moments in math?

Subset counting for even numbers

Placing subfig vertically

Finding algorithms of QGIS commands?

Low budget alien movie about the Earth being cooked



Guava EventBus dispatching



2019 Community Moderator ElectionGuava EventBus delaying handler execution of nested eventsGoogle Guava vs. Apache CommonsAre static variables shared between threads?Guava EventBus: How to return result from event handlerCompile all files in src?EDT queue cuttingWhy Guava eventbus (the module) is not extensible?Guava eventbus dispatching errorJava - Method executed prior to Default ConstructorWhen use java regular-expression pattern.matcher(), source does not match regex.But, my hope result is ,source matches regex










12















I'm using Guava's EventBus to kick off some processing and report results. Here's a very simple compilable example:



import com.google.common.eventbus.EventBus;
import com.google.common.eventbus.Subscribe;

public class Test

public static class InitiateProcessing
public static class ProcessingStarted
public static class ProcessingResults
public static class ProcessingFinished

public static EventBus bus = new EventBus();

@Subscribe
public void receiveStartRequest(InitiateProcessing evt)
System.out.println("Got processing request - starting processing");
bus.post(new ProcessingStarted());

System.out.println("Generating results");
bus.post(new ProcessingResults());
System.out.println("Generating more results");
bus.post(new ProcessingResults());

bus.post(new ProcessingFinished());


@Subscribe
public void processingStarted(ProcessingStarted evt)
System.out.println("Processing has started");


@Subscribe
public void resultsReceived(ProcessingResults evt)
System.out.println("got results");


@Subscribe
public void processingComplete(ProcessingFinished evt)
System.out.println("Processing has completed");



public static void main(String[] args)
Test t = new Test();
bus.register(t);
bus.post(new InitiateProcessing());




I use these events as a way for other software components to react in preparation for this processing. For example, they may have to save their current state before processing and restore it after.



I would expect the output of this program to be:



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


Instead, the actual output is:



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


The event that is supposed to indicate that processing has started actually happens after the actual processing ("generating results").



After looking at the source code, I understand why it's behaving this way. Here's the relevant source code for the EventBus.



 /**
* Drain the queue of events to be dispatched. As the queue is being drained,
* new events may be posted to the end of the queue.
*/
void dispatchQueuedEvents() {
// don't dispatch if we're already dispatching, that would allow reentrancy
// and out-of-order events. Instead, leave the events to be dispatched
// after the in-progress dispatch is complete.
if (isDispatching.get())
return;

// dispatch event (omitted)


What's happening is since I'm already dispatching the top level InitiateProcessing event, the rest of the events just get pushed to the end of the queue. I would like this to behave similar to .NET events, where invoking the event doesn't return until all handlers have completed.



I don't quite understand the reason for this implementation. Sure, the events are guaranteed to be in order, but the order of the surrounding code gets completely distorted.



Is there any way to get the bus to behave as described and produce the desired output? I did read in the Javadocs that




The EventBus guarantees that it will not call a subscriber method from
multiple threads simultaneously, unless the method explicitly allows
it by bearing the @AllowConcurrentEvents annotation.




But I don't think this applies here - I'm seeing this issue in a single threaded application.



Edit



The cause of the issue here is that I'm posting from within a subscriber. Since the event bus is not reentrant, these "sub-posts" get queued up and are handled after the first handler completes. I can comment out the if (isDispatching.get()) return; section in the EventBus source and everything behaves as I would expect - so the real question is what potential problems have I introduced by doing so? It seems the designers made a conscientious decision to not allow reentrancy.










share|improve this question
























  • looks like the event bus runs in it's own thread. That means usually, that the actions are performed asynchronously and (as soon it's a bus) guaranteed to be delivered according to its' order, and it has nothing to do with the main thread

    – injecteer
    Feb 22 '14 at 0:40











  • @injecteer It does not run it's own thread. They do have an AsyncEventBus that allows you to specify an Executor - but I'm not using that. This is all single threaded.

    – zmb
    Feb 22 '14 at 0:41











  • you might be right. Although I think, they DO run in a new thread :) Can you please test it by adding System.out.println( "curr thread: " + Thread.currentThread().getName() ) to each of your processing @Subscribe-d methods?

    – injecteer
    Feb 22 '14 at 0:46












  • Why do you .post() from within a subscriber to begin with? Something is fishy here

    – fge
    Feb 22 '14 at 9:47






  • 1





    That's exactly why I'm seeing this problem. Is that not a valid use case? Conceptually, events can trigger other events - we've been operating under the assumption that this was okay.

    – zmb
    Feb 22 '14 at 13:54















12















I'm using Guava's EventBus to kick off some processing and report results. Here's a very simple compilable example:



import com.google.common.eventbus.EventBus;
import com.google.common.eventbus.Subscribe;

public class Test

public static class InitiateProcessing
public static class ProcessingStarted
public static class ProcessingResults
public static class ProcessingFinished

public static EventBus bus = new EventBus();

@Subscribe
public void receiveStartRequest(InitiateProcessing evt)
System.out.println("Got processing request - starting processing");
bus.post(new ProcessingStarted());

System.out.println("Generating results");
bus.post(new ProcessingResults());
System.out.println("Generating more results");
bus.post(new ProcessingResults());

bus.post(new ProcessingFinished());


@Subscribe
public void processingStarted(ProcessingStarted evt)
System.out.println("Processing has started");


@Subscribe
public void resultsReceived(ProcessingResults evt)
System.out.println("got results");


@Subscribe
public void processingComplete(ProcessingFinished evt)
System.out.println("Processing has completed");



public static void main(String[] args)
Test t = new Test();
bus.register(t);
bus.post(new InitiateProcessing());




I use these events as a way for other software components to react in preparation for this processing. For example, they may have to save their current state before processing and restore it after.



I would expect the output of this program to be:



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


Instead, the actual output is:



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


The event that is supposed to indicate that processing has started actually happens after the actual processing ("generating results").



After looking at the source code, I understand why it's behaving this way. Here's the relevant source code for the EventBus.



 /**
* Drain the queue of events to be dispatched. As the queue is being drained,
* new events may be posted to the end of the queue.
*/
void dispatchQueuedEvents() {
// don't dispatch if we're already dispatching, that would allow reentrancy
// and out-of-order events. Instead, leave the events to be dispatched
// after the in-progress dispatch is complete.
if (isDispatching.get())
return;

// dispatch event (omitted)


What's happening is since I'm already dispatching the top level InitiateProcessing event, the rest of the events just get pushed to the end of the queue. I would like this to behave similar to .NET events, where invoking the event doesn't return until all handlers have completed.



I don't quite understand the reason for this implementation. Sure, the events are guaranteed to be in order, but the order of the surrounding code gets completely distorted.



Is there any way to get the bus to behave as described and produce the desired output? I did read in the Javadocs that




The EventBus guarantees that it will not call a subscriber method from
multiple threads simultaneously, unless the method explicitly allows
it by bearing the @AllowConcurrentEvents annotation.




But I don't think this applies here - I'm seeing this issue in a single threaded application.



Edit



The cause of the issue here is that I'm posting from within a subscriber. Since the event bus is not reentrant, these "sub-posts" get queued up and are handled after the first handler completes. I can comment out the if (isDispatching.get()) return; section in the EventBus source and everything behaves as I would expect - so the real question is what potential problems have I introduced by doing so? It seems the designers made a conscientious decision to not allow reentrancy.










share|improve this question
























  • looks like the event bus runs in it's own thread. That means usually, that the actions are performed asynchronously and (as soon it's a bus) guaranteed to be delivered according to its' order, and it has nothing to do with the main thread

    – injecteer
    Feb 22 '14 at 0:40











  • @injecteer It does not run it's own thread. They do have an AsyncEventBus that allows you to specify an Executor - but I'm not using that. This is all single threaded.

    – zmb
    Feb 22 '14 at 0:41











  • you might be right. Although I think, they DO run in a new thread :) Can you please test it by adding System.out.println( "curr thread: " + Thread.currentThread().getName() ) to each of your processing @Subscribe-d methods?

    – injecteer
    Feb 22 '14 at 0:46












  • Why do you .post() from within a subscriber to begin with? Something is fishy here

    – fge
    Feb 22 '14 at 9:47






  • 1





    That's exactly why I'm seeing this problem. Is that not a valid use case? Conceptually, events can trigger other events - we've been operating under the assumption that this was okay.

    – zmb
    Feb 22 '14 at 13:54













12












12








12


2






I'm using Guava's EventBus to kick off some processing and report results. Here's a very simple compilable example:



import com.google.common.eventbus.EventBus;
import com.google.common.eventbus.Subscribe;

public class Test

public static class InitiateProcessing
public static class ProcessingStarted
public static class ProcessingResults
public static class ProcessingFinished

public static EventBus bus = new EventBus();

@Subscribe
public void receiveStartRequest(InitiateProcessing evt)
System.out.println("Got processing request - starting processing");
bus.post(new ProcessingStarted());

System.out.println("Generating results");
bus.post(new ProcessingResults());
System.out.println("Generating more results");
bus.post(new ProcessingResults());

bus.post(new ProcessingFinished());


@Subscribe
public void processingStarted(ProcessingStarted evt)
System.out.println("Processing has started");


@Subscribe
public void resultsReceived(ProcessingResults evt)
System.out.println("got results");


@Subscribe
public void processingComplete(ProcessingFinished evt)
System.out.println("Processing has completed");



public static void main(String[] args)
Test t = new Test();
bus.register(t);
bus.post(new InitiateProcessing());




I use these events as a way for other software components to react in preparation for this processing. For example, they may have to save their current state before processing and restore it after.



I would expect the output of this program to be:



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


Instead, the actual output is:



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


The event that is supposed to indicate that processing has started actually happens after the actual processing ("generating results").



After looking at the source code, I understand why it's behaving this way. Here's the relevant source code for the EventBus.



 /**
* Drain the queue of events to be dispatched. As the queue is being drained,
* new events may be posted to the end of the queue.
*/
void dispatchQueuedEvents() {
// don't dispatch if we're already dispatching, that would allow reentrancy
// and out-of-order events. Instead, leave the events to be dispatched
// after the in-progress dispatch is complete.
if (isDispatching.get())
return;

// dispatch event (omitted)


What's happening is since I'm already dispatching the top level InitiateProcessing event, the rest of the events just get pushed to the end of the queue. I would like this to behave similar to .NET events, where invoking the event doesn't return until all handlers have completed.



I don't quite understand the reason for this implementation. Sure, the events are guaranteed to be in order, but the order of the surrounding code gets completely distorted.



Is there any way to get the bus to behave as described and produce the desired output? I did read in the Javadocs that




The EventBus guarantees that it will not call a subscriber method from
multiple threads simultaneously, unless the method explicitly allows
it by bearing the @AllowConcurrentEvents annotation.




But I don't think this applies here - I'm seeing this issue in a single threaded application.



Edit



The cause of the issue here is that I'm posting from within a subscriber. Since the event bus is not reentrant, these "sub-posts" get queued up and are handled after the first handler completes. I can comment out the if (isDispatching.get()) return; section in the EventBus source and everything behaves as I would expect - so the real question is what potential problems have I introduced by doing so? It seems the designers made a conscientious decision to not allow reentrancy.










share|improve this question
















I'm using Guava's EventBus to kick off some processing and report results. Here's a very simple compilable example:



import com.google.common.eventbus.EventBus;
import com.google.common.eventbus.Subscribe;

public class Test

public static class InitiateProcessing
public static class ProcessingStarted
public static class ProcessingResults
public static class ProcessingFinished

public static EventBus bus = new EventBus();

@Subscribe
public void receiveStartRequest(InitiateProcessing evt)
System.out.println("Got processing request - starting processing");
bus.post(new ProcessingStarted());

System.out.println("Generating results");
bus.post(new ProcessingResults());
System.out.println("Generating more results");
bus.post(new ProcessingResults());

bus.post(new ProcessingFinished());


@Subscribe
public void processingStarted(ProcessingStarted evt)
System.out.println("Processing has started");


@Subscribe
public void resultsReceived(ProcessingResults evt)
System.out.println("got results");


@Subscribe
public void processingComplete(ProcessingFinished evt)
System.out.println("Processing has completed");



public static void main(String[] args)
Test t = new Test();
bus.register(t);
bus.post(new InitiateProcessing());




I use these events as a way for other software components to react in preparation for this processing. For example, they may have to save their current state before processing and restore it after.



I would expect the output of this program to be:



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


Instead, the actual output is:



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


The event that is supposed to indicate that processing has started actually happens after the actual processing ("generating results").



After looking at the source code, I understand why it's behaving this way. Here's the relevant source code for the EventBus.



 /**
* Drain the queue of events to be dispatched. As the queue is being drained,
* new events may be posted to the end of the queue.
*/
void dispatchQueuedEvents() {
// don't dispatch if we're already dispatching, that would allow reentrancy
// and out-of-order events. Instead, leave the events to be dispatched
// after the in-progress dispatch is complete.
if (isDispatching.get())
return;

// dispatch event (omitted)


What's happening is since I'm already dispatching the top level InitiateProcessing event, the rest of the events just get pushed to the end of the queue. I would like this to behave similar to .NET events, where invoking the event doesn't return until all handlers have completed.



I don't quite understand the reason for this implementation. Sure, the events are guaranteed to be in order, but the order of the surrounding code gets completely distorted.



Is there any way to get the bus to behave as described and produce the desired output? I did read in the Javadocs that




The EventBus guarantees that it will not call a subscriber method from
multiple threads simultaneously, unless the method explicitly allows
it by bearing the @AllowConcurrentEvents annotation.




But I don't think this applies here - I'm seeing this issue in a single threaded application.



Edit



The cause of the issue here is that I'm posting from within a subscriber. Since the event bus is not reentrant, these "sub-posts" get queued up and are handled after the first handler completes. I can comment out the if (isDispatching.get()) return; section in the EventBus source and everything behaves as I would expect - so the real question is what potential problems have I introduced by doing so? It seems the designers made a conscientious decision to not allow reentrancy.







java guava






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Dec 22 '17 at 20:39









sebkur

5522616




5522616










asked Feb 22 '14 at 0:32









zmbzmb

4,55622847




4,55622847












  • looks like the event bus runs in it's own thread. That means usually, that the actions are performed asynchronously and (as soon it's a bus) guaranteed to be delivered according to its' order, and it has nothing to do with the main thread

    – injecteer
    Feb 22 '14 at 0:40











  • @injecteer It does not run it's own thread. They do have an AsyncEventBus that allows you to specify an Executor - but I'm not using that. This is all single threaded.

    – zmb
    Feb 22 '14 at 0:41











  • you might be right. Although I think, they DO run in a new thread :) Can you please test it by adding System.out.println( "curr thread: " + Thread.currentThread().getName() ) to each of your processing @Subscribe-d methods?

    – injecteer
    Feb 22 '14 at 0:46












  • Why do you .post() from within a subscriber to begin with? Something is fishy here

    – fge
    Feb 22 '14 at 9:47






  • 1





    That's exactly why I'm seeing this problem. Is that not a valid use case? Conceptually, events can trigger other events - we've been operating under the assumption that this was okay.

    – zmb
    Feb 22 '14 at 13:54

















  • looks like the event bus runs in it's own thread. That means usually, that the actions are performed asynchronously and (as soon it's a bus) guaranteed to be delivered according to its' order, and it has nothing to do with the main thread

    – injecteer
    Feb 22 '14 at 0:40











  • @injecteer It does not run it's own thread. They do have an AsyncEventBus that allows you to specify an Executor - but I'm not using that. This is all single threaded.

    – zmb
    Feb 22 '14 at 0:41











  • you might be right. Although I think, they DO run in a new thread :) Can you please test it by adding System.out.println( "curr thread: " + Thread.currentThread().getName() ) to each of your processing @Subscribe-d methods?

    – injecteer
    Feb 22 '14 at 0:46












  • Why do you .post() from within a subscriber to begin with? Something is fishy here

    – fge
    Feb 22 '14 at 9:47






  • 1





    That's exactly why I'm seeing this problem. Is that not a valid use case? Conceptually, events can trigger other events - we've been operating under the assumption that this was okay.

    – zmb
    Feb 22 '14 at 13:54
















looks like the event bus runs in it's own thread. That means usually, that the actions are performed asynchronously and (as soon it's a bus) guaranteed to be delivered according to its' order, and it has nothing to do with the main thread

– injecteer
Feb 22 '14 at 0:40





looks like the event bus runs in it's own thread. That means usually, that the actions are performed asynchronously and (as soon it's a bus) guaranteed to be delivered according to its' order, and it has nothing to do with the main thread

– injecteer
Feb 22 '14 at 0:40













@injecteer It does not run it's own thread. They do have an AsyncEventBus that allows you to specify an Executor - but I'm not using that. This is all single threaded.

– zmb
Feb 22 '14 at 0:41





@injecteer It does not run it's own thread. They do have an AsyncEventBus that allows you to specify an Executor - but I'm not using that. This is all single threaded.

– zmb
Feb 22 '14 at 0:41













you might be right. Although I think, they DO run in a new thread :) Can you please test it by adding System.out.println( "curr thread: " + Thread.currentThread().getName() ) to each of your processing @Subscribe-d methods?

– injecteer
Feb 22 '14 at 0:46






you might be right. Although I think, they DO run in a new thread :) Can you please test it by adding System.out.println( "curr thread: " + Thread.currentThread().getName() ) to each of your processing @Subscribe-d methods?

– injecteer
Feb 22 '14 at 0:46














Why do you .post() from within a subscriber to begin with? Something is fishy here

– fge
Feb 22 '14 at 9:47





Why do you .post() from within a subscriber to begin with? Something is fishy here

– fge
Feb 22 '14 at 9:47




1




1





That's exactly why I'm seeing this problem. Is that not a valid use case? Conceptually, events can trigger other events - we've been operating under the assumption that this was okay.

– zmb
Feb 22 '14 at 13:54





That's exactly why I'm seeing this problem. Is that not a valid use case? Conceptually, events can trigger other events - we've been operating under the assumption that this was okay.

– zmb
Feb 22 '14 at 13:54












4 Answers
4






active

oldest

votes


















7














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.






share|improve this answer























  • "Separating my code from what exactly happens in response to a given event" is what I want. I want the event to say "get ready for something to happen" - I don't care how or what subscribers have to do to get ready. They might not have to do anything. I just want to be confident that after posting the event, the subscribers are ready so I can proceed with some action. The event bus seems perfect for this case because I can easily add and remove components that might handle the event differently. The code posting the event doesn't care.

    – zmb
    Feb 24 '14 at 19:55






  • 1





    What I am taking out of the answers so far is that this behavior is by design and the event bus as is will not support my use case. I ended up modifying the bus to allow reentrancy which better suits my use case.

    – zmb
    Feb 24 '14 at 19:57


















5














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.






share|improve this answer






























    2














    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.







    share|improve this answer























    • This isn't quite right - in this case the when the first post returns all of the events have been handled. Either way - this doesn't answer my question about whether I can get the bus to behave as expected.

      – zmb
      Feb 22 '14 at 18:05


















    0














    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





    share|improve this answer






















      Your Answer






      StackExchange.ifUsing("editor", function ()
      StackExchange.using("externalEditor", function ()
      StackExchange.using("snippets", function ()
      StackExchange.snippets.init();
      );
      );
      , "code-snippets");

      StackExchange.ready(function()
      var channelOptions =
      tags: "".split(" "),
      id: "1"
      ;
      initTagRenderer("".split(" "), "".split(" "), channelOptions);

      StackExchange.using("externalEditor", function()
      // Have to fire editor after snippets, if snippets enabled
      if (StackExchange.settings.snippets.snippetsEnabled)
      StackExchange.using("snippets", function()
      createEditor();
      );

      else
      createEditor();

      );

      function createEditor()
      StackExchange.prepareEditor(
      heartbeatType: 'answer',
      autoActivateHeartbeat: false,
      convertImagesToLinks: true,
      noModals: true,
      showLowRepImageUploadWarning: true,
      reputationToPostImages: 10,
      bindNavPrevention: true,
      postfix: "",
      imageUploader:
      brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
      contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
      allowUrls: true
      ,
      onDemand: true,
      discardSelector: ".discard-answer"
      ,immediatelyShowMarkdownHelp:true
      );



      );













      draft saved

      draft discarded


















      StackExchange.ready(
      function ()
      StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f21947936%2fguava-eventbus-dispatching%23new-answer', 'question_page');

      );

      Post as a guest















      Required, but never shown

























      4 Answers
      4






      active

      oldest

      votes








      4 Answers
      4






      active

      oldest

      votes









      active

      oldest

      votes






      active

      oldest

      votes









      7














      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.






      share|improve this answer























      • "Separating my code from what exactly happens in response to a given event" is what I want. I want the event to say "get ready for something to happen" - I don't care how or what subscribers have to do to get ready. They might not have to do anything. I just want to be confident that after posting the event, the subscribers are ready so I can proceed with some action. The event bus seems perfect for this case because I can easily add and remove components that might handle the event differently. The code posting the event doesn't care.

        – zmb
        Feb 24 '14 at 19:55






      • 1





        What I am taking out of the answers so far is that this behavior is by design and the event bus as is will not support my use case. I ended up modifying the bus to allow reentrancy which better suits my use case.

        – zmb
        Feb 24 '14 at 19:57















      7














      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.






      share|improve this answer























      • "Separating my code from what exactly happens in response to a given event" is what I want. I want the event to say "get ready for something to happen" - I don't care how or what subscribers have to do to get ready. They might not have to do anything. I just want to be confident that after posting the event, the subscribers are ready so I can proceed with some action. The event bus seems perfect for this case because I can easily add and remove components that might handle the event differently. The code posting the event doesn't care.

        – zmb
        Feb 24 '14 at 19:55






      • 1





        What I am taking out of the answers so far is that this behavior is by design and the event bus as is will not support my use case. I ended up modifying the bus to allow reentrancy which better suits my use case.

        – zmb
        Feb 24 '14 at 19:57













      7












      7








      7







      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.






      share|improve this answer













      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.







      share|improve this answer












      share|improve this answer



      share|improve this answer










      answered Feb 24 '14 at 18:24









      ColinDColinD

      93k24175189




      93k24175189












      • "Separating my code from what exactly happens in response to a given event" is what I want. I want the event to say "get ready for something to happen" - I don't care how or what subscribers have to do to get ready. They might not have to do anything. I just want to be confident that after posting the event, the subscribers are ready so I can proceed with some action. The event bus seems perfect for this case because I can easily add and remove components that might handle the event differently. The code posting the event doesn't care.

        – zmb
        Feb 24 '14 at 19:55






      • 1





        What I am taking out of the answers so far is that this behavior is by design and the event bus as is will not support my use case. I ended up modifying the bus to allow reentrancy which better suits my use case.

        – zmb
        Feb 24 '14 at 19:57

















      • "Separating my code from what exactly happens in response to a given event" is what I want. I want the event to say "get ready for something to happen" - I don't care how or what subscribers have to do to get ready. They might not have to do anything. I just want to be confident that after posting the event, the subscribers are ready so I can proceed with some action. The event bus seems perfect for this case because I can easily add and remove components that might handle the event differently. The code posting the event doesn't care.

        – zmb
        Feb 24 '14 at 19:55






      • 1





        What I am taking out of the answers so far is that this behavior is by design and the event bus as is will not support my use case. I ended up modifying the bus to allow reentrancy which better suits my use case.

        – zmb
        Feb 24 '14 at 19:57
















      "Separating my code from what exactly happens in response to a given event" is what I want. I want the event to say "get ready for something to happen" - I don't care how or what subscribers have to do to get ready. They might not have to do anything. I just want to be confident that after posting the event, the subscribers are ready so I can proceed with some action. The event bus seems perfect for this case because I can easily add and remove components that might handle the event differently. The code posting the event doesn't care.

      – zmb
      Feb 24 '14 at 19:55





      "Separating my code from what exactly happens in response to a given event" is what I want. I want the event to say "get ready for something to happen" - I don't care how or what subscribers have to do to get ready. They might not have to do anything. I just want to be confident that after posting the event, the subscribers are ready so I can proceed with some action. The event bus seems perfect for this case because I can easily add and remove components that might handle the event differently. The code posting the event doesn't care.

      – zmb
      Feb 24 '14 at 19:55




      1




      1





      What I am taking out of the answers so far is that this behavior is by design and the event bus as is will not support my use case. I ended up modifying the bus to allow reentrancy which better suits my use case.

      – zmb
      Feb 24 '14 at 19:57





      What I am taking out of the answers so far is that this behavior is by design and the event bus as is will not support my use case. I ended up modifying the bus to allow reentrancy which better suits my use case.

      – zmb
      Feb 24 '14 at 19:57













      5














      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.






      share|improve this answer



























        5














        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.






        share|improve this answer

























          5












          5








          5







          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.






          share|improve this answer













          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.







          share|improve this answer












          share|improve this answer



          share|improve this answer










          answered Dec 17 '14 at 9:29









          PetiPeti

          1,0471220




          1,0471220





















              2














              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.







              share|improve this answer























              • This isn't quite right - in this case the when the first post returns all of the events have been handled. Either way - this doesn't answer my question about whether I can get the bus to behave as expected.

                – zmb
                Feb 22 '14 at 18:05















              2














              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.







              share|improve this answer























              • This isn't quite right - in this case the when the first post returns all of the events have been handled. Either way - this doesn't answer my question about whether I can get the bus to behave as expected.

                – zmb
                Feb 22 '14 at 18:05













              2












              2








              2







              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.







              share|improve this answer













              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.








              share|improve this answer












              share|improve this answer



              share|improve this answer










              answered Feb 22 '14 at 0:46









              ErstwhileIIIErstwhileIII

              4,34221735




              4,34221735












              • This isn't quite right - in this case the when the first post returns all of the events have been handled. Either way - this doesn't answer my question about whether I can get the bus to behave as expected.

                – zmb
                Feb 22 '14 at 18:05

















              • This isn't quite right - in this case the when the first post returns all of the events have been handled. Either way - this doesn't answer my question about whether I can get the bus to behave as expected.

                – zmb
                Feb 22 '14 at 18:05
















              This isn't quite right - in this case the when the first post returns all of the events have been handled. Either way - this doesn't answer my question about whether I can get the bus to behave as expected.

              – zmb
              Feb 22 '14 at 18:05





              This isn't quite right - in this case the when the first post returns all of the events have been handled. Either way - this doesn't answer my question about whether I can get the bus to behave as expected.

              – zmb
              Feb 22 '14 at 18:05











              0














              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





              share|improve this answer



























                0














                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





                share|improve this answer

























                  0












                  0








                  0







                  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





                  share|improve this answer













                  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






                  share|improve this answer












                  share|improve this answer



                  share|improve this answer










                  answered Mar 6 at 16:26









                  mwoodmanmwoodman

                  562410




                  562410



























                      draft saved

                      draft discarded
















































                      Thanks for contributing an answer to Stack Overflow!


                      • Please be sure to answer the question. Provide details and share your research!

                      But avoid


                      • Asking for help, clarification, or responding to other answers.

                      • Making statements based on opinion; back them up with references or personal experience.

                      To learn more, see our tips on writing great answers.




                      draft saved


                      draft discarded














                      StackExchange.ready(
                      function ()
                      StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f21947936%2fguava-eventbus-dispatching%23new-answer', 'question_page');

                      );

                      Post as a guest















                      Required, but never shown





















































                      Required, but never shown














                      Required, but never shown












                      Required, but never shown







                      Required, but never shown

































                      Required, but never shown














                      Required, but never shown












                      Required, but never shown







                      Required, but never shown







                      Popular posts from this blog

                      1928 у кіно

                      Захаров Федір Захарович

                      Ель Греко