Reverse Ajax, Part 4: Atmosphere and CometD

Learn to use the best open source Reverse Ajax libraries for Java technology servers

This series explores how to develop event-driven web applications using Reverse Ajax techniques. Part 1 introduced different ways to implement a Reverse Ajax communication. Part 2 explained how to implement Reverse Ajax using WebSockets, and discussed the limitations of web servers using Comet and WebSockets. Part 3 explored the difficulties of implementing your own Comet or WebSockets communication system if you need to support several servers or provide an independent Web application that users can deploy on their own server. It also introduced Socket.IO. In this article, learn about Atmosphere and CometD—the best-known open source Reverse Ajax libraries for Java technology servers.

Share:

Mathieu Carbou, Java Web Architect, Ovea

Mathieu Carbou photoMathieu Carbou, a Java web architect and consultant at Ovea, provides services and development solutions. He is a committer and leader of several open source projects, a speaker, and a leader of Montreal's Java User Group. Mathieu has a strong background in code design and best practices, and is a specialist of event-driven web development from the client side to the back end. He focuses on providing event-driven and messaging solutions in highly scalable web applications. Check out his blog.



06 September 2011

Also available in Chinese Russian Japanese Vietnamese

Introduction

This series shows you how to develop event-driven web applications using Reverse Ajax techniques. Part 1 introduced Reverse Ajax, polling, streaming, Comet, and long polling. Part 2 explained how to implement Reverse Ajax using WebSockets and discussed the limitations of web servers using Comet and WebSockets. Part 3 showed that implementing your own Comet or WebSockets communication system can be difficult if you need to support several servers or provide an independent web application for users to deploy on their own server. Even if the JavaScript code on the client side is simple, you would need some exception handling, reconnection, and acknowledgement features. On the server side, the lack of a global API and the multiple web server APIs lead to the need for frameworks, which brings an abstraction. Part 3 also discussed Socket.IO.

In this article, learn about Atmosphere and CometD. They are the most widely known open source Reverse Ajax libraries for Java servers.

You can download the source code used in this article.

Prerequisites

Ideally, to get the most out of this article, you should know JavaScript and Java. To run the sample in the article, you will also need the latest version of Maven and the JDK (see Resources).


The Atmosphere framework

Atmosphere is a Java technolog framework that provides a common API for using the Comet and WebSocket features of many of the web servers, including Tomcat, Jetty, GlassFish, Weblogic, Grizzly, JBossWeb, JBoss, and Resin. Any web server supporting the Servlet 3.0 Specification is also supported. Of the frameworks presented in this series of articles, Atmosphere supports the most servers.

Atmosphere can detect native server APIs (for Comet and WebSockets) and switch back to Servlet 3.0, if available, for Comet. Or, also for Comet, it will fall back to a "managed" asynchronous mode (but not as scalable as Jetty Continuations). Atmosphere has been around for more than two years, and it is still in active development. It is used in large web applications such as JIRA, which is one of the best known issue trackers. Figure 1 shows the Atmosphere architecture.

Figure 1. Architectural view of Atmosphere
Architectural view of the Atmosphere framework

The Atmosphere framework is composed of the Atmosphere runtime, which provides a common API for all different web server solutions and standards. On top of this, the client can access the API and Reverse Ajax features through the Google Web Toolkit (GWT) by setting up a mere servlet. Or, you can also use Jersey, a framework implementing the JSR-311 (JAX-RS specification). Thus, Atmosphere can be used in restful services with additional annotations provided. After configuring your chosen module, you can then access the Atmosphere runtime by implementing some classes (discussed later in this article). You can also optionally use some provided plugins that add support for clustering, messaging, dependency injection, and more. If you're using a web framework (Wicket, Struts, Spring MVC), you can transparently add Reverse Ajax support by using the MeteorServlet of Atmosphere. This servlet exposes a Meteor object that can be retrieved within your controllers and services to suspend or resume the requests.

Atmosphere's strength remains on the server side: it provides a standardized API that covers all of the different solutions and ways to communicate with WebSockets or Comet. Atmosphere does not use a protocol between the client and server, like Socket.IO and CometD. Both libraries provide a client-side JavaScript and a server-side servlet that communicate using a specific protocol (for handshaking, messaging, acknowledgment, and heartbeat). Atmosphere's goal is to provide a common communication channel on the server side. If you need to use a specific protocol, such as Bayeux (a protocol used by CometD), you have to develop your own "handler" in Atmosphere. The CometD plugin does just that: it takes advantage of Atmosphere's API to suspend and resume the requests, and it delegates to CometD classes to manage the CometD communication using the Bayeux protocol.

Atmosphere comes with a jQuery client library to facilitate the connection setup, which is able to automatically detect the best transport available (WebSockets or CometD). Usage of Atmosphere's jQuery plugin is similar to the HTML5 WebSockets API. First, you connect to the server, register a callback to receive messages, and then you can push some data.

The source code included with this article contains an Atmosphere sample that directly uses a handler with the Atmosphere servlet. The client code is always the same; it's the same code used in Parts 1, 2, and 3 of this series (in the chat samples using Comet long polling). You could have used Atmosphere's jQuery plugin, but it's not required because Atmosphere does not enforce any communication protocol. It is strongly suggested that you look at the other examples in Atmosphere's project, especially those using JSR-311 annotations (Jersey). They really simplify the writing of handlers.

Listing 1 shows the Atmosphere handler interface.

Listing 1. AtmosphereHandler interface
public interface AtmosphereHandler<F, G> { 
    void onRequest(AtmosphereResource<F, G> resource) 
        throws IOException; 
    void onStateChange(AtmosphereResourceEvent<F, G> event) 
        throws IOException; 
    void destroy(); 
}

The onRequest method receives all requests from the client and decides whether to suspend or resume them (or do nothing). Each time a request is suspended or resumed, a broadcast is sent, or a timeout occurs, an event is sent and received by the onStateChange method.

The implementation of the onRequest method for the Comet chat is shown in Listing 2.

Listing 2. AtmosphereHandler interface - onRequest
Broadcaster broadcaster = 
        BroadcasterFactory.getDefault().lookup(
        DefaultBroadcaster.class, ChatHandler.class.getName(), true); 
broadcaster.setScope(Broadcaster.SCOPE.APPLICATION); 
resource.setBroadcaster(broadcaster); 
HttpServletRequest req = resource.getRequest(); 
String user = (String) req.getSession().getAttribute("user"); 
if (user != null) { 
    if ("GET".equals(req.getMethod())) { 
        resource.suspend(-1, false); 
    } else if ("POST".equals(req.getMethod())) { 
        String cmd = req.getParameter("cmd"); 
        String message = req.getParameter("message"); 
        if ("disconnect".equals(cmd)) { 
            close(resource); 
        } else if (message != null && message.trim().length() > 0) {
            broadcaster.broadcast("[" + user + "] " + message); 
        } 
    } 
}

A typical convention is to suspend GET requests and send messages using POST requests. When a message is received, it is broadcast to all resources registered within the broadcaster. Notice that the example never writes anything to the HttpServlet output stream. The broadcast or suspend action just sends events received by the other method implemented, as shown in Listing 3:

Listing 3. AtmosphereHandler interface - onStateChange
Broadcaster broadcaster = 
    BroadcasterFactory.getDefault().lookup(
        DefaultBroadcaster.class, ChatHandler.class.getName(), true); 
// Client closed the connection. 
if (event.isCancelled()) { 
    close(event.getResource()); 
    return; 
} 
try { 
    String message = (String) event.getMessage(); 
    if (message != null) { 
        PrintWriter writer = 
            event.getResource().getResponse().getWriter(); 
        writer.write(message); 
        writer.flush(); 
    } 
} finally { 
    if (!event.isResumedOnTimeout()) { 
        event.getResource().resume(); 
    } 
}

And now you have all you need for a working Comet chat. To summarize, the important Atmosphere concepts are: the resource object representing the connection, and a broadcaster responsible for firing events to resources and deciding when to suspend or resume a request. Note that the example is Comet only. To be able to use WebSockets and Comet, a client-side library should be used and a more complex handler would be needed.

Table 1 outlines the pros and cons of using the Atmosphere framework.

Table 1. Pros and cons of Atmosphere
ProsCons

If you have to deploy a web application in several web servers that you can't control. You'll have a better chance that the Reverse Ajax features of your application work correctly due to the number of web servers supported by Atmosphere.

When you need a common API over a raw Reverse Ajax communication, without any protocol defined, because you want to develop or extend it.

Lack of documentation about Atmosphere's architecture, project, concepts, and APIs, which is helpful if you need to go into the source code or analyze several provided samples. The API is highly technical, and sometimes obscure, compared to the simple APIs of other frameworks, such as Socket.IO and CometD. Even when using Atmosphere annotations, some names and attributes were too technical.

Though a good abstraction on the server side, there is not a good client library. There is no protocol, so all additional features are left to the developer. The current library is too simple for the needs of a big, scalable web application if you require advanced timeout detection, acknowledgement, back-off, cross-domain and so on, especially when working with mobile devices. In this case, CometD is much more reliable; it leverages a communication protocol that can be used to activate some control flow and error detection, all provided within CometD. Using the CometD JavaScript client with the Atmosphere CometD plugin could be a good alternative if you need extra features.


The CometD framework

The CometD framework, an event-driven communication solution based on HTTP, has been around for several years. Version 2 added support for annotation configuration and WebSockets. The CometD framework provides a Java server part and a Java client part, plus JavaScript client libraries based upon jQuery and Dojo. CometD uses a standardized communication protocol called Bayeux, allowing you to activate some extensions for message acknowledgement, flow control, synchronization, clustering, and so on.

CometD's event-driven approach fits very well with the new concept of event-driven web development. As with traditional desktop user interfaces, all of the components communicate through a bus to send notifications and receive events. All communication is therefore asynchronous.

The CometD framework:

  • Is well-documented.
  • Provides samples and Maven archetypes to facilitate the startup of a project.
  • Has a well-designed API that enables extension development.
  • Provides a clustering module, called Oort, that gives you the ability to run multiple CometD web servers as nodes in a cluster behind a load balancer to scale to a larger number of HTTP connections.
  • Supports security policies to allow a fine-grain configuration of who can send messages over which channel.
  • Integrates quite well with Spring and Google Guice (dependency injection frameworks).

Bayeux protocol

The Bayeux communication protocol is primarily over HTTP. It asynchronously provides a responsive bi-directional communication between the client and server. The Bayeux protocol is based on channels where messages are routed and delivered client to server, server to client, or client to client (but through the server). Bayeux is a type of publish-subscribe protocol. CometD implements the Bayeux protocol, and thus provides an abstraction layer on top of Comet and WebSocket transports to route requests through Bayeux.

Servers and internals

CometD is bundled with three transports: JSON, JSONP, and WebSocket. They depend upon Jetty Continuations and the Jetty WebSocket API. By default, CometD can be used in Jetty 6, 7, and 8, as well as any other servers supporting the Servlet 3.0 Specification. Transports can be added and developed in the same way as extensions. You should be able to write transports supporting the Grizzly WebSocket API and others, and then add them at the step where the CometD server is configured. Figure 2 shows an overview of the main CometD blocks.

Figure 2. Architectural view of CometD
Architectural view of CometD framework, which is composed of a client-side library and server-side library communicating through the Bayeux protocol. CometD supports extensions and different transport layers (WebSockets, Ajax long polling, ...), as well as several APIs on the server side.

The security layer to access message channels is not shown in Figure 2.

The source code provided with this article includes a web application using CometD. The web application's descriptor contains the definition in Listing 4 for the chat example.

Listing 4. web.xml
<servlet> 
    <servlet-name>cometd</servlet-name> 
    <servlet-class>
        org.cometd.java.annotation.AnnotationCometdServlet
    </servlet-class> 
    <async-supported>true</async-supported> 
    [...]
    <init-param> 
        <param-name>services</param-name> 
        <param-value>ChatService</param-value> 
    </init-param> 
    <init-param> 
        <param-name>transports</param-name> 
        <param-value>
            com.ovea.cometd.websocket.jetty8.Jetty8WebSocketTransport
        </param-value> 
    </init-param> 
</servlet>

The CometD servlet supports several options controlling global settings, such as the ability to set transports and services. In the example, assume you want to add WebSocket support for Jetty 8. The CometD service class ChatService on the server side will control the chatroom where everyone is speaking, as shown in Listing 5:

Listing 5. CometD ChatService
@Service 
public final class ChatService { 

    @Inject 
    BayeuxServer server; 

    @PostConstruct 
    void init() { 
        server.addListener(new BayeuxServer.SessionListener() { 
            @Override 
            public void sessionAdded(ServerSession session) { 
                [...]
            } 

            @Override 
            public void sessionRemoved(ServerSession session, boolean timedout) {
                [...]
            } 
        }); 
    } 

    @Configure("/**") 
    void any(ConfigurableServerChannel channel) { 
        channel.addAuthorizer(GrantAuthorizer.GRANT_NONE); 
    } 

    @Configure("/chatroom") 
    void configure(ConfigurableServerChannel channel) { 
        channel.addAuthorizer(new Authorizer() { 
            @Override 
            public Result authorize(
                [..] // check that the user is in session
            } 
        }); 
    } 

    @Listener("/chatroom") 
    void appendUser(ServerSession remote, 
                    ServerMessage.Mutable message) { 
        [...]
    } 

}

Listing 5 demonstrates some of the important features of CometD, including:

  • Dependency injection
  • Life cycle management
  • Global channel configuration
  • Security management
  • Message transformation (to add the user name before all messages)
  • Session management

On the client side, the example did not activate any extension -- just the raw CometD code, as shown in Listing 6:

Listing 6. CometD client code
// First create t cometd object and configure it

var cometd = new $.Cometd('CometD chat client'); 
cometd.configure({ 
    url: document.location + 'cometd', 
    logLevel: 'debug' 
}); 
cometd.websocketEnabled = 'WebSocket' in window;

// Then we register some listeners. Meta channels (those with 
// the form /meta/<name> are specific reserved channels)

cometd.addListener('/meta/disconnect', function(message) { 
    [...]
}); 

cometd.addListener('/meta/connect', function(message) { 
    [...]
});

// Then, starting a connexion can be done using:

cometd.handshake();

// And subscriptions with:

cometd.subscribe('/chatroom', function(event) { 
    [...] //  event.data holds the message
});

// We finally send data to the chatroom like this:

cometd.publish('/chatroom', msg);

CometD's client-side API is simple to use and understand, while remaining powerful and extensible. This article only covers the major parts of the web application, so check out the example application to get a better idea of the power of CometD.

Table 2 outlines the pros and cons of using the CometD framework.

Table 2. Pros and cons of CometD
ProsCons

CometD offers a complete solution, from client and server side, and also from a standalone Java client to a server. The framework is well-documented, has a good API, and is easy to use. Best of all, it has an event-driven approach. CometD and Bayeux are part of many event-driven web applications. Other Reverse Ajax frameworks don't provide any event-driven mechanisms, forcing end users to develop their own custom solution.

CometD supports many required features, such as reconnection, reliable timeout detection, back-off, batching, message acknowledgement, and more that you won't find in other Reverse Ajax frameworks. CometD lets you achieve the most reliable, low-latency communication possible.

CometD currently does not support any Servlet 2.5 containers other than Jetty for Comet (Tomcat), and it does not support Glassfish/Grizzly WebSocket.


Conclusion

Both Atmosphere and CometD are solid, open source Reverse Ajax solutions. At Ovea, our choice is CometD because we develop scalable event-driven web applications for mobile devices within a clustered environment, and we have total control over the infrastructure (we use Jetty). However, without additional development, CometD might not be the best choice if you are selling web applications and want your Reverse Ajax features to work on as many servers as possible. But knowing that more and more Web containers now support the Servlet Specification 3.0, CometD's limitation tends to decrease. Speaking about the transport layer, the main remaining difference now relies on the WebSocket support.


Download

DescriptionNameSize
Article source codereverse_ajaxpt4_source.zip28KB

Resources

Learn

Get products and technologies

  • Atmosphere source code: Get Atmoshphere, a POJO based framework using Inversion of Control (IoC) to bring push/Comet and Websocket to the masses.
  • CometD source code: Get the project that's a scalable comet (server push) implementation for web messaging.
  • CometD extensions: Get them for Jetty 8 WebSocket support and Google Guice support from Ovea.
  • Jetty: Get Jetty, a web server and javax.servlet container, plus support for WebSockets.
  • Apache Tomcat Advanced I/O documentation: Get valuable links, a User Guide, Reference, and Apache Tomcat Development instructions.
  • Grizzly NIO Framework: To help you take advantage of the Java NIO API.
  • Grizzly Comet Sample: See the changes you'll need to make to existing applications before building a new one from scratch.
  • Glassfish Application Server: Get the main GlassFish Server Open Source Edition.
  • Socket.IO Java: Get the original project and the most updated Ovea's fork.
  • Apache Maven: Get Maven, a software project management and comprehension tool.
  • Java Development Kit, Version 6: Get the Java Platform, Standard Edition (Java SE), which lets you develop and deploy Java applications on desktops and servers, as well as in today's demanding embedded environments.
  • Try out IBM software for free. Download a trial version, log into an online trial, work with a product in a sandbox environment, or access it through the cloud. Choose from over 100 IBM product trials.

Discuss

Comments

developerWorks: Sign in

Required fields are indicated with an asterisk (*).


Need an IBM ID?
Forgot your IBM ID?


Forgot your password?
Change your password

By clicking Submit, you agree to the developerWorks terms of use.

 


The first time you sign into developerWorks, a profile is created for you. Information in your profile (your name, country/region, and company name) is displayed to the public and will accompany any content you post, unless you opt to hide your company name. You may update your IBM account at any time.

All information submitted is secure.

Choose your display name



The first time you sign in to developerWorks, a profile is created for you, so you need to choose a display name. Your display name accompanies the content you post on developerWorks.

Please choose a display name between 3-31 characters. Your display name must be unique in the developerWorks community and should not be your email address for privacy reasons.

Required fields are indicated with an asterisk (*).

(Must be between 3 – 31 characters.)

By clicking Submit, you agree to the developerWorks terms of use.

 


All information submitted is secure.

Dig deeper into Web development on developerWorks


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=1
Zone=Web development
ArticleID=756124
ArticleTitle=Reverse Ajax, Part 4: Atmosphere and CometD
publish-date=09062011