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
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 post
ing 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
|
show 1 more comment
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 post
ing 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
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 anAsyncEventBus
that allows you to specify anExecutor
- 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 addingSystem.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
|
show 1 more comment
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 post
ing 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
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 post
ing 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
java guava
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 anAsyncEventBus
that allows you to specify anExecutor
- 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 addingSystem.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
|
show 1 more comment
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 anAsyncEventBus
that allows you to specify anExecutor
- 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 addingSystem.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
|
show 1 more comment
4 Answers
4
active
oldest
votes
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.
"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
add a comment |
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.
add a comment |
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.
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
add a comment |
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
add a comment |
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
);
);
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
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
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.
"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
add a comment |
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.
"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
add a comment |
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.
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.
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
add a comment |
"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
add a comment |
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.
add a comment |
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.
add a comment |
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 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.
answered Dec 17 '14 at 9:29
PetiPeti
1,0471220
1,0471220
add a comment |
add a comment |
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.
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
add a comment |
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.
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
add a comment |
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.
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.
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
add a comment |
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
add a comment |
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
add a comment |
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
add a comment |
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
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
answered Mar 6 at 16:26
mwoodmanmwoodman
562410
562410
add a comment |
add a comment |
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.
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
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
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
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
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 anExecutor
- 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