Home > Atmosphere, Comet, JQuery, Websocket > Using JQuery, XMPP and Atmosphere to cluster your WebSocket/Comet application

Using JQuery, XMPP and Atmosphere to cluster your WebSocket/Comet application

The Extensible Messaging and Presence Protocol (XMPP) is an open technology for real-time communication, which powers a wide range of applications including instant messaging, presence, multi-party chat, voice and video calls, collaboration, lightweight middleware, content syndication, and generalized routing of XML data. The protocol’s adoption is phenomenal, and this time I will show how easy is to use the Atmosphere’s XMPP Plugin with GTalk to scale and cluster a WebSocket/Comet application.

Warning: If you have read my previous blog entry on Redis and WebSocket, this new entry will suspiciously looks similar :-) The Atmosphere Framework Plugin API is bloody simple and adding support for any cloud/clustering technology is extremely easy.

Atmosphere supports many communication channel between server, but today we will focus on our newly addition: XMPP.  For the sample I will use GTalk (but works with any XMPP server) and the XMPP library named  Smack. I will show how it is possible to deploy a WebSocket application on any Webserver and use GTalk/XMPP to share events between “the cloud”.  As usual I will use Atmosphere JQuery Plugin on the client side as the library will always try to use WebSocket, and if fail will fall back to Comet techniques. And fortunately, the Plug In will also fall back to Comet as well if the remote server isn’t supporting WebSocket.  This is great because when you deploy into a cloud or a cluster, you aren’t guarantee all servers will be the same product, same version etc. The Atmosphere Framework saves you from all those questions.  Less things to worries.

OK, so let’s write a simple PubSub application. Without going into the details (read this entry for an introduction of Atmosphere JQuery Plugin), our client side will looks like (browse the code here):


    function callback(response)
    {
      if (response.status == 200) {
        // display the result.
      }
    }
    /* transport can be : long-polling, streaming or websocket */
    $.atmosphere.subscribe(uri + 'pubsub/' + "A topic",
                           callback,
                           $.atmosphere.request = {transport: 'websocket'});

As simple as it look, we just invoke  the subscribe method with a uri, a callback and the default transport we want to use: WebSocket. The server will understand the request and act appropriately: upgrade for WebSocket, avoid committing the response for Comet. For publishing, you can use any existing Redis client or use Atmosphere JQuery Plugin as well

    $.atmosphere.response.push(uri + 'pubsub/' + "A Topic",
                               $.atmosphere.request = {data: 'Some Message'});

Here the push method re-use the existing connection (the WebSocket one) to push messages back to the server.  If WebSocket is not supported, the Plug In will still works and fall back to use Comet. That’s it for the client side.

Now, configuration wise, the Atmosphere XMPP’s plugin can be configured via your web.xml (or using the API as well):

<?xml version="1.0" encoding="ISO-8859-1"?>
<web-app xmlns="http://java.sun.com/xml/ns/j2ee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
               http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"
         version="2.4">

    <display-name>XMPPAtmosphere</display-name>

    <servlet>
        <description>AtmosphereServlet</description>
        <servlet-name>AtmosphereServlet</servlet-name>
        <servlet-class>org.atmosphere.cpr.AtmosphereServlet</servlet-class>
        <init-param>
            <param-name>org.atmosphere.useWebSocket</param-name>
            <param-value>true</param-value>
        </init-param>
        <init-param>
            <param-name>org.atmosphere.useNative</param-name>
            <param-value>true</param-value>
        </init-param>

        <init-param>
            <param-name>org.atmosphere.plugin.xmpp.
                 XMPPBroadcaster.authorizationt</param-name>
            <param-value>me@gmail.com:password</param-value>
        </init-param>
        <init-param>
            <param-name>org.atmosphere.plugin.xmpp.
                  XMPPBroadcaster.server</param-name>
            <param-value>http://gmail.com</param-value>
        </init-param>

        <load-on-startup>0</load-on-startup>
    </servlet>

    <servlet-mapping>
        <servlet-name>MeteorServlet</servlet-name>
        <url-pattern>/*</url-pattern>
    </servlet-mapping>
</web-app>

Here you specify a GMail account and which server you want to use ti transit your messages.

Now on the server side, let’s use the Atmosphere’s Jersey module and the Atmosphere XMPP Plugin. The XMPP Plugin uses the great Smack internally to connect to XMPP Server. For this demo I use GTalk. (browse the code here)

    private @PathParam("topic") XMPPBroadcaster topic;

    @GET
    public SuspendResponse subscribe() {

        return new SuspendResponse.SuspendResponseBuilder()
                .broadcaster(topic)
                .outputComments(true)
                .addListener(new EventsLogger())
                .build();
    }

    @POST
    @Broadcast
    public Broadcastable publish(@FormParam("message") String message) {
      return new Broadcastable(message, "", topic);
    }

Don’t look for more code, there isn’t more! How it works:

  1. When the JQuery Plugin issue a request like GET /pubsub/”A Topic”, the above resource is created and an instance of XMPPBroadcaster gets injected.  The XMPPBroadcaster uses the value of “A Topic” for creating a channel to the  to GTalk’ server  using your GMail ID (more on that below) . “A Topic”  is also the name of theXMPPBroadcaster , which can always be used to retrieve it by an external component like an EJB, a Java Program etc.
  2. Second, the subscribe method gets invoked, and we tell Atmosphere to suspend the response. For WebSocket, it means accept the upgrade handshake.
  3. Now any messages send using  Atmosphere JQuery’s $.atmosphere.response.push will transit in XMPP via GTalk. The $.atmosphere.response.push will invoke the publish method of your resource, which will use the XMPPBroadcaster  to progate the change to all WebSocket/Comet connection via GTalk.

That’s it. The JQuery look and field is the same as the one described here.  Of course you can do much more with XMPP and Atmosphere, but my goal for this blog was to show how easy it is to get started.

As demonstrated, writing an application with Atmosphere is super simple, and deploying it inside a cloud/distributed environment is also simple. The good news here is you don’t have to focus on how GTalk/XMPP works, but on your application. On a side note, if you want to use RedisActiveMQ (any JMS impl) or JGroups intead of Redis, this is as simple as:

    private @PathParam("topic")
    RedisBroadcaster topic; // Or JMSBroadcaster or JGroupsBroadcaster

    @GET
    public SuspendResponse subscribe() {

        return new SuspendResponse.SuspendResponseBuilder()
                .broadcaster(topic)
                .outputComments(true)
                .addListener(new EventsLogger())
                .build();
    }

Just need to inject the proper technology you want to use.

The complete binary/source code can be downloaded here. For any questions or to download Atmosphere Client and Server Framework, go to our main site and use our Nabble forum, or follow the team and myself and tweet your questions there!

About these ads
  1. Muneeb
    June 17, 2011 at 10:17 am | #1

    How would I implement this using GWT?

  2. June 25, 2011 at 3:24 am | #2

    This is fantastic! So it is possible to create a custom GTalk IM client within your own website? All powered through jQuery?

    Because I would love to build this.

  1. November 16, 2010 at 6:07 pm | #1

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Follow

Get every new post delivered to your Inbox.

Join 50 other followers

%d bloggers like this: