How to design push notifications using Atmosphere

Saurabh Kumar picture Saurabh Kumar · Nov 12, 2013 · Viewed 15.9k times · Source

I want to use atmosphere to develop a notification System.

I am very new to Atmosphere so apologies if I am wrong somewhere. What i understood is when a Actor publishes something I save the notification action to the database. What i don't understand how the receiver will receive those notifications in realtime.

The sender i know will do something like following

event.getBroadcaster().broadcast(
            objectMapper.writeValueAsString("Some Message"));

Now i am not able to figure out how the receiver can receive this message.

For example . I want to add a User Object as Friend. So when User1 adds User2 User1 broadcast but than how i push the notification to User2. I have difficulty in understanding this.

Technically i want something similar like facebook or gmail notification where on user activity other users get notifications.

Answer

elusive-code picture elusive-code · Nov 21, 2013

Basically what you need is to implement Publish-subscribe on top of Atmosphere.

Atmosphere consists of two parts: client-side (javascript-based) and server-side(java-based).

First of all you need to configure server-side: Installing Atmosphere

Namely servlet or filter, it is required so that it could add AtmosphereResource to the HttpServletRequest.

AtmosphereResource represents a single client connection on the server-side.

Broadcaster is actually a container for these resources, so that you don't need to handle lookup/iteration/concurrency when you need to send to multiple connections. (Note that multiple connections can be produced by single client).

On the server-side you need to provide clients an endpoint to subscribe for notifications. For example, if you are using Spring-MVC, it could go like this (omitting validations/authentications, etc.):

@RequestMapping(value = "/user-notifications/{userId}")
@ResponseStatus(HttpStatus.OK)
@ResponseBody
public void watch(@PathVariable("userId") String userId,
                  HttpServletRequest request) throws Exception {
    //Atmosphere framework puts filter/servlet that adds ATMOSPHERE_RESOURCE to all requests
    AtmosphereResource resource = (AtmosphereResource)request.getAttribute(ApplicationConfig.ATMOSPHERE_RESOURCE);

    //suspending resource to keep connection
    resource.suspend();

    //find broadcaster, second parameter says to create broadcaster if it doesn't exist
    Broadcaster broadcaster = BroadcasterFactory.getDefault().lookup(userId,true);

    //saving resource for notifications
    broadcaster.addAtmosphereResource(resource);
}

When something happens you can notify clients like this:

public void notify(User user, Event event){
    Broadcaster b = BroadcasterFactory.getDefault().lookup(user.getId());
    if (b!=null){
        b.broadcast(event);
    }
}

On the client side you need to send a subscribe request and listen for subsequent events, like this:

var request = new atmosphere.AtmosphereRequest();
request.url = '/user-notifications/'+userId;
request.transport = 'websocket';
request.fallbackTransport = 'streaming';
request.contentType = 'application/json';
request.reconnectInterval = 60000;
request.maxReconnectOnClose = 1000;
request.onMessage = function(response){
    console.log(response);
    alert('something happend<br>'+response);
};
that.watcherSocket = atmosphere.subscribe(request);

So, to sum it up:

  1. Client sends request "I want to receive this kind of notifications".
  2. Server receives request, suspends and saves connection somewhere (either in your code or in Broadcaster).
  3. When something happens server looks for suspended connection and sends notification in it.
  4. Client receives notification and callback is invoked.
  5. Profit!!!

This wiki has explanations for some concepts behind Atmosphere and links to other documentation.