How to use the GWT EventBus
When you divide the project into logical parts (for example with MVP), then the different parts sometimes need to communicate. Typical this communication is done by sending status changes, e.g.:
- user logged-in / logged-out.
- user navigated directly via URL to a page, so the menu needs to be updated.
Using the event bus is quite logical in those cases.
To use it you instantiate one EventBus
per app which is then used by all other classes. To achieve this use a static field, factory or dependency injection (GIN in case of GWT).
Example with your own event types:
public class AppUtils{
public static EventBus EVENT_BUS = GWT.create(SimpleEventBus.class);
}
Normally you'd also create your own event types and handlers:
public class AuthenticationEvent extends GwtEvent<AuthenticationEventHandler> {
public static Type<AuthenticationEventHandler> TYPE = new Type<AuthenticationEventHandler>();
@Override
public Type<AuthenticationEventHandler> getAssociatedType() {
return TYPE;
}
@Override
protected void dispatch(AuthenticationEventHandler handler) {
handler.onAuthenticationChanged(this);
}
}
and the handler:
public interface AuthenticationEventHandler extends EventHandler {
void onAuthenticationChanged(AuthenticationEvent authenticationEvent);
}
Then you use it like this:
AppUtils.EVENT_BUS.addHandler(AuthenticationEvent.TYPE, new AuthenticationEventHandler() {
@Override
public void onAuthenticationChanged(AuthenticationEvent authenticationEvent) {
// authentication changed - do something
}
});
and fire the event:
AppUtils.EVENT_BUS.fireEvent(new AuthenticationEvent());
GWT MVP. How to use event bus?
If the point when the presenter needs to get the selected value is when the user makes an action you won't get around using an event. (Altough, maybe both presenters could react to the same event so don't need to use two different ones?)
If it is known when the presenter needs to get the value (a defined step in a workflow), you could to it like this:
Keep a reference to the views in the ClientFactory
:
public class ClientFactoryImpl implements ClientFactory {
private static final EventBus eventBus = new SimpleEventBus();
/* The views */
private static final SampleView sampleView = new SampleView();
....
public ClientFactoryImpl(){
eventBus.addHandler(ReleaseAddedEvent.type, sampleView);
....
}
// getter and setters
}
So in the Presenter you can get a reference to the view: SampleView view = MyEntryPoint.getClientFactory().getSampleView();
and then you can just call a method from the view which returns the selected value.
GWT Event Bus for which benefits
No event bus
Example: You can buy apples from the farm directly.
Button
maintains the collection of listeners. Button
is aware about all listeners and needs to notify them in the loop. Button
is directly coupled with the handlers.
Event bus
Example: You buy apples from a store and store buys apples from the farm. The store is a broker between you and the farm. You are not aware about the farm. The farm is not aware about you.
Event bus is broker between the event producer and event consumer. Event producer is aware about event bus but not all event consumers.
Button
is not aware about the listeners. It's aware about EventBus only.
Handlers are not aware about the Button
. They are aware about the bus.
Summary:
Applications without plugins may be implemented without event bus.
Applications with plugin support should be implemented with the event bus as it's not known before hand how many plugins are connected to the event producer.
How to use EventBus for non-Presenter class in GWTP?
I' dont use GWTP, but I guess the following is ok.
@Inject private EventBus eventBus
should work (if you don't use it in SearchDialogBox constructor right away).
Otherwise try to find out which class in GWTP extends com.google.gwt.inject.client.Ginjector. Assuming it is called "MyInjector" just write :
private EventBus eventBus = MyInjector.INSTANCE.getEventBus();
How do you use GWT's SimpleEventBus or EventBus?
A SimpleEventBus provides the very basic functionality of storing a collection of handlers, and calling event.dispatch() with all of the relevant handlers when appropriate. I wouldn't say that you "set EventBus to listen for events" from the parent widget. The SimpleEventBus doesn't have a concept of a "parent." Instead, you pass around a reference to your SimpleEventBus. Then, any object can "fire an event" with the SimpleEventBus.fireEvent method. There's no hierarchy.
Similarly, any object can listen for those events with SimpleEventBus.addHandler(). This is closest to your #4 - addHandler takes a type of event and a handler, so whenever that type of event is passed to fireEvent
(by something in your app), that handler will be passed to the event. Note that the Event
is what calls the handler, NOT the EventBus! The EventBus just calls event.dispatch(theHandler), and the programmer of the event is responsible for calling the proper function in theHandler. Your #5 is inaccurate, at least for a SimpleEventBus - SimpleEventBus does not inspect the events at all, except to see which handlers to call. It doesn't know about any child widgets or any app logic, and never changes the type of an Event.
Your logic about seeing which region was picked would not be appropriate in an EventBus - instead, you would make a handler that does the logic and listens for ClickEvents. Then, that handler could tell the selected region that it was selected directly, or you could create your own RegionSelectionEvent that you could fire along an EventBus, and then all of the regions could be informed that a RegionSelection has occurred, and your logger could get a notification, or your server monitor could get the notification and notify the boss that someone selected a region, or whatever. If you just need to deselect one region and select another, an eventbus is overkill.
On the other hand, something like a "resize" event makes a lot of sense, since all of your widgets might need to know about it.
GWT, how to fire event from widget or composite using EventBus from HandlerManager
It does not work because your FileUploadWidget
uses it's own EventBus
and not GWTP
one that is also used in all of your Presenters
.
There are two solutions:
Don't use
fireEvent(new IndicatorStartEvent("Message"))
but useeventBus.fireEvent(new IndicatorStartEvent("Message"))
on the injectedEventBus
inside of yourWidget
.Add the
IndicatorStartEvent
handler to yourFileUploadWidget
directly instead of usingaddRegisteredHandler
on yourPresenter
.
I prefer solution 2:
public class FileUploadWidget extends Composite {
MaterialFileUploader uploader = new MaterialFileUploader();
@Inject
public FileUploadWidget(String triggerId) {
super();
initWidget(uploader);
Window.alert("TEST Start");
fireEvent(new IndicatorStartEvent("Message"));
}
}
In the Presenter
or to be precise the View
which uses your FileUploadWidget
, you add a handler directly to the FileUploadWidget
:
public class UploadView extends ViewWithUiHandlers<UploadUiHandlers> implements UploadPresenter.MyView,IndicatorStartEvent.IndicatorHandler {
@UiField
FileUploadWidget uploadWidget;
@Inject
public UploadView(final Binder binder) {
widget = binder.createAndBindUi(this);
uploadWidget.addHandler(new IndicatorStartEvent.Handler(),this);
}
public void onIndicatorProgressStart(IndicatorStartEvent event) {
MaterialToast.fireToast("Indicator start: " + event.getMessage());
}
}
Which GWT EventBus should I use?
Generally you should use the one in com.google.web.bindery
. The only version used to be in com.google.gwt.event
, but when RequestFactory and AutoBeans were moved out of GWT itself and into com.google.web.bindery
so they could work in non-GWT clients.
If you use the com.google.web.bindery
version in your presenters and such, it will make it easier to use outside GWT apps, should you need to. You'll also not get deprecation warnings when passing that instance to PlaceController
and other classes that use EventBus.
Which GWT EventBus should I use?
Generally you should use the one in com.google.web.bindery
. The only version used to be in com.google.gwt.event
, but when RequestFactory and AutoBeans were moved out of GWT itself and into com.google.web.bindery
so they could work in non-GWT clients.
If you use the com.google.web.bindery
version in your presenters and such, it will make it easier to use outside GWT apps, should you need to. You'll also not get deprecation warnings when passing that instance to PlaceController
and other classes that use EventBus.
Check if GWT EventBus has an EventHandler or not
The addHandler() method returns a HandlerRegistration the removeHandler() method of which you can use to remove your handler.
Related Topics
Why Does This Gridbaglayout Not Appear as Planned
"Not Allowed to Load Local Resource: File:///C:....Jpg" Java Ee Tomcat
"Noclassdeffounderror: Could Not Initialize Class" Error
When Should an Illegalargumentexception Be Thrown
When to Use a Constructor and When to Use Getinstance() Method (Static Factory Methods)
How to Get the Http Status Code Out of a Servletresponse in a Servletfilter
Change Database Schema Used by Spring Boot
How to Mock New Date() in Java Using Mockito
Does Java Read Integers in Little Endian or Big Endian
How to Serialize Only the Id of a Child with Jackson
Remove Last Character of a Stringbuilder
Why Does Intellij Give Me "Package Doesn't Exist" Error
How to Stop a Thread Created by Implementing Runnable Interface
Tomcat7 Starts Too Late on Ubuntu 14.04 X64 [Digitalocean]