Skip to content

GlobalEventBus: Real time communication

sockeqwe edited this page Jun 23, 2013 · 5 revisions

Wouldn't it be nice to have a way to communicate with multiple clients in real time? In this chapter we will present you a component that you can use to realize this in an elegant way. Say hello to the GlobalEventBus.

#The basic idea We guess we have convinced you that an EventBus is something very useful and the @EventHandler Annotation makes it really easy to handle Events. Imagine that one user has changed something. We would define an Event for this:

public class SomethingChangedEvent extends Event {
	...  
}

Whenever the user has changed something, we want to inform all other local Views or better all other presenters about the change: Therefore we would fire a new SomethingChangedEvent in the local EventBus.

eventBus.fireEvent(new SomethingChangedEvent());

But what if the change concerns other users that are now online? Wouldn't it be nice if we could inform other users as well about the change? With the GlobalEventBus its really easy with minimal work for you as programmer. You can simply fire the same SomethingChangedEvent via the GlobalEventBus and the other users will receive this Event and the received Event will dispatched to the receivers local EventBus.

How to fire an Event

The GlobalEventBus is a singleton class. It provides five methods to fire Events. The first is to fire an Event to every user that is online right now:

public static void fireBroadcastEvent(Event event);

// example
GlobalEventBus.fireEvent(new SomethingChangeEvent());

This call will fire an Event to everybody including the sender himself.

The second method is to fire an Event to everybody, excluding the sender himself:

public static void fireBroadcastEvent(Event event, String sessionIdOfSender);

The GlobalEventBus usses the unique HttpSession id (javax.servlet.http.HttpSession.getId()) to distinguish clients. Therefore we pass the session id as second parameter, to ensure that the fired event is dispatched to every other client, excepted the sender himself. The HttpSession id can be retrieved by Vaadins Application class by calling

WebApplicationContext c = (WebApplicationContext) getContext();
String sessionId =  c.getHttpSession().getId();

But why should we use this second method instead of the first method (broadcast to all, including sender himself)? The reason is that it could come to an delay of a few milliseconds up to seconds durring firing and dispatching process of the GlobalEventBus. The delay could leed to a bad user experience. Imagine you have changed something in you local app, but not every SubView of your local vaadin application has been informed yet about the change because of the delay by firing the Event over the GlobalEventBus. Therefore we always recommend to fire the event to the users local EventBus and then to the other users via the GlobalEventBus (excluding the sender himself):

SomethingChangeEvent e = new SomethingChangedEvent();

// fire on the local eventBus
eventBus.fireEvent(e);

// fire on the GlobalEventBus, excluding the sender
GlobalEventBus.fireEvent(e, getSessionId() );

The third method is to fire an Event to a specific user, which is identified by the username:

public static void fireEventToUser(String username, Event event);

The fourth method is to fire an Event to a group of users:

	public static void fireGroupBroadcastEvent(Event e, String groupName);

The fifth method is almost the same like the fourth. You can fire an Event to a group of user excepted the sender himself (by passing the senders session id):

The fourth method is to fire an Event to a group of users:

	public static void fireGroupBroadcastEvent(Event e, String groupName, String sessionIdOfSender);

#GlobalEventBusDispatcher You may now asking yourself, how do I register a client with an username or for a certain group and how do I get the Events from the GlobalEventBus to the users local EventBus? The answer is that there is a component that will do that for you automatically: The GlobalEventBusDispatcher:

public interface GlobalEventBusDispatcher {
	
	/**
	 * Starts to listen to the {@link GlobalEventBus} 
	 * for new incomming {@link Event}s
	 */
	public void start();
	
	/**
	 * Stops to listen to the {@link GlobalEventBus}
	 */
	public void stop();

}

RefresherGlobalEventBusDispatcher

Currently there is only one implementation of the GlobalEventBusDispatcher available: RefresherGlobalEventBusDispatcher. This dispacher uses the gread Refresher Addon of Henrik Paul. The idea behind the RefresherGlobalEventBusDispatcher is that this dispatcher queries the GlobalEventBus peroidically (default: 2 seconds) for new Events, which are stored in a queue. So its not real time push mechanism, its a pull mechanism, but you get the guarantee that it will work on almost any browser and with every server. The disadvantage is, that your server get a lot of senseless requests, which will end in a high server payload (depending on the count of users). However, we find its currently the best solution for such an mechanism in vaadin.

public RefresherGlobalEventBusDispatcher(String username, String sessionId, 
	List<String> groupNames, EventBus localEventBus){
	... 
}

The first two parameter are the username, the sessionId. The third is a List of groupNames (Strings). So you can specify by yourself the groupmembership. Like we mentioned above Events can be fired to certain groups. For example, in a real world application you would have a group of admins. The last parameter is the local EventBus. So all incoming Events are forwarded to the local EventBus.

In the last step, add the RefresherGlobalEventDispatcher to the main Window: mainWindow.addComponent(globalDispatcher);

###A real push GlobalEventBusDispatcher Like we have mentioned above, the RefreshGlobalEventBusDispatcher is the only dispatcher implemented yet and its not uses server push, but queries the GlobalEventBus periodically for new Events. We currently evaluate for the best push solution, but to be hornest, we are not happy with the current available server push addons, because every addon has its advantages and disadvantages. But no one seems to be the perfect solution in general. That why we want to wait untli Vaadin 7 is finaly released. We also hope that Vaadin 7 brings a standard push mechanism already build in.


Read previous: View Navigation