SlideShare a Scribd company logo
1 of 19
Download to read offline
Developing with Comet and Java
      Implementing the Servlet 3.0 specification

      Skill Level: Intermediate


      Michael Galpin
      Software architect
      eBay



      26 May 2009


      Explore the different implementations of developing with Comet. See how popular
      Java™ Web servers like Jetty and Tomcat have enabled Comet applications, and
      learn how to program with each server. And finally, learn about the standardization
      proposals for Comet in Java that are part of the upcoming Servlet 3.0 and JavaEE 6
      specifications.


      Getting started
      In this article I will show you how to build some simple Comet-style Web applications
      using a variety of Java technologies. Some light knowledge of Java servlets, Ajax,
      and JavaScript will be useful. We will look at the Comet-enabling features of both
      Tomcat and Jetty, so you will want the latest versions of each. Tomcat 6.0.14 and
      Jetty 6.1.14 were used in this article. You will also need a Java Development Kit
      supporting Java 5 or higher. JDK 1.5.0-16 was used in this article. You also might
      want to look at a pre-release version of Jetty 7, as it implements the Servlet 3.0
      specification that we will examine in this article. See Resources for download links.


      Understanding Comet
      You may have heard of Comet, given its recent share of buzz. Comet is sometimes
      called reverse Ajax or server-side push. The idea is pretty simple: push data from
      the server to the browser without the browser requesting it. This sounds simple, but


Developing with Comet and Java
© Copyright IBM Corporation 2009. All rights reserved.                                  Page 1 of 19
developerWorks®                                                                       ibm.com/developerWorks



     if you are familiar with Web applications, and in particular the HTTP protocol, then
     you know it is anything but simple. Implementing Comet-style Web applications in a
     way that scales on both the browser and the server is something that has only
     become generally feasible in recent years. Later in this article we will look at how
     some popular Java Web servers enable scalable Comet architectures, but first let's
     look at why you would create Comet applications and the general design patterns
     used to implement them.

     Motivations for using Comet

     It is hard to argue with the success of the HTTP protocol. It is the foundation of the
     bulk of the information exchange on the Internet. However, it has several limitations.
     In particular, it is a stateless, one-way protocol. A request is sent to a Web server,
     and that server turns around and issues a response—end of story. The request has
     to be initiated by the client, and the server can only send data in response to a
     request. This can make a number of types of Web applications a bit impractical to
     say the least. The classic example is a chat program. Other examples are sports
     scores, stock tickers, or e-mail programs.

     The limitations of HTTP are also responsible for some of its success. The
     request/response cycle lends itself to the classic one thread per connection model.
     As long as you can service the request quickly, this approach can scale massively. A
     huge number of requests per second can be handled, and a relatively low number of
     servers can handle a very large number of users. This is a perfect fit for many of the
     classic types of Web applications such as content management systems, search
     applications, and e-commerce sites, just to name a few. In each case, the server
     provides the data that the user requests and can then close the connection, allowing
     that thread to be freed up to serve other requests. If interaction was possible after
     the initial data was served, and the connection was kept open, then the thread could
     not be released and the server would not be able to serve many users.

     But what if you want to keep interacting with the user after the initial data is sent in
     response to a request? In the early days of the Web, this used to be accomplished
     using a meta refresh. This would automatically instruct the browser to reload the
     page after a specified number of seconds, thus enabling a crude form of polling. This
     is not only a bad user experience, but it is generally a terribly inefficient way of doing
     things. What if there is no new data to show on the page? The exact same page just
     gets re-rendered. What if the change to the page is very small, and most of the page
     does not change? Again, everything gets re-requested and re-drawn, if it needs to
     be or not.

     The advent and popularity of Ajax changed the above scenario. Now the server can
     be contacted asynchronously, thus the entire page does not have to be
     re-requested. An incremental update is now possible. All you need to do is poll the
     server using an XMLHttpRequest. This technique is commonly known as Comet.
     There are several variations on this technique, each with different performance and


Developing with Comet and Java
Page 2 of 19                                               © Copyright IBM Corporation 2009. All rights reserved.
ibm.com/developerWorks                                                                     developerWorks®



      scalability characteristics. Let's take a look at these different styles of Comet.

      Comet styles

      The viability of Ajax made Comet possible. The one-way nature of HTTP could be
      effectively worked around. As it turns out there are actually several different ways to
      pull this off. As you have probably guessed, the easiest way to enable Comet is to
      poll. You make a call to your server using XMLHttpRequest, and as soon as it
      comes back, wait a fixed amount of time (usually using JavaScript's setTimeout
      function), and then call it again. This is a very common technique. For example, this
      is how most webmail applications show you new e-mail messages when they arrive.

      There are some pros and cons to this technique. In this setup, you expect the
      response to come back quickly, like any other Ajax request. Having the pause in
      between requests like this is essential. Otherwise you would bombard your server
      with constant requests, and clearly that would not scale. This pause introduces a
      latency in your application. The longer your pause, the longer it takes for new data
      from the server to arrive on the client. If you shorten up the pause, then you run back
      into the risk of overwhelming your server. On the other hand, this is definitely the
      simplest way to implement Comet.

      Now, it should be pointed out that many people do not consider polling to be Comet.
      Instead they consider Comet to be the solutions to the limitations of polling. The
      most common quot;truequot; Comet technique is a variant of polling called long polling. The
      main difference between polling and long polling is how long it takes the server to
      respond. A long poll generally keeps the connection open for a long time—usually
      several seconds, but it could be a minute or longer. When an event happens on the
      server, the response is sent and closed, and the poll immediately begins anew.

      The advantage of a long poll over normal polling is that data goes from the server to
      the client as soon as it is available. The request may wait a long time with nothing to
      send back, but once there is something new, it is immediately sent to the client.
      There is no latency. If you have used a Web-based chat program, or anything that
      claims to be quot;real-timequot;, it probably used this technique.

      There is a variation of the long poll, a third flavor of Comet that is worth mentioning.
      This is usually referred to as streaming. In this flavor, the server pushes data back to
      the client, but does not close the connection. The connection stays open until it
      times out and causes the request to get re-initiated. The XMLHttpRequest
      specification states that you can check for a readyState of 3 or Receiving (as
      opposed to the usual readyState of 4 or Loaded) and get the data that is
      quot;streamingquot; from the server. This is similar to long polling in that there is no latency.
      When the data is ready on the server, it is sent to the client. It has an added
      advantage of making far fewer requests to the server, thus avoiding the overhead
      and latency associated with setting up the connection to the server. Unfortunately,
      there is great variance in the implementation of XMLHttpRequest across browsers.


Developing with Comet and Java
© Copyright IBM Corporation 2009. All rights reserved.                                         Page 3 of 19
developerWorks®                                                                       ibm.com/developerWorks



     This technique only works reliably on the newer versions of Mozilla Firefox. For
     Internet Explorer or Safari, you need to stick to long polling.

     At this point you might be thinking that there is a major problem with both long
     polling and streaming. The request stays alive on the server for a long time. This
     breaks the one thread per request model, as the thread for a request never gets
     freed up. Even worse, this thread will be sitting idle until there is data to send back.
     This definitely will not scale. Luckily, modern Java Web servers have ways of
     addressing this.


     Comet on Java
     There have always been a lot of Web servers built with Java. One reason for this is
     that Java has a rich, native thread model. Thus it is relatively straightforward to
     implement the classic one thread per connection model. This model does not work
     so well for Comet, but fortunately Java once again has a solution. To handle Comet
     efficiently, you need non-blocking IO, and Java has this via its NIO library. Two of
     the most popular open source servers, Apache Tomcat and Jetty, have both
     leveraged NIO to add non-blocking IO and thus enable Comet. However, the
     implementations are quite different. Let's take a look at both Tomcat and Jetty's
     support for Comet.

     Tomcat and Comet

     For Apache Tomcat, there are two major things that you need to do to get Comet
     working. First, you need to make a small change in Tomcat's configuration file,
     server.xml. The more typical synchronous IO connector is enabled by default. You
     just need to switch this to the asynchronous version as shown in Listing 1.

     Listing 1. Modify Tomcat's server.xml

       <!-- This is the
       usual Connector,
       comment it out
       and add the NIO
       one -->
          <!-- Connector
       URIEncoding=quot;utf-8quot;
       connectionTimeout=quot;20000quot;
       port=quot;8084quot;
       protocol=quot;HTTP/1.1quot;
       redirectPort=quot;8443quot;/
       -->
       <Connector
       connectionTimeout=quot;20000quot;
       port=quot;8080quot;
       protocol=quot;org.apache.
       coyote.http11.Http11NioProtocolquot;
       redirectPort=quot;8443quot;/>




Developing with Comet and Java
Page 4 of 19                                               © Copyright IBM Corporation 2009. All rights reserved.
ibm.com/developerWorks                                                             developerWorks®



      This allows for Tomcat to handle many more simultaneous connections, with the
      caveat that most of those connections are going to be idle much of the time. The
      easiest way to take advantage of this is to create a servlet that implements the
      org.apache.catalina.CometProcessor interface. This is obviously an
      interface unique to Tomcat. An example of this is shown in Listing 2.

      Listing 2. Tomcat Comet servlet

       public class
       TomcatWeatherServlet
       extends
       HttpServlet
       implements
       CometProcessor {
           private
       MessageSender
       messageSender =
       null;
           private
       static final
       Integer TIMEOUT =
       60 * 1000;
           @Override
           public void
       destroy() {
       messageSender.stop();
       messageSender =
       null;
             }
           @Override
           public void
       init() throws
       ServletException
       {
       messageSender =
       new
       MessageSender();
               Thread
       messageSenderThread
       =
       new
       Thread(messageSender,
       quot;MessageSender[quot;
       +
       getServletContext()
       .getContextPath()
       + quot;]quot;);
       messageSenderThread.setDaemon(true);
       messageSenderThread.start();
             }
           public void
       event(final
       CometEvent event)
       throws
       IOException,
       ServletException
       {
       HttpServletRequest



Developing with Comet and Java
© Copyright IBM Corporation 2009. All rights reserved.                                   Page 5 of 19
developerWorks®                                                                   ibm.com/developerWorks




       request =
       event.getHttpServletRequest();
       HttpServletResponse
       response =
       event.getHttpServletResponse();
               if
       (event.getEventType()
       ==
       CometEvent.EventType.BEGIN)
       {
       request.setAttribute(quot;org.apache.tomcat.comet.timeoutquot;,
       TIMEOUT);
       log(quot;Begin for
       session: quot; +
       request.getSession(true).getId());
       messageSender.setConnection(response);
       Weatherman
       weatherman = new
       Weatherman(95118,
       32408);
                   new
       Thread(weatherman).start();
               } else if
       (event.getEventType()
       ==
       CometEvent.EventType.ERROR)
       {
       log(quot;Error for
       session: quot; +
       request.getSession(true).getId());
       event.close();
               } else if
       (event.getEventType()
       ==
       CometEvent.EventType.END)
       {
       log(quot;End for
       session: quot; +
       request.getSession(true).getId());
       event.close();
               } else if
       (event.getEventType()
       ==
       CometEvent.EventType.READ)
       {
                   throw
       new
       UnsupportedOperationException(quot;This
       servlet does not
       accept
       dataquot;);
               }
            }
       }


     The CometProcessor interface requires you to implement the event method. This
     is a lifecycle method for a Comet interaction. Tomcat will invoke with different
     CometEvent instances. We check the eventType of the CometEvent to
     determine where in the lifecycle we are. A BEGIN event happens when the request
     first comes in. A READ event indicates data being sent in, and is only needed if the
     request was a POST. The request can terminate in either an END or ERROR event.

     In the example in Listing 2, the servlet uses a class called MessageSender to send


Developing with Comet and Java
Page 6 of 19                                           © Copyright IBM Corporation 2009. All rights reserved.
ibm.com/developerWorks                                                             developerWorks®



      in data. This is set up in its own thread during the init method of the servlet and
      taken down in the destroy method of the servlet. The MessageSender is shown in
      Listing 3.

      Listing 3. The MessageSender

       private class
       MessageSender
       implements
       Runnable {
           protected
       boolean running =
       true;
           protected
       final
       ArrayList<String>
       messages = new
       ArrayList<String>();
           private
       ServletResponse
       connection;
           private
       synchronized void
       setConnection(ServletResponse
       connection){
       this.connection =
       connection;
               notify();
           }
           public void
       send(String
       message) {
       synchronized
       (messages) {
       messages.add(message);
       log(quot;Message
       added #messages=quot;
       +
       messages.size());
       messages.notify();
               }
           }
           public void
       run() {
               while
       (running) {
                   if
       (messages.size()
       == 0) {
       try {
       synchronized
       (messages) {
       messages.wait();
       }
                       }
       catch
       (InterruptedException
       e) {
       // Ignore
                       }
                   }
       String[]
       pendingMessages =
       null;



Developing with Comet and Java
© Copyright IBM Corporation 2009. All rights reserved.                                  Page 7 of 19
developerWorks®                                                                    ibm.com/developerWorks




       synchronized
       (messages) {
       pendingMessages =
       messages.toArray(new
       String[0]);
       messages.clear();
                   }
                   try {
       if (connection ==
       null){
       try{
       synchronized(this){
       wait();
       }
       } catch
       (InterruptedException
       e){
       // Ignore
       }
                       }
       PrintWriter
       writer =
       connection.getWriter();
       for (int j = 0; j
       <
       pendingMessages.length;
       j++) {
       final String
       forecast =
       pendingMessages[j]
       + quot;<br>quot;;
       writer.println(forecast);
       log(quot;Writing:quot; +
       forecast);
                       }
       writer.flush();
       writer.close();
       connection =
       null;
       log(quot;Closing
       connectionquot;);
                   }
       catch
       (IOException e) {
       log(quot;IOExeption
       sending messagequot;,
       e);
                   }
               }
           }
       }


     This class is mostly boilerplate code, not directly relevant to Comet. There are a
     couple of things to notice, though. The class takes a ServletResponse object. If
     you look back at Listing 2 in the event method, when the event is a BEGIN, the
     response object is passed in to the MessageSender. In the MessageSender's run
     method, it uses the ServletResponse to send data back to the client. Notice that
     once it has sent all of the queued up messages, it closes the connection. Thus this
     implements a long poll. If you wanted to implement a streaming style of Comet, you
     would want to keep the connection open, but still flush the data.

     If you look back at Listing 2, you will see that there is a Weatherman class being


Developing with Comet and Java
Page 8 of 19                                            © Copyright IBM Corporation 2009. All rights reserved.
ibm.com/developerWorks                                                              developerWorks®



      created. This class is what uses the MessageSender to send data back to the
      client. It is a class that uses a Yahoo RSS feed to get weather information about
      various zip codes and sends this to the client. This is a contrived example designed
      to simulate a data source that sends data in an asynchronous manner. Its code is
      shown in Listing 4.

      Listing 4. The Weatherman

       private class
       Weatherman
       implements
       Runnable{
           private final
       List<URL>
       zipCodes;
           private final
       String
       YAHOO_WEATHER =
       quot;http://weather.yahooapis.com/forecastrss?p=quot;;
           public
       Weatherman(Integer...
       zips) {
               zipCodes
       = new
       ArrayList<URL>(zips.length);
               for
       (Integer zip :
       zips) {
                   try {
       zipCodes.add(new
       URL(YAHOO_WEATHER
       + zip));
                   }
       catch (Exception
       e) {
       // dont add it if
       it sucks
                   }
               }
           }
          public void
       run() {
              int i = 0;
              while (i
       >= 0) {
                  int j
       = i %
       zipCodes.size();
       SyndFeedInput
       input = new
       SyndFeedInput();
                  try {
       SyndFeed feed =
       input.build(new
       InputStreamReader(zipCodes.get(j)
       .openStream()));
       SyndEntry entry =
       (SyndEntry)
       feed.getEntries().get(0);
       messageSender.send(entryToHtml(entry));
       Thread.sleep(30000L);



Developing with Comet and Java
© Copyright IBM Corporation 2009. All rights reserved.                                  Page 9 of 19
developerWorks®                                                                       ibm.com/developerWorks




                  }
       catch (Exception
       e) {
                      //
       just eat it, eat
       it
                  }
                  i++;
              }
          }
           private
       String
       entryToHtml(SyndEntry
       entry){
       StringBuilder
       html = new
       StringBuilder(quot;<h2>quot;);
       html.append(entry.getTitle());
       html.append(quot;</h2>quot;);
       html.append(entry.getDescription().getValue());
               return
       html.toString();
           }
       }


     This class uses the Project Rome library for parsing the RSS feed from Yahoo
     Weather. If you need to produce or consume RSS or Atom feeds, this is a very
     useful library. The only other point of interest in this code is that it spawns another
     thread that sends in weather data every 30 seconds. Finally, we have one last thing
     to look at: the client code for using this servlet. In this case a simple JSP with a small
     amount of JavaScript is sufficient. This is shown in Listing 5.

     Listing 5. Client Comet code

       <%@page
       contentType=quot;text/htmlquot;
       pageEncoding=quot;UTF-8quot;%>
       <!DOCTYPE HTML
       PUBLIC
       quot;-//W3C//DTD HTML
       4.01
       Transitional//ENquot;
       quot;http://www.w3.org/TR/html4/loose.dtdquot;>
       <html>
           <head>
               <meta
       http-equiv=quot;Content-Typequot;
       content=quot;text/html;
       charset=UTF-8quot;>
       <title>Comet
       Weather</title>
               <SCRIPT
       TYPE=quot;text/javascriptquot;>
       function go(){
       var url =
       quot;http://localhost:8484/WeatherServer/Weatherquot;
       var request =
       new
       XMLHttpRequest();
       request.open(quot;GETquot;,



Developing with Comet and Java
Page 10 of 19                                              © Copyright IBM Corporation 2009. All rights reserved.
ibm.com/developerWorks                                                                 developerWorks®




       url, true);
       request.setRequestHeader(quot;Content-Typequot;,quot;application/x-javascript;quot;);
       request.onreadystatechange
       = function() {
       if
       (request.readyState
       == 4) {
       if
       (request.status
       == 200){
       if
       (request.responseText)
       {
       document.getElementById(quot;forecastsquot;).innerHTML
       =
       request.responseText;
       }
       }
       go();
       }
       };
       request.send(null);
                    }
               </SCRIPT>
           </head>
           <body>
               <h1>Rapid
       Fire Weather</h1>
               <input
       type=quot;buttonquot;
       onclick=quot;go()quot;
       value=quot;Go!quot;></input>
               <div
       id=quot;forecastsquot;></div>
           </body>
       </html>


      This code simply starts the long poll when the user clicks the Go button. Notice that
      it uses the XMLHttpRequest object directly, so this will not work in Internet
      Explorer 6. You probably want to use an Ajax library to smooth over the browser
      differences. The only other important thing to note is the callback function, or, the
      closure created for the request's onreadystatechange function. This function
      pastes in the new data from the server and then re-invokes the go function.

      Now we have seen what a simple Comet application looks like on Tomcat. There
      were two very Tomcat-centric things we had to do: configure its connector and
      implement a Tomcat specific interface in the servlet. So you may be wondering just
      how difficult it would be to quot;portquot; this code to Jetty. Let's take a look at that next.

      Jetty and Comet

      The Jetty server uses a slightly different technique to enable a scalable
      implementation of Comet. Jetty supports the programming construct known as
      continuations. The idea is simple enough. A request is suspended and continued at
      some point in the future. The resumption could happen either because of a timeout
      or some other, meaningful event. While the request is suspended, its thread is freed
      up.



Developing with Comet and Java
© Copyright IBM Corporation 2009. All rights reserved.                                    Page 11 of 19
developerWorks®                                                                   ibm.com/developerWorks



     You can use Jetty's org.mortbay.util.ajax.ContinuationSupport class to
     create an instance of org.mortbay.util.ajax.Continuation for any
     HttpServletRequest. This allows for a very different approach to Comet.
     However, continuations can be used to implement a logically identical style of
     Comet. Listing 6 shows the weather servlet from Listing 2 after it has been quot;portedquot;
     to Jetty.

     Listing 6. Jetty Comet servlet

       public class
       JettyWeatherServlet
       extends
       HttpServlet {
           private
       MessageSender
       messageSender =
       null;
           private
       static final
       Integer TIMEOUT =
       5 * 1000;
           public void
       begin(HttpServletRequest
       request,
       HttpServletResponse
       response)
       throws
       IOException,
       ServletException
       {
       request.setAttribute(quot;org.apache.tomcat.cometquot;,
       Boolean.TRUE);
       request.setAttribute(quot;org.apache.tomcat.comet.timeoutquot;,
       TIMEOUT);
       messageSender.setConnection(response);
       Weatherman
       weatherman = new
       Weatherman(95118,
       32408);
               new
       Thread(weatherman).start();
           }
           public void
       end(HttpServletRequest
       request,
       HttpServletResponse
       response)
       throws
       IOException,
       ServletException
       {
       synchronized
       (request) {
       request.removeAttribute(quot;org.apache.tomcat.cometquot;);
       Continuation
       continuation =
       ContinuationSupport.getContinuation
       (request,
       request);
                   if
       (continuation.isPending())
       {
       continuation.resume();
                   }


Developing with Comet and Java
Page 12 of 19                                          © Copyright IBM Corporation 2009. All rights reserved.
ibm.com/developerWorks                                   developerWorks®




               }
           }
           public void
       error(HttpServletRequest
       request,
       HttpServletResponse
       response)
       throws
       IOException,
       ServletException
       {
       end(request,
       response);
           }
           public
       boolean
       read(HttpServletRequest
       request,
       HttpServletResponse
       response)
       throws
       IOException,
       ServletException
       {
               throw new
       UnsupportedOperationException();
           }
           @Override
           protected
       void
       service(HttpServletRequest
       request,
       HttpServletResponse
       response)
       throws
       IOException,
       ServletException
       {
       synchronized
       (request) {
       Continuation
       continuation =
       ContinuationSupport.getContinuation
       (request,
       request);
                   if
       (!continuation.isPending())
       {
       begin(request,
       response);
                   }
       Integer timeout =
       (Integer)
       request.getAttribute
       (quot;org.apache.tomcat.comet.timeoutquot;);
       boolean resumed =
       continuation.suspend(timeout
       == null ? 10000 :
       timeout.intValue());
                   if
       (!resumed) {
       error(request,
       response);
                   }
               }
           }
           public void
       setTimeout(HttpServletRequest


Developing with Comet and Java
© Copyright IBM Corporation 2009. All rights reserved.      Page 13 of 19
developerWorks®                                                                       ibm.com/developerWorks




       request,
       HttpServletResponse
       response,
       int timeout)
       throws
       IOException,
       ServletException,
       UnsupportedOperationException
       {
       request.setAttribute(quot;org.apache.tomcat.comet.timeoutquot;,
       new
       Integer(timeout));
           }
       }


     The most important thing to notice here is how the structure mimics the Tomcat
     version of the code. The begin, read, end, and error methods match up to the
     same events in Tomcat. The servlet's service method is overridden to create a
     continuation when the request first comes in and suspends it until either the timeout
     is hit or another event causes it to resume. The init and destroy methods are not
     shown above because they are identical to the Tomcat version. This servlet uses the
     same MessageSender as the Tomcat version. No modification is needed. Notice
     how the begin method creates a Weatherman instance. That class is also used
     exactly as in the Tomcat version. Even the client code is identical. Only the servlet is
     changed at all. Its changes are significant, but with a straightforward mapping back
     to the event model in Tomcat.

     I hope this is encouraging. The exact same code does not work in both Tomcat and
     Jetty, but it is very similar. Of course one of the appeals of JavaEE is portability.
     Most code that runs in Tomcat will run in Jetty with no modification and vice versa.
     Thus it should come as no surprise that the next version of the Java Servlet
     specification includes a standardization of asynchronous request processing, or, the
     underlying technology behind Comet. Let's take a look at that spec, the Servlet 3.0
     spec.


     Servlet 3.0 spec
     We could dive into all of the gnarly details of the Servlet 3.0 specification. Instead
     let's just take a look at what the Comet servlet might look like if it was running inside
     a Servlet 3.0 container. Notice the word quot;might.quot; The specification has been
     released for public review, but has not been finalized as of the time of this writing.
     Thus Listing 7 shows an implementation compliant with the public review
     specification.

     Listing 7. Servlet 3.0 Comet

       @WebServlet(asyncSupported=true,
       asyncTimeout=5000)
       public class



Developing with Comet and Java
Page 14 of 19                                              © Copyright IBM Corporation 2009. All rights reserved.
ibm.com/developerWorks                                                                  developerWorks®




       WeatherServlet
       extends
       HttpServlet {
          private
       MessageSender
       messageSender;
       // init and
       destroy are the
       same as other
           @Override
           protected
       void
       doGet(HttpServletRequest
       request,
       HttpServletResponse
       response)
           throws
       ServletException,
       IOException {
       AsyncContext
       async =
       request.startAsync(request,
       response);
       messageSender.setConnection(async);
       Weatherman
       weatherman = new
       Weatherman(95118,
       32444);
       async.start(weatherman);;
           }
       }


      The nice thing here is that this is much simpler. In all fairness, a similar
      implementation is possible with Jetty, if we had not tried to adhere to the event
      model of Tomcat. The event model may have seemed sensible and could be easily
      implemented in containers other than Tomcat, like Jetty, but there will be no
      standardization around it.

      Looking back at Listing 7, notice that its annotation declares that it supports
      asynchronous processing and sets the timeout. The startAsync method is a new
      method on HttpServletRequest, and it returns an instance of the new class
      javax.servlet.AsyncContext. Notice that the MessageSender is being
      passed a reference to the AsynContext instead of the ServletResponse.
      Instead of closing the response, you should call the complete method on the
      AsyncContext instance. Also notice that the Weatherman was passed directly to
      the start method of the AsyncContext instance. This starts a new thread in the
      current ServletContext.

      So, despite being significantly different than either Tomcat or Jetty, it is not too hard
      to adapt the same style of programming to work with the proposed APIs of the
      Servlet 3.0 specification. It should be noted that Jetty 7 is intended to implement
      Servlet 3.0 and is available in a beta form. However, as of the time of writing, it did
      not implement the latest version of the specification as shown above.




Developing with Comet and Java
© Copyright IBM Corporation 2009. All rights reserved.                                      Page 15 of 19
developerWorks®                                                                    ibm.com/developerWorks




     Summary
     Comet-style Web applications can bring a whole new level of interactivity to the
     Web. It presents some complex challenges for implementing these features on a
     large scale. However, the leading Java Web servers are all providing mature, stable
     technology for implementing Comet. You have seen in this article the differences
     and similarities of the current flavors of Comet on Tomcat and Jetty, as well as the
     ongoing standardization effort for the Servlet 3.0 specification. Tomcat and Jetty
     make it possible to build scalable Comet applications today, with a clear upgrade
     path to standardization under Servlet 3.0 in the future.




Developing with Comet and Java
Page 16 of 19                                           © Copyright IBM Corporation 2009. All rights reserved.
ibm.com/developerWorks                                                           developerWorks®




      Downloads
       Description                                 Name                Size    Download
                                                                               method
      Weather Server Source Code                   WeatherServer.zip   347KB   HTTP

       Information about download methods




Developing with Comet and Java
© Copyright IBM Corporation 2009. All rights reserved.                                Page 17 of 19
developerWorks®                                                                      ibm.com/developerWorks




     Resources
     Learn
        • quot;The allure of Cometquot; (Erik Burkhart, developerWorks, November 2007): Find
          out more about the history and motivations behind Comet.
        • quot;High-performance Ajax with Tomcat Advanced I/Oquot; (Adriaan de Jonge,
          developerWorks, September 2008): Learn even more about Comet on Tomcat.
        • quot;Ajax for Java Developers: Write Scalable Comet applications with Jetty and
          Direct Web Remotingquot; (Philip McCarthy, developerWorks, July 2007): Direct
          Web Remoting (DWR) can make Ajax a lot easier for Java developers, and it
          can do the same for Comet. Find out how in the developerWorks article.
        • quot;Java EE meets Web 2.0quot; (Constantine Plotnikov et al., developerWorks,
          November 2007): Dive into the performance implications of Comet.
        • quot;Developing Rich Internet Applications with WebSphere Application Server
          Community Editionquot; (Manu George and Vamsavardhana Reddy Chillakuru,
          developerWorks, September 2008): Read about how Comet works equally well
          in a full Java EE stack.
        • Asynchronous HTTP Comet architectures: Check out Asynchronous HTTP
          Comet architectures for even more information on Comet in Java.
        • An Introduction to Servlet 3.0: Read about all of the new features of Servlet 3.0.
        • Check out the reference information about Tomcat's Advanced IO and
          Continuations in Jetty.
        • quot;Creating mashups on the Google App Enginequot; (Michael Galpin,
          developerWorks, August 2008): See how you can use Python and the Prototype
          JavaScript library to create a Comet application that can be deployed to the
          Google App Engine.
        • Web development zone: See the developerWorks Web development zone for a
          wide range of technical articles and tips, tutorials, and standards.
        • developerWorks podcasts: Listen to interesting interviews and discussions for
          software developers.
        • developerWorks technical events and webcasts: Stay current with
          developerWorks technical events and webcasts.
     Get products and technologies
        • JDK 1.5.0-16 was used in this article.
        • Jetty: Jetty 6.1.14 was used in this article.
        • Tomcat: Tomcat 6.0.14 was used in this article.


Developing with Comet and Java
Page 18 of 19                                             © Copyright IBM Corporation 2009. All rights reserved.
ibm.com/developerWorks                                                             developerWorks®



         • Innovate your next open source development project with IBM trial software,
           available for download or on DVD.
         • Download IBM product evaluation versions, and get your hands on application
           development tools and middleware products from DB2, Lotus, Rational, Tivoli,
           and WebSphere.
      Discuss
         • Participate in the developerWorks community.



      About the author
      Michael Galpin
      Michael Galpin has been developing Web applications since the late 90's. He holds a
      degree in mathematics from the California Institute of Technology and is an architect
      at eBay in San Jose, CA.




Developing with Comet and Java
© Copyright IBM Corporation 2009. All rights reserved.                                   Page 19 of 19

More Related Content

What's hot

ServiceMix 4 -- Integrating OSGi with JBI
ServiceMix 4 -- Integrating OSGi with JBIServiceMix 4 -- Integrating OSGi with JBI
ServiceMix 4 -- Integrating OSGi with JBIGert Vanthienen
 
An Introduction to Apache ServiceMix 4 - FUSE ESB
An Introduction to Apache ServiceMix 4 - FUSE ESBAn Introduction to Apache ServiceMix 4 - FUSE ESB
An Introduction to Apache ServiceMix 4 - FUSE ESBAdrian Trenaman
 
The Case for HTTP/2
The Case for HTTP/2The Case for HTTP/2
The Case for HTTP/2Andy Davies
 
Introduction to WebSockets
Introduction to WebSocketsIntroduction to WebSockets
Introduction to WebSocketsGunnar Hillert
 
vlavrynovych - WebSockets Presentation
vlavrynovych - WebSockets Presentationvlavrynovych - WebSockets Presentation
vlavrynovych - WebSockets PresentationVolodymyr Lavrynovych
 
Alex carcea, radu macovei a story of how java script joined the big league
Alex carcea, radu macovei   a story of how java script joined the big leagueAlex carcea, radu macovei   a story of how java script joined the big league
Alex carcea, radu macovei a story of how java script joined the big leagueCodecamp Romania
 
WebSockets On Fire
WebSockets On FireWebSockets On Fire
WebSockets On FireJef Claes
 
Performance in business terms
Performance in business termsPerformance in business terms
Performance in business termsStrangeloop
 
Succeding with the Apache SOA stack
Succeding with the Apache SOA stackSucceding with the Apache SOA stack
Succeding with the Apache SOA stackJohan Edstrom
 
Service Oriented Integration With ServiceMix
Service Oriented Integration With ServiceMixService Oriented Integration With ServiceMix
Service Oriented Integration With ServiceMixBruce Snyder
 
Altitude San Francisco 2018: Programming the Edge
Altitude San Francisco 2018: Programming the EdgeAltitude San Francisco 2018: Programming the Edge
Altitude San Francisco 2018: Programming the EdgeFastly
 
Web Performance Automation - NY Web Performance Meetup
Web Performance Automation - NY Web Performance MeetupWeb Performance Automation - NY Web Performance Meetup
Web Performance Automation - NY Web Performance MeetupStrangeloop
 
Implementing WebServices with Camel and CXF in ServiceMix
Implementing WebServices with Camel and CXF in ServiceMixImplementing WebServices with Camel and CXF in ServiceMix
Implementing WebServices with Camel and CXF in ServiceMixAdrian Trenaman
 
Web Performance Hacks
Web Performance HacksWeb Performance Hacks
Web Performance HacksSagar Desarda
 
Async event based web server
Async event based web serverAsync event based web server
Async event based web serverGi Woong Lee
 
HTML5 WebSocket Introduction
HTML5 WebSocket IntroductionHTML5 WebSocket Introduction
HTML5 WebSocket IntroductionMarcelo Jabali
 
Implementing Advanced Caching and Replication Techniques in ...
Implementing Advanced Caching and Replication Techniques in ...Implementing Advanced Caching and Replication Techniques in ...
Implementing Advanced Caching and Replication Techniques in ...webhostingguy
 
HTML5 Real Time and WebSocket Code Lab (SFHTML5, GTUGSF)
HTML5 Real Time and WebSocket Code Lab (SFHTML5, GTUGSF)HTML5 Real Time and WebSocket Code Lab (SFHTML5, GTUGSF)
HTML5 Real Time and WebSocket Code Lab (SFHTML5, GTUGSF)Peter Lubbers
 
Webinar slides "Building Real-Time Collaborative Web Applications"
Webinar slides "Building Real-Time Collaborative Web Applications"Webinar slides "Building Real-Time Collaborative Web Applications"
Webinar slides "Building Real-Time Collaborative Web Applications"Sachin Katariya
 

What's hot (20)

ServiceMix 4 -- Integrating OSGi with JBI
ServiceMix 4 -- Integrating OSGi with JBIServiceMix 4 -- Integrating OSGi with JBI
ServiceMix 4 -- Integrating OSGi with JBI
 
An Introduction to Apache ServiceMix 4 - FUSE ESB
An Introduction to Apache ServiceMix 4 - FUSE ESBAn Introduction to Apache ServiceMix 4 - FUSE ESB
An Introduction to Apache ServiceMix 4 - FUSE ESB
 
The Case for HTTP/2
The Case for HTTP/2The Case for HTTP/2
The Case for HTTP/2
 
Introduction to WebSockets
Introduction to WebSocketsIntroduction to WebSockets
Introduction to WebSockets
 
vlavrynovych - WebSockets Presentation
vlavrynovych - WebSockets Presentationvlavrynovych - WebSockets Presentation
vlavrynovych - WebSockets Presentation
 
Alex carcea, radu macovei a story of how java script joined the big league
Alex carcea, radu macovei   a story of how java script joined the big leagueAlex carcea, radu macovei   a story of how java script joined the big league
Alex carcea, radu macovei a story of how java script joined the big league
 
CMIS REST HTTP
CMIS REST HTTPCMIS REST HTTP
CMIS REST HTTP
 
WebSockets On Fire
WebSockets On FireWebSockets On Fire
WebSockets On Fire
 
Performance in business terms
Performance in business termsPerformance in business terms
Performance in business terms
 
Succeding with the Apache SOA stack
Succeding with the Apache SOA stackSucceding with the Apache SOA stack
Succeding with the Apache SOA stack
 
Service Oriented Integration With ServiceMix
Service Oriented Integration With ServiceMixService Oriented Integration With ServiceMix
Service Oriented Integration With ServiceMix
 
Altitude San Francisco 2018: Programming the Edge
Altitude San Francisco 2018: Programming the EdgeAltitude San Francisco 2018: Programming the Edge
Altitude San Francisco 2018: Programming the Edge
 
Web Performance Automation - NY Web Performance Meetup
Web Performance Automation - NY Web Performance MeetupWeb Performance Automation - NY Web Performance Meetup
Web Performance Automation - NY Web Performance Meetup
 
Implementing WebServices with Camel and CXF in ServiceMix
Implementing WebServices with Camel and CXF in ServiceMixImplementing WebServices with Camel and CXF in ServiceMix
Implementing WebServices with Camel and CXF in ServiceMix
 
Web Performance Hacks
Web Performance HacksWeb Performance Hacks
Web Performance Hacks
 
Async event based web server
Async event based web serverAsync event based web server
Async event based web server
 
HTML5 WebSocket Introduction
HTML5 WebSocket IntroductionHTML5 WebSocket Introduction
HTML5 WebSocket Introduction
 
Implementing Advanced Caching and Replication Techniques in ...
Implementing Advanced Caching and Replication Techniques in ...Implementing Advanced Caching and Replication Techniques in ...
Implementing Advanced Caching and Replication Techniques in ...
 
HTML5 Real Time and WebSocket Code Lab (SFHTML5, GTUGSF)
HTML5 Real Time and WebSocket Code Lab (SFHTML5, GTUGSF)HTML5 Real Time and WebSocket Code Lab (SFHTML5, GTUGSF)
HTML5 Real Time and WebSocket Code Lab (SFHTML5, GTUGSF)
 
Webinar slides "Building Real-Time Collaborative Web Applications"
Webinar slides "Building Real-Time Collaborative Web Applications"Webinar slides "Building Real-Time Collaborative Web Applications"
Webinar slides "Building Real-Time Collaborative Web Applications"
 

Viewers also liked

Hadoop 調査報告書
Hadoop 調査報告書Hadoop 調査報告書
Hadoop 調査報告書Hiroshi Ono
 
Webマイニングと情報論的学習理論
Webマイニングと情報論的学習理論Webマイニングと情報論的学習理論
Webマイニングと情報論的学習理論Hiroshi Ono
 
私がチャレンジしたSBMデータマイニング
私がチャレンジしたSBMデータマイニング私がチャレンジしたSBMデータマイニング
私がチャレンジしたSBMデータマイニングHiroshi Ono
 
Gamecenter概説
Gamecenter概説Gamecenter概説
Gamecenter概説Hiroshi Ono
 

Viewers also liked (8)

Hadoop 調査報告書
Hadoop 調査報告書Hadoop 調査報告書
Hadoop 調査報告書
 
p723-zukowski
p723-zukowskip723-zukowski
p723-zukowski
 
PythonTribe
PythonTribePythonTribe
PythonTribe
 
fj
fjfj
fj
 
future-search
future-searchfuture-search
future-search
 
Webマイニングと情報論的学習理論
Webマイニングと情報論的学習理論Webマイニングと情報論的学習理論
Webマイニングと情報論的学習理論
 
私がチャレンジしたSBMデータマイニング
私がチャレンジしたSBMデータマイニング私がチャレンジしたSBMデータマイニング
私がチャレンジしたSBMデータマイニング
 
Gamecenter概説
Gamecenter概説Gamecenter概説
Gamecenter概説
 

Similar to wa-cometjava-pdf

Comet / WebSocket Web Applications
Comet / WebSocket Web ApplicationsComet / WebSocket Web Applications
Comet / WebSocket Web ApplicationsCodemotion
 
Reverse ajax in 2014
Reverse ajax in 2014Reverse ajax in 2014
Reverse ajax in 2014Nenad Pecanac
 
Taking a Quantum Leap with Html 5 WebSocket
Taking a Quantum Leap with Html 5 WebSocketTaking a Quantum Leap with Html 5 WebSocket
Taking a Quantum Leap with Html 5 WebSocketShahriar Hyder
 
Real-Time with Flowdock
Real-Time with FlowdockReal-Time with Flowdock
Real-Time with FlowdockFlowdock
 
Presentation on java servlets
Presentation on java servletsPresentation on java servlets
Presentation on java servletsAamir Sohail
 
Programming Server side with Sevlet
 Programming Server side with Sevlet  Programming Server side with Sevlet
Programming Server side with Sevlet backdoor
 
Ajp notes-chapter-06
Ajp notes-chapter-06Ajp notes-chapter-06
Ajp notes-chapter-06Ankit Dubey
 
Unit 1st and 3rd notes of java
Unit 1st and 3rd notes of javaUnit 1st and 3rd notes of java
Unit 1st and 3rd notes of javaNiraj Bharambe
 
How do I - Networking and Webservices - Transcript.pdf
How do I - Networking and Webservices - Transcript.pdfHow do I - Networking and Webservices - Transcript.pdf
How do I - Networking and Webservices - Transcript.pdfShaiAlmog1
 
Building Next Generation Real-Time Web Applications using Websockets
Building Next Generation Real-Time Web Applications using WebsocketsBuilding Next Generation Real-Time Web Applications using Websockets
Building Next Generation Real-Time Web Applications using WebsocketsNaresh Chintalcheru
 
Building and Scaling a WebSockets Pubsub System
Building and Scaling a WebSockets Pubsub SystemBuilding and Scaling a WebSockets Pubsub System
Building and Scaling a WebSockets Pubsub SystemKapil Reddy
 
UNIT-3 Servlet
UNIT-3 ServletUNIT-3 Servlet
UNIT-3 Servletssbd6985
 
WebSocket Perspectives and Vision for the Future
WebSocket Perspectives and Vision for the FutureWebSocket Perspectives and Vision for the Future
WebSocket Perspectives and Vision for the FutureFrank Greco
 

Similar to wa-cometjava-pdf (20)

Comet / WebSocket Web Applications
Comet / WebSocket Web ApplicationsComet / WebSocket Web Applications
Comet / WebSocket Web Applications
 
Reverse ajax in 2014
Reverse ajax in 2014Reverse ajax in 2014
Reverse ajax in 2014
 
Taking a Quantum Leap with Html 5 WebSocket
Taking a Quantum Leap with Html 5 WebSocketTaking a Quantum Leap with Html 5 WebSocket
Taking a Quantum Leap with Html 5 WebSocket
 
Real-Time with Flowdock
Real-Time with FlowdockReal-Time with Flowdock
Real-Time with Flowdock
 
Presentation on java servlets
Presentation on java servletsPresentation on java servlets
Presentation on java servlets
 
Programming Server side with Sevlet
 Programming Server side with Sevlet  Programming Server side with Sevlet
Programming Server side with Sevlet
 
Ajp notes-chapter-06
Ajp notes-chapter-06Ajp notes-chapter-06
Ajp notes-chapter-06
 
Jetty Vs Tomcat
Jetty Vs TomcatJetty Vs Tomcat
Jetty Vs Tomcat
 
Unit 1st and 3rd notes of java
Unit 1st and 3rd notes of javaUnit 1st and 3rd notes of java
Unit 1st and 3rd notes of java
 
How do I - Networking and Webservices - Transcript.pdf
How do I - Networking and Webservices - Transcript.pdfHow do I - Networking and Webservices - Transcript.pdf
How do I - Networking and Webservices - Transcript.pdf
 
Building Next Generation Real-Time Web Applications using Websockets
Building Next Generation Real-Time Web Applications using WebsocketsBuilding Next Generation Real-Time Web Applications using Websockets
Building Next Generation Real-Time Web Applications using Websockets
 
Servlet.pptx
Servlet.pptxServlet.pptx
Servlet.pptx
 
Servlet.pptx
Servlet.pptxServlet.pptx
Servlet.pptx
 
Building and Scaling a WebSockets Pubsub System
Building and Scaling a WebSockets Pubsub SystemBuilding and Scaling a WebSockets Pubsub System
Building and Scaling a WebSockets Pubsub System
 
UNIT-3 Servlet
UNIT-3 ServletUNIT-3 Servlet
UNIT-3 Servlet
 
Web-Socket
Web-SocketWeb-Socket
Web-Socket
 
Servlets
ServletsServlets
Servlets
 
WebSocket Perspectives and Vision for the Future
WebSocket Perspectives and Vision for the FutureWebSocket Perspectives and Vision for the Future
WebSocket Perspectives and Vision for the Future
 
Ajax and PHP
Ajax and PHPAjax and PHP
Ajax and PHP
 
Servlet classnotes
Servlet classnotesServlet classnotes
Servlet classnotes
 

More from Hiroshi Ono

Voltdb - wikipedia
Voltdb - wikipediaVoltdb - wikipedia
Voltdb - wikipediaHiroshi Ono
 
EventDrivenArchitecture
EventDrivenArchitectureEventDrivenArchitecture
EventDrivenArchitectureHiroshi Ono
 
program_draft3.pdf
program_draft3.pdfprogram_draft3.pdf
program_draft3.pdfHiroshi Ono
 
nodalities_issue7.pdf
nodalities_issue7.pdfnodalities_issue7.pdf
nodalities_issue7.pdfHiroshi Ono
 
genpaxospublic-090703114743-phpapp01.pdf
genpaxospublic-090703114743-phpapp01.pdfgenpaxospublic-090703114743-phpapp01.pdf
genpaxospublic-090703114743-phpapp01.pdfHiroshi Ono
 
kademlia-1227143905867010-8.pdf
kademlia-1227143905867010-8.pdfkademlia-1227143905867010-8.pdf
kademlia-1227143905867010-8.pdfHiroshi Ono
 
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdfpragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdfHiroshi Ono
 
downey08semaphores.pdf
downey08semaphores.pdfdowney08semaphores.pdf
downey08semaphores.pdfHiroshi Ono
 
BOF1-Scala02.pdf
BOF1-Scala02.pdfBOF1-Scala02.pdf
BOF1-Scala02.pdfHiroshi Ono
 
TwitterOct2008.pdf
TwitterOct2008.pdfTwitterOct2008.pdf
TwitterOct2008.pdfHiroshi Ono
 
stateyouredoingitwrongjavaone2009-090617031310-phpapp02.pdf
stateyouredoingitwrongjavaone2009-090617031310-phpapp02.pdfstateyouredoingitwrongjavaone2009-090617031310-phpapp02.pdf
stateyouredoingitwrongjavaone2009-090617031310-phpapp02.pdfHiroshi Ono
 
SACSIS2009_TCP.pdf
SACSIS2009_TCP.pdfSACSIS2009_TCP.pdf
SACSIS2009_TCP.pdfHiroshi Ono
 
scalaliftoff2009.pdf
scalaliftoff2009.pdfscalaliftoff2009.pdf
scalaliftoff2009.pdfHiroshi Ono
 
stateyouredoingitwrongjavaone2009-090617031310-phpapp02.pdf
stateyouredoingitwrongjavaone2009-090617031310-phpapp02.pdfstateyouredoingitwrongjavaone2009-090617031310-phpapp02.pdf
stateyouredoingitwrongjavaone2009-090617031310-phpapp02.pdfHiroshi Ono
 
program_draft3.pdf
program_draft3.pdfprogram_draft3.pdf
program_draft3.pdfHiroshi Ono
 
nodalities_issue7.pdf
nodalities_issue7.pdfnodalities_issue7.pdf
nodalities_issue7.pdfHiroshi Ono
 
genpaxospublic-090703114743-phpapp01.pdf
genpaxospublic-090703114743-phpapp01.pdfgenpaxospublic-090703114743-phpapp01.pdf
genpaxospublic-090703114743-phpapp01.pdfHiroshi Ono
 
kademlia-1227143905867010-8.pdf
kademlia-1227143905867010-8.pdfkademlia-1227143905867010-8.pdf
kademlia-1227143905867010-8.pdfHiroshi Ono
 
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdfpragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdfHiroshi Ono
 

More from Hiroshi Ono (20)

Voltdb - wikipedia
Voltdb - wikipediaVoltdb - wikipedia
Voltdb - wikipedia
 
EventDrivenArchitecture
EventDrivenArchitectureEventDrivenArchitecture
EventDrivenArchitecture
 
program_draft3.pdf
program_draft3.pdfprogram_draft3.pdf
program_draft3.pdf
 
nodalities_issue7.pdf
nodalities_issue7.pdfnodalities_issue7.pdf
nodalities_issue7.pdf
 
genpaxospublic-090703114743-phpapp01.pdf
genpaxospublic-090703114743-phpapp01.pdfgenpaxospublic-090703114743-phpapp01.pdf
genpaxospublic-090703114743-phpapp01.pdf
 
kademlia-1227143905867010-8.pdf
kademlia-1227143905867010-8.pdfkademlia-1227143905867010-8.pdf
kademlia-1227143905867010-8.pdf
 
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdfpragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
 
downey08semaphores.pdf
downey08semaphores.pdfdowney08semaphores.pdf
downey08semaphores.pdf
 
BOF1-Scala02.pdf
BOF1-Scala02.pdfBOF1-Scala02.pdf
BOF1-Scala02.pdf
 
TwitterOct2008.pdf
TwitterOct2008.pdfTwitterOct2008.pdf
TwitterOct2008.pdf
 
camel-scala.pdf
camel-scala.pdfcamel-scala.pdf
camel-scala.pdf
 
stateyouredoingitwrongjavaone2009-090617031310-phpapp02.pdf
stateyouredoingitwrongjavaone2009-090617031310-phpapp02.pdfstateyouredoingitwrongjavaone2009-090617031310-phpapp02.pdf
stateyouredoingitwrongjavaone2009-090617031310-phpapp02.pdf
 
SACSIS2009_TCP.pdf
SACSIS2009_TCP.pdfSACSIS2009_TCP.pdf
SACSIS2009_TCP.pdf
 
scalaliftoff2009.pdf
scalaliftoff2009.pdfscalaliftoff2009.pdf
scalaliftoff2009.pdf
 
stateyouredoingitwrongjavaone2009-090617031310-phpapp02.pdf
stateyouredoingitwrongjavaone2009-090617031310-phpapp02.pdfstateyouredoingitwrongjavaone2009-090617031310-phpapp02.pdf
stateyouredoingitwrongjavaone2009-090617031310-phpapp02.pdf
 
program_draft3.pdf
program_draft3.pdfprogram_draft3.pdf
program_draft3.pdf
 
nodalities_issue7.pdf
nodalities_issue7.pdfnodalities_issue7.pdf
nodalities_issue7.pdf
 
genpaxospublic-090703114743-phpapp01.pdf
genpaxospublic-090703114743-phpapp01.pdfgenpaxospublic-090703114743-phpapp01.pdf
genpaxospublic-090703114743-phpapp01.pdf
 
kademlia-1227143905867010-8.pdf
kademlia-1227143905867010-8.pdfkademlia-1227143905867010-8.pdf
kademlia-1227143905867010-8.pdf
 
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdfpragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
 

Recently uploaded

Data governance with Unity Catalog Presentation
Data governance with Unity Catalog PresentationData governance with Unity Catalog Presentation
Data governance with Unity Catalog PresentationKnoldus Inc.
 
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024BookNet Canada
 
What is DBT - The Ultimate Data Build Tool.pdf
What is DBT - The Ultimate Data Build Tool.pdfWhat is DBT - The Ultimate Data Build Tool.pdf
What is DBT - The Ultimate Data Build Tool.pdfMounikaPolabathina
 
Sample pptx for embedding into website for demo
Sample pptx for embedding into website for demoSample pptx for embedding into website for demo
Sample pptx for embedding into website for demoHarshalMandlekar2
 
2024 April Patch Tuesday
2024 April Patch Tuesday2024 April Patch Tuesday
2024 April Patch TuesdayIvanti
 
Assure Ecommerce and Retail Operations Uptime with ThousandEyes
Assure Ecommerce and Retail Operations Uptime with ThousandEyesAssure Ecommerce and Retail Operations Uptime with ThousandEyes
Assure Ecommerce and Retail Operations Uptime with ThousandEyesThousandEyes
 
The Ultimate Guide to Choosing WordPress Pros and Cons
The Ultimate Guide to Choosing WordPress Pros and ConsThe Ultimate Guide to Choosing WordPress Pros and Cons
The Ultimate Guide to Choosing WordPress Pros and ConsPixlogix Infotech
 
Take control of your SAP testing with UiPath Test Suite
Take control of your SAP testing with UiPath Test SuiteTake control of your SAP testing with UiPath Test Suite
Take control of your SAP testing with UiPath Test SuiteDianaGray10
 
Generative Artificial Intelligence: How generative AI works.pdf
Generative Artificial Intelligence: How generative AI works.pdfGenerative Artificial Intelligence: How generative AI works.pdf
Generative Artificial Intelligence: How generative AI works.pdfIngrid Airi González
 
The State of Passkeys with FIDO Alliance.pptx
The State of Passkeys with FIDO Alliance.pptxThe State of Passkeys with FIDO Alliance.pptx
The State of Passkeys with FIDO Alliance.pptxLoriGlavin3
 
Digital Identity is Under Attack: FIDO Paris Seminar.pptx
Digital Identity is Under Attack: FIDO Paris Seminar.pptxDigital Identity is Under Attack: FIDO Paris Seminar.pptx
Digital Identity is Under Attack: FIDO Paris Seminar.pptxLoriGlavin3
 
[Webinar] SpiraTest - Setting New Standards in Quality Assurance
[Webinar] SpiraTest - Setting New Standards in Quality Assurance[Webinar] SpiraTest - Setting New Standards in Quality Assurance
[Webinar] SpiraTest - Setting New Standards in Quality AssuranceInflectra
 
Unleashing Real-time Insights with ClickHouse_ Navigating the Landscape in 20...
Unleashing Real-time Insights with ClickHouse_ Navigating the Landscape in 20...Unleashing Real-time Insights with ClickHouse_ Navigating the Landscape in 20...
Unleashing Real-time Insights with ClickHouse_ Navigating the Landscape in 20...Alkin Tezuysal
 
Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024BookNet Canada
 
Arizona Broadband Policy Past, Present, and Future Presentation 3/25/24
Arizona Broadband Policy Past, Present, and Future Presentation 3/25/24Arizona Broadband Policy Past, Present, and Future Presentation 3/25/24
Arizona Broadband Policy Past, Present, and Future Presentation 3/25/24Mark Goldstein
 
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptx
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptxThe Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptx
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptxLoriGlavin3
 
Use of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptx
Use of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptxUse of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptx
Use of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptxLoriGlavin3
 
TrustArc Webinar - How to Build Consumer Trust Through Data Privacy
TrustArc Webinar - How to Build Consumer Trust Through Data PrivacyTrustArc Webinar - How to Build Consumer Trust Through Data Privacy
TrustArc Webinar - How to Build Consumer Trust Through Data PrivacyTrustArc
 
Manual 508 Accessibility Compliance Audit
Manual 508 Accessibility Compliance AuditManual 508 Accessibility Compliance Audit
Manual 508 Accessibility Compliance AuditSkynet Technologies
 
A Framework for Development in the AI Age
A Framework for Development in the AI AgeA Framework for Development in the AI Age
A Framework for Development in the AI AgeCprime
 

Recently uploaded (20)

Data governance with Unity Catalog Presentation
Data governance with Unity Catalog PresentationData governance with Unity Catalog Presentation
Data governance with Unity Catalog Presentation
 
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
 
What is DBT - The Ultimate Data Build Tool.pdf
What is DBT - The Ultimate Data Build Tool.pdfWhat is DBT - The Ultimate Data Build Tool.pdf
What is DBT - The Ultimate Data Build Tool.pdf
 
Sample pptx for embedding into website for demo
Sample pptx for embedding into website for demoSample pptx for embedding into website for demo
Sample pptx for embedding into website for demo
 
2024 April Patch Tuesday
2024 April Patch Tuesday2024 April Patch Tuesday
2024 April Patch Tuesday
 
Assure Ecommerce and Retail Operations Uptime with ThousandEyes
Assure Ecommerce and Retail Operations Uptime with ThousandEyesAssure Ecommerce and Retail Operations Uptime with ThousandEyes
Assure Ecommerce and Retail Operations Uptime with ThousandEyes
 
The Ultimate Guide to Choosing WordPress Pros and Cons
The Ultimate Guide to Choosing WordPress Pros and ConsThe Ultimate Guide to Choosing WordPress Pros and Cons
The Ultimate Guide to Choosing WordPress Pros and Cons
 
Take control of your SAP testing with UiPath Test Suite
Take control of your SAP testing with UiPath Test SuiteTake control of your SAP testing with UiPath Test Suite
Take control of your SAP testing with UiPath Test Suite
 
Generative Artificial Intelligence: How generative AI works.pdf
Generative Artificial Intelligence: How generative AI works.pdfGenerative Artificial Intelligence: How generative AI works.pdf
Generative Artificial Intelligence: How generative AI works.pdf
 
The State of Passkeys with FIDO Alliance.pptx
The State of Passkeys with FIDO Alliance.pptxThe State of Passkeys with FIDO Alliance.pptx
The State of Passkeys with FIDO Alliance.pptx
 
Digital Identity is Under Attack: FIDO Paris Seminar.pptx
Digital Identity is Under Attack: FIDO Paris Seminar.pptxDigital Identity is Under Attack: FIDO Paris Seminar.pptx
Digital Identity is Under Attack: FIDO Paris Seminar.pptx
 
[Webinar] SpiraTest - Setting New Standards in Quality Assurance
[Webinar] SpiraTest - Setting New Standards in Quality Assurance[Webinar] SpiraTest - Setting New Standards in Quality Assurance
[Webinar] SpiraTest - Setting New Standards in Quality Assurance
 
Unleashing Real-time Insights with ClickHouse_ Navigating the Landscape in 20...
Unleashing Real-time Insights with ClickHouse_ Navigating the Landscape in 20...Unleashing Real-time Insights with ClickHouse_ Navigating the Landscape in 20...
Unleashing Real-time Insights with ClickHouse_ Navigating the Landscape in 20...
 
Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
 
Arizona Broadband Policy Past, Present, and Future Presentation 3/25/24
Arizona Broadband Policy Past, Present, and Future Presentation 3/25/24Arizona Broadband Policy Past, Present, and Future Presentation 3/25/24
Arizona Broadband Policy Past, Present, and Future Presentation 3/25/24
 
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptx
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptxThe Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptx
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptx
 
Use of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptx
Use of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptxUse of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptx
Use of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptx
 
TrustArc Webinar - How to Build Consumer Trust Through Data Privacy
TrustArc Webinar - How to Build Consumer Trust Through Data PrivacyTrustArc Webinar - How to Build Consumer Trust Through Data Privacy
TrustArc Webinar - How to Build Consumer Trust Through Data Privacy
 
Manual 508 Accessibility Compliance Audit
Manual 508 Accessibility Compliance AuditManual 508 Accessibility Compliance Audit
Manual 508 Accessibility Compliance Audit
 
A Framework for Development in the AI Age
A Framework for Development in the AI AgeA Framework for Development in the AI Age
A Framework for Development in the AI Age
 

wa-cometjava-pdf

  • 1. Developing with Comet and Java Implementing the Servlet 3.0 specification Skill Level: Intermediate Michael Galpin Software architect eBay 26 May 2009 Explore the different implementations of developing with Comet. See how popular Java™ Web servers like Jetty and Tomcat have enabled Comet applications, and learn how to program with each server. And finally, learn about the standardization proposals for Comet in Java that are part of the upcoming Servlet 3.0 and JavaEE 6 specifications. Getting started In this article I will show you how to build some simple Comet-style Web applications using a variety of Java technologies. Some light knowledge of Java servlets, Ajax, and JavaScript will be useful. We will look at the Comet-enabling features of both Tomcat and Jetty, so you will want the latest versions of each. Tomcat 6.0.14 and Jetty 6.1.14 were used in this article. You will also need a Java Development Kit supporting Java 5 or higher. JDK 1.5.0-16 was used in this article. You also might want to look at a pre-release version of Jetty 7, as it implements the Servlet 3.0 specification that we will examine in this article. See Resources for download links. Understanding Comet You may have heard of Comet, given its recent share of buzz. Comet is sometimes called reverse Ajax or server-side push. The idea is pretty simple: push data from the server to the browser without the browser requesting it. This sounds simple, but Developing with Comet and Java © Copyright IBM Corporation 2009. All rights reserved. Page 1 of 19
  • 2. developerWorks® ibm.com/developerWorks if you are familiar with Web applications, and in particular the HTTP protocol, then you know it is anything but simple. Implementing Comet-style Web applications in a way that scales on both the browser and the server is something that has only become generally feasible in recent years. Later in this article we will look at how some popular Java Web servers enable scalable Comet architectures, but first let's look at why you would create Comet applications and the general design patterns used to implement them. Motivations for using Comet It is hard to argue with the success of the HTTP protocol. It is the foundation of the bulk of the information exchange on the Internet. However, it has several limitations. In particular, it is a stateless, one-way protocol. A request is sent to a Web server, and that server turns around and issues a response—end of story. The request has to be initiated by the client, and the server can only send data in response to a request. This can make a number of types of Web applications a bit impractical to say the least. The classic example is a chat program. Other examples are sports scores, stock tickers, or e-mail programs. The limitations of HTTP are also responsible for some of its success. The request/response cycle lends itself to the classic one thread per connection model. As long as you can service the request quickly, this approach can scale massively. A huge number of requests per second can be handled, and a relatively low number of servers can handle a very large number of users. This is a perfect fit for many of the classic types of Web applications such as content management systems, search applications, and e-commerce sites, just to name a few. In each case, the server provides the data that the user requests and can then close the connection, allowing that thread to be freed up to serve other requests. If interaction was possible after the initial data was served, and the connection was kept open, then the thread could not be released and the server would not be able to serve many users. But what if you want to keep interacting with the user after the initial data is sent in response to a request? In the early days of the Web, this used to be accomplished using a meta refresh. This would automatically instruct the browser to reload the page after a specified number of seconds, thus enabling a crude form of polling. This is not only a bad user experience, but it is generally a terribly inefficient way of doing things. What if there is no new data to show on the page? The exact same page just gets re-rendered. What if the change to the page is very small, and most of the page does not change? Again, everything gets re-requested and re-drawn, if it needs to be or not. The advent and popularity of Ajax changed the above scenario. Now the server can be contacted asynchronously, thus the entire page does not have to be re-requested. An incremental update is now possible. All you need to do is poll the server using an XMLHttpRequest. This technique is commonly known as Comet. There are several variations on this technique, each with different performance and Developing with Comet and Java Page 2 of 19 © Copyright IBM Corporation 2009. All rights reserved.
  • 3. ibm.com/developerWorks developerWorks® scalability characteristics. Let's take a look at these different styles of Comet. Comet styles The viability of Ajax made Comet possible. The one-way nature of HTTP could be effectively worked around. As it turns out there are actually several different ways to pull this off. As you have probably guessed, the easiest way to enable Comet is to poll. You make a call to your server using XMLHttpRequest, and as soon as it comes back, wait a fixed amount of time (usually using JavaScript's setTimeout function), and then call it again. This is a very common technique. For example, this is how most webmail applications show you new e-mail messages when they arrive. There are some pros and cons to this technique. In this setup, you expect the response to come back quickly, like any other Ajax request. Having the pause in between requests like this is essential. Otherwise you would bombard your server with constant requests, and clearly that would not scale. This pause introduces a latency in your application. The longer your pause, the longer it takes for new data from the server to arrive on the client. If you shorten up the pause, then you run back into the risk of overwhelming your server. On the other hand, this is definitely the simplest way to implement Comet. Now, it should be pointed out that many people do not consider polling to be Comet. Instead they consider Comet to be the solutions to the limitations of polling. The most common quot;truequot; Comet technique is a variant of polling called long polling. The main difference between polling and long polling is how long it takes the server to respond. A long poll generally keeps the connection open for a long time—usually several seconds, but it could be a minute or longer. When an event happens on the server, the response is sent and closed, and the poll immediately begins anew. The advantage of a long poll over normal polling is that data goes from the server to the client as soon as it is available. The request may wait a long time with nothing to send back, but once there is something new, it is immediately sent to the client. There is no latency. If you have used a Web-based chat program, or anything that claims to be quot;real-timequot;, it probably used this technique. There is a variation of the long poll, a third flavor of Comet that is worth mentioning. This is usually referred to as streaming. In this flavor, the server pushes data back to the client, but does not close the connection. The connection stays open until it times out and causes the request to get re-initiated. The XMLHttpRequest specification states that you can check for a readyState of 3 or Receiving (as opposed to the usual readyState of 4 or Loaded) and get the data that is quot;streamingquot; from the server. This is similar to long polling in that there is no latency. When the data is ready on the server, it is sent to the client. It has an added advantage of making far fewer requests to the server, thus avoiding the overhead and latency associated with setting up the connection to the server. Unfortunately, there is great variance in the implementation of XMLHttpRequest across browsers. Developing with Comet and Java © Copyright IBM Corporation 2009. All rights reserved. Page 3 of 19
  • 4. developerWorks® ibm.com/developerWorks This technique only works reliably on the newer versions of Mozilla Firefox. For Internet Explorer or Safari, you need to stick to long polling. At this point you might be thinking that there is a major problem with both long polling and streaming. The request stays alive on the server for a long time. This breaks the one thread per request model, as the thread for a request never gets freed up. Even worse, this thread will be sitting idle until there is data to send back. This definitely will not scale. Luckily, modern Java Web servers have ways of addressing this. Comet on Java There have always been a lot of Web servers built with Java. One reason for this is that Java has a rich, native thread model. Thus it is relatively straightforward to implement the classic one thread per connection model. This model does not work so well for Comet, but fortunately Java once again has a solution. To handle Comet efficiently, you need non-blocking IO, and Java has this via its NIO library. Two of the most popular open source servers, Apache Tomcat and Jetty, have both leveraged NIO to add non-blocking IO and thus enable Comet. However, the implementations are quite different. Let's take a look at both Tomcat and Jetty's support for Comet. Tomcat and Comet For Apache Tomcat, there are two major things that you need to do to get Comet working. First, you need to make a small change in Tomcat's configuration file, server.xml. The more typical synchronous IO connector is enabled by default. You just need to switch this to the asynchronous version as shown in Listing 1. Listing 1. Modify Tomcat's server.xml <!-- This is the usual Connector, comment it out and add the NIO one --> <!-- Connector URIEncoding=quot;utf-8quot; connectionTimeout=quot;20000quot; port=quot;8084quot; protocol=quot;HTTP/1.1quot; redirectPort=quot;8443quot;/ --> <Connector connectionTimeout=quot;20000quot; port=quot;8080quot; protocol=quot;org.apache. coyote.http11.Http11NioProtocolquot; redirectPort=quot;8443quot;/> Developing with Comet and Java Page 4 of 19 © Copyright IBM Corporation 2009. All rights reserved.
  • 5. ibm.com/developerWorks developerWorks® This allows for Tomcat to handle many more simultaneous connections, with the caveat that most of those connections are going to be idle much of the time. The easiest way to take advantage of this is to create a servlet that implements the org.apache.catalina.CometProcessor interface. This is obviously an interface unique to Tomcat. An example of this is shown in Listing 2. Listing 2. Tomcat Comet servlet public class TomcatWeatherServlet extends HttpServlet implements CometProcessor { private MessageSender messageSender = null; private static final Integer TIMEOUT = 60 * 1000; @Override public void destroy() { messageSender.stop(); messageSender = null; } @Override public void init() throws ServletException { messageSender = new MessageSender(); Thread messageSenderThread = new Thread(messageSender, quot;MessageSender[quot; + getServletContext() .getContextPath() + quot;]quot;); messageSenderThread.setDaemon(true); messageSenderThread.start(); } public void event(final CometEvent event) throws IOException, ServletException { HttpServletRequest Developing with Comet and Java © Copyright IBM Corporation 2009. All rights reserved. Page 5 of 19
  • 6. developerWorks® ibm.com/developerWorks request = event.getHttpServletRequest(); HttpServletResponse response = event.getHttpServletResponse(); if (event.getEventType() == CometEvent.EventType.BEGIN) { request.setAttribute(quot;org.apache.tomcat.comet.timeoutquot;, TIMEOUT); log(quot;Begin for session: quot; + request.getSession(true).getId()); messageSender.setConnection(response); Weatherman weatherman = new Weatherman(95118, 32408); new Thread(weatherman).start(); } else if (event.getEventType() == CometEvent.EventType.ERROR) { log(quot;Error for session: quot; + request.getSession(true).getId()); event.close(); } else if (event.getEventType() == CometEvent.EventType.END) { log(quot;End for session: quot; + request.getSession(true).getId()); event.close(); } else if (event.getEventType() == CometEvent.EventType.READ) { throw new UnsupportedOperationException(quot;This servlet does not accept dataquot;); } } } The CometProcessor interface requires you to implement the event method. This is a lifecycle method for a Comet interaction. Tomcat will invoke with different CometEvent instances. We check the eventType of the CometEvent to determine where in the lifecycle we are. A BEGIN event happens when the request first comes in. A READ event indicates data being sent in, and is only needed if the request was a POST. The request can terminate in either an END or ERROR event. In the example in Listing 2, the servlet uses a class called MessageSender to send Developing with Comet and Java Page 6 of 19 © Copyright IBM Corporation 2009. All rights reserved.
  • 7. ibm.com/developerWorks developerWorks® in data. This is set up in its own thread during the init method of the servlet and taken down in the destroy method of the servlet. The MessageSender is shown in Listing 3. Listing 3. The MessageSender private class MessageSender implements Runnable { protected boolean running = true; protected final ArrayList<String> messages = new ArrayList<String>(); private ServletResponse connection; private synchronized void setConnection(ServletResponse connection){ this.connection = connection; notify(); } public void send(String message) { synchronized (messages) { messages.add(message); log(quot;Message added #messages=quot; + messages.size()); messages.notify(); } } public void run() { while (running) { if (messages.size() == 0) { try { synchronized (messages) { messages.wait(); } } catch (InterruptedException e) { // Ignore } } String[] pendingMessages = null; Developing with Comet and Java © Copyright IBM Corporation 2009. All rights reserved. Page 7 of 19
  • 8. developerWorks® ibm.com/developerWorks synchronized (messages) { pendingMessages = messages.toArray(new String[0]); messages.clear(); } try { if (connection == null){ try{ synchronized(this){ wait(); } } catch (InterruptedException e){ // Ignore } } PrintWriter writer = connection.getWriter(); for (int j = 0; j < pendingMessages.length; j++) { final String forecast = pendingMessages[j] + quot;<br>quot;; writer.println(forecast); log(quot;Writing:quot; + forecast); } writer.flush(); writer.close(); connection = null; log(quot;Closing connectionquot;); } catch (IOException e) { log(quot;IOExeption sending messagequot;, e); } } } } This class is mostly boilerplate code, not directly relevant to Comet. There are a couple of things to notice, though. The class takes a ServletResponse object. If you look back at Listing 2 in the event method, when the event is a BEGIN, the response object is passed in to the MessageSender. In the MessageSender's run method, it uses the ServletResponse to send data back to the client. Notice that once it has sent all of the queued up messages, it closes the connection. Thus this implements a long poll. If you wanted to implement a streaming style of Comet, you would want to keep the connection open, but still flush the data. If you look back at Listing 2, you will see that there is a Weatherman class being Developing with Comet and Java Page 8 of 19 © Copyright IBM Corporation 2009. All rights reserved.
  • 9. ibm.com/developerWorks developerWorks® created. This class is what uses the MessageSender to send data back to the client. It is a class that uses a Yahoo RSS feed to get weather information about various zip codes and sends this to the client. This is a contrived example designed to simulate a data source that sends data in an asynchronous manner. Its code is shown in Listing 4. Listing 4. The Weatherman private class Weatherman implements Runnable{ private final List<URL> zipCodes; private final String YAHOO_WEATHER = quot;http://weather.yahooapis.com/forecastrss?p=quot;; public Weatherman(Integer... zips) { zipCodes = new ArrayList<URL>(zips.length); for (Integer zip : zips) { try { zipCodes.add(new URL(YAHOO_WEATHER + zip)); } catch (Exception e) { // dont add it if it sucks } } } public void run() { int i = 0; while (i >= 0) { int j = i % zipCodes.size(); SyndFeedInput input = new SyndFeedInput(); try { SyndFeed feed = input.build(new InputStreamReader(zipCodes.get(j) .openStream())); SyndEntry entry = (SyndEntry) feed.getEntries().get(0); messageSender.send(entryToHtml(entry)); Thread.sleep(30000L); Developing with Comet and Java © Copyright IBM Corporation 2009. All rights reserved. Page 9 of 19
  • 10. developerWorks® ibm.com/developerWorks } catch (Exception e) { // just eat it, eat it } i++; } } private String entryToHtml(SyndEntry entry){ StringBuilder html = new StringBuilder(quot;<h2>quot;); html.append(entry.getTitle()); html.append(quot;</h2>quot;); html.append(entry.getDescription().getValue()); return html.toString(); } } This class uses the Project Rome library for parsing the RSS feed from Yahoo Weather. If you need to produce or consume RSS or Atom feeds, this is a very useful library. The only other point of interest in this code is that it spawns another thread that sends in weather data every 30 seconds. Finally, we have one last thing to look at: the client code for using this servlet. In this case a simple JSP with a small amount of JavaScript is sufficient. This is shown in Listing 5. Listing 5. Client Comet code <%@page contentType=quot;text/htmlquot; pageEncoding=quot;UTF-8quot;%> <!DOCTYPE HTML PUBLIC quot;-//W3C//DTD HTML 4.01 Transitional//ENquot; quot;http://www.w3.org/TR/html4/loose.dtdquot;> <html> <head> <meta http-equiv=quot;Content-Typequot; content=quot;text/html; charset=UTF-8quot;> <title>Comet Weather</title> <SCRIPT TYPE=quot;text/javascriptquot;> function go(){ var url = quot;http://localhost:8484/WeatherServer/Weatherquot; var request = new XMLHttpRequest(); request.open(quot;GETquot;, Developing with Comet and Java Page 10 of 19 © Copyright IBM Corporation 2009. All rights reserved.
  • 11. ibm.com/developerWorks developerWorks® url, true); request.setRequestHeader(quot;Content-Typequot;,quot;application/x-javascript;quot;); request.onreadystatechange = function() { if (request.readyState == 4) { if (request.status == 200){ if (request.responseText) { document.getElementById(quot;forecastsquot;).innerHTML = request.responseText; } } go(); } }; request.send(null); } </SCRIPT> </head> <body> <h1>Rapid Fire Weather</h1> <input type=quot;buttonquot; onclick=quot;go()quot; value=quot;Go!quot;></input> <div id=quot;forecastsquot;></div> </body> </html> This code simply starts the long poll when the user clicks the Go button. Notice that it uses the XMLHttpRequest object directly, so this will not work in Internet Explorer 6. You probably want to use an Ajax library to smooth over the browser differences. The only other important thing to note is the callback function, or, the closure created for the request's onreadystatechange function. This function pastes in the new data from the server and then re-invokes the go function. Now we have seen what a simple Comet application looks like on Tomcat. There were two very Tomcat-centric things we had to do: configure its connector and implement a Tomcat specific interface in the servlet. So you may be wondering just how difficult it would be to quot;portquot; this code to Jetty. Let's take a look at that next. Jetty and Comet The Jetty server uses a slightly different technique to enable a scalable implementation of Comet. Jetty supports the programming construct known as continuations. The idea is simple enough. A request is suspended and continued at some point in the future. The resumption could happen either because of a timeout or some other, meaningful event. While the request is suspended, its thread is freed up. Developing with Comet and Java © Copyright IBM Corporation 2009. All rights reserved. Page 11 of 19
  • 12. developerWorks® ibm.com/developerWorks You can use Jetty's org.mortbay.util.ajax.ContinuationSupport class to create an instance of org.mortbay.util.ajax.Continuation for any HttpServletRequest. This allows for a very different approach to Comet. However, continuations can be used to implement a logically identical style of Comet. Listing 6 shows the weather servlet from Listing 2 after it has been quot;portedquot; to Jetty. Listing 6. Jetty Comet servlet public class JettyWeatherServlet extends HttpServlet { private MessageSender messageSender = null; private static final Integer TIMEOUT = 5 * 1000; public void begin(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { request.setAttribute(quot;org.apache.tomcat.cometquot;, Boolean.TRUE); request.setAttribute(quot;org.apache.tomcat.comet.timeoutquot;, TIMEOUT); messageSender.setConnection(response); Weatherman weatherman = new Weatherman(95118, 32408); new Thread(weatherman).start(); } public void end(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { synchronized (request) { request.removeAttribute(quot;org.apache.tomcat.cometquot;); Continuation continuation = ContinuationSupport.getContinuation (request, request); if (continuation.isPending()) { continuation.resume(); } Developing with Comet and Java Page 12 of 19 © Copyright IBM Corporation 2009. All rights reserved.
  • 13. ibm.com/developerWorks developerWorks® } } public void error(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { end(request, response); } public boolean read(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { throw new UnsupportedOperationException(); } @Override protected void service(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { synchronized (request) { Continuation continuation = ContinuationSupport.getContinuation (request, request); if (!continuation.isPending()) { begin(request, response); } Integer timeout = (Integer) request.getAttribute (quot;org.apache.tomcat.comet.timeoutquot;); boolean resumed = continuation.suspend(timeout == null ? 10000 : timeout.intValue()); if (!resumed) { error(request, response); } } } public void setTimeout(HttpServletRequest Developing with Comet and Java © Copyright IBM Corporation 2009. All rights reserved. Page 13 of 19
  • 14. developerWorks® ibm.com/developerWorks request, HttpServletResponse response, int timeout) throws IOException, ServletException, UnsupportedOperationException { request.setAttribute(quot;org.apache.tomcat.comet.timeoutquot;, new Integer(timeout)); } } The most important thing to notice here is how the structure mimics the Tomcat version of the code. The begin, read, end, and error methods match up to the same events in Tomcat. The servlet's service method is overridden to create a continuation when the request first comes in and suspends it until either the timeout is hit or another event causes it to resume. The init and destroy methods are not shown above because they are identical to the Tomcat version. This servlet uses the same MessageSender as the Tomcat version. No modification is needed. Notice how the begin method creates a Weatherman instance. That class is also used exactly as in the Tomcat version. Even the client code is identical. Only the servlet is changed at all. Its changes are significant, but with a straightforward mapping back to the event model in Tomcat. I hope this is encouraging. The exact same code does not work in both Tomcat and Jetty, but it is very similar. Of course one of the appeals of JavaEE is portability. Most code that runs in Tomcat will run in Jetty with no modification and vice versa. Thus it should come as no surprise that the next version of the Java Servlet specification includes a standardization of asynchronous request processing, or, the underlying technology behind Comet. Let's take a look at that spec, the Servlet 3.0 spec. Servlet 3.0 spec We could dive into all of the gnarly details of the Servlet 3.0 specification. Instead let's just take a look at what the Comet servlet might look like if it was running inside a Servlet 3.0 container. Notice the word quot;might.quot; The specification has been released for public review, but has not been finalized as of the time of this writing. Thus Listing 7 shows an implementation compliant with the public review specification. Listing 7. Servlet 3.0 Comet @WebServlet(asyncSupported=true, asyncTimeout=5000) public class Developing with Comet and Java Page 14 of 19 © Copyright IBM Corporation 2009. All rights reserved.
  • 15. ibm.com/developerWorks developerWorks® WeatherServlet extends HttpServlet { private MessageSender messageSender; // init and destroy are the same as other @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { AsyncContext async = request.startAsync(request, response); messageSender.setConnection(async); Weatherman weatherman = new Weatherman(95118, 32444); async.start(weatherman);; } } The nice thing here is that this is much simpler. In all fairness, a similar implementation is possible with Jetty, if we had not tried to adhere to the event model of Tomcat. The event model may have seemed sensible and could be easily implemented in containers other than Tomcat, like Jetty, but there will be no standardization around it. Looking back at Listing 7, notice that its annotation declares that it supports asynchronous processing and sets the timeout. The startAsync method is a new method on HttpServletRequest, and it returns an instance of the new class javax.servlet.AsyncContext. Notice that the MessageSender is being passed a reference to the AsynContext instead of the ServletResponse. Instead of closing the response, you should call the complete method on the AsyncContext instance. Also notice that the Weatherman was passed directly to the start method of the AsyncContext instance. This starts a new thread in the current ServletContext. So, despite being significantly different than either Tomcat or Jetty, it is not too hard to adapt the same style of programming to work with the proposed APIs of the Servlet 3.0 specification. It should be noted that Jetty 7 is intended to implement Servlet 3.0 and is available in a beta form. However, as of the time of writing, it did not implement the latest version of the specification as shown above. Developing with Comet and Java © Copyright IBM Corporation 2009. All rights reserved. Page 15 of 19
  • 16. developerWorks® ibm.com/developerWorks Summary Comet-style Web applications can bring a whole new level of interactivity to the Web. It presents some complex challenges for implementing these features on a large scale. However, the leading Java Web servers are all providing mature, stable technology for implementing Comet. You have seen in this article the differences and similarities of the current flavors of Comet on Tomcat and Jetty, as well as the ongoing standardization effort for the Servlet 3.0 specification. Tomcat and Jetty make it possible to build scalable Comet applications today, with a clear upgrade path to standardization under Servlet 3.0 in the future. Developing with Comet and Java Page 16 of 19 © Copyright IBM Corporation 2009. All rights reserved.
  • 17. ibm.com/developerWorks developerWorks® Downloads Description Name Size Download method Weather Server Source Code WeatherServer.zip 347KB HTTP Information about download methods Developing with Comet and Java © Copyright IBM Corporation 2009. All rights reserved. Page 17 of 19
  • 18. developerWorks® ibm.com/developerWorks Resources Learn • quot;The allure of Cometquot; (Erik Burkhart, developerWorks, November 2007): Find out more about the history and motivations behind Comet. • quot;High-performance Ajax with Tomcat Advanced I/Oquot; (Adriaan de Jonge, developerWorks, September 2008): Learn even more about Comet on Tomcat. • quot;Ajax for Java Developers: Write Scalable Comet applications with Jetty and Direct Web Remotingquot; (Philip McCarthy, developerWorks, July 2007): Direct Web Remoting (DWR) can make Ajax a lot easier for Java developers, and it can do the same for Comet. Find out how in the developerWorks article. • quot;Java EE meets Web 2.0quot; (Constantine Plotnikov et al., developerWorks, November 2007): Dive into the performance implications of Comet. • quot;Developing Rich Internet Applications with WebSphere Application Server Community Editionquot; (Manu George and Vamsavardhana Reddy Chillakuru, developerWorks, September 2008): Read about how Comet works equally well in a full Java EE stack. • Asynchronous HTTP Comet architectures: Check out Asynchronous HTTP Comet architectures for even more information on Comet in Java. • An Introduction to Servlet 3.0: Read about all of the new features of Servlet 3.0. • Check out the reference information about Tomcat's Advanced IO and Continuations in Jetty. • quot;Creating mashups on the Google App Enginequot; (Michael Galpin, developerWorks, August 2008): See how you can use Python and the Prototype JavaScript library to create a Comet application that can be deployed to the Google App Engine. • Web development zone: See the developerWorks Web development zone for a wide range of technical articles and tips, tutorials, and standards. • developerWorks podcasts: Listen to interesting interviews and discussions for software developers. • developerWorks technical events and webcasts: Stay current with developerWorks technical events and webcasts. Get products and technologies • JDK 1.5.0-16 was used in this article. • Jetty: Jetty 6.1.14 was used in this article. • Tomcat: Tomcat 6.0.14 was used in this article. Developing with Comet and Java Page 18 of 19 © Copyright IBM Corporation 2009. All rights reserved.
  • 19. ibm.com/developerWorks developerWorks® • Innovate your next open source development project with IBM trial software, available for download or on DVD. • Download IBM product evaluation versions, and get your hands on application development tools and middleware products from DB2, Lotus, Rational, Tivoli, and WebSphere. Discuss • Participate in the developerWorks community. About the author Michael Galpin Michael Galpin has been developing Web applications since the late 90's. He holds a degree in mathematics from the California Institute of Technology and is an architect at eBay in San Jose, CA. Developing with Comet and Java © Copyright IBM Corporation 2009. All rights reserved. Page 19 of 19