The Source for Java Technology Collaboration
User: Password:



Jean-Francois Arcand

Jean-Francois Arcand's Blog

Introducing Grizzlet! Building Ajax/Comet based application with POJO

Posted by jfarcand on September 21, 2007 at 11:00 AM | Comments (6)

The GlassFish's Comet implementation is 'live' for more than one year and fortunately, there is some really cool applications build on top of it (ex: 4homemedia, the co-founders of Kaazing nicely talked about it, internally our Sun Instant Messaging(XMPP protocol) systems is also using it, and much more). The Grizzly user list get regularly questions about Comet, and I'm getting a lot of private emails on the topic as well. But one thing I've learned with all those interactions is the fact that Ajax developers aren't that interested about writing a 'heavy' Servlet|JSP|JSF components in order to use the power of Comet. Even with Jetty, which was the first to support it and as a well defined API for Comet, it is still difficult....I'm not talking about Tomcat, as the community is collapsing those days, fighting about internal problems instead of innovating with Comet :-(. Hence most of the Ajax developers I've talked recently are not interested to learn how to write a Servlet, how to package it (although it is quite simple thanks to the Java EE 5), then learn what Grizzly Comet is and how you can use it. It would be much more simple if we can write a single POJO class, hook it to an Ajax client, and bang make it work! So here comes Grizzlet, an extremely simple POJO based approach to write Comet based application!

mathieu 072.jpg

What is a Grizzlet exactly? A Grizzlet is a very simple POJO that implement a single interface, the com.sun.grizzly.grizzlet.Grizzlet interface:

public interface Grizzlet {
    
    /**
     * When a client send a request to its associated Grizzlet, it can decide
     * if the underlying connection can be suspended (creating a Continuation)
     * or handle the connection synchronously. 
     *
     * It is recommended to only suspend request for which HTTP method is a GET
     * and use the POST method to send data to the server, without marking the
     * connection as asynchronous.
     *
     * @param asyncConnection An object representing an asynchronous connection.
     */
    public void onRequest(AsyncConnection asyncConnection) throws IOException;
    
    
    /**
     * This method is invoked when the Grizzlet Container execute a push 
     * operations. When this method is invoked by the Grizzlet Container, any
     * suspended connection will be allowed to push the data back to its
     * associated clients. 
     *
     * @param asyncConnection An object representing an asynchronous connection.
     */
    public void onPush(AsyncConnection asyncConnection) throws IOException;
   
}

The interface consists of two simple methods: onRequest and onPush. The onRequest method is similar to the Servlet.service method. The Grizzlet Container will invoke that method when a request is coming. From the AsyncConnection, it is possible to decide if the connection needs to be suspended(meaning parking the request), resumed or handled normally (synchronous request). This is also where you will decide to initiate a server push (to all connections that are suspended). The onPush method will be invoked by the Grizzlet Container when the AsyncConnection.push() is invoked, and this is where you will decide if you want to push data on a suspended connection. Still looking complicated? Let's re-write the Chat application TAKAI Naoto did on top of Grizzly Comet, but this time using a Grizzlet POJO. First, let's take a look at the onRequest method:

     51     public void onRequest(AsyncConnection ac) throws IOException {
     52         GrizzletRequest req = ac.getRequest();
     53         GrizzletResponse res = ac.getResponse();
     54
     55         res.setContentType("text/html");
     56         res.addHeader("Cache-Control", "private");
     57         res.addHeader("Pragma", "no-cache");
     58         if (ac.isGet()){
     59             // for IE
     60             res.write("<!-- Comet is a programming technique that enables web " +
     61                     "servers to send data to the client without having any need " +
     62                     "for the client to request it. -->\n");
     63             res.flush();
     64
     65             //
     66             // Mark this connection as suspended.
     67             //
     68             ac.suspend();
     69             return;
     70         } else if (event.isPost()){
     71             res.setCharacterEncoding("UTF-8");
     72             String action = req.getParameterValues("action")[0];
     73             String name = req.getParameterValues("name")[0];
     74
     75             if ("login".equals(action)) {
     76                 ac.push(
     77                     BEGIN_SCRIPT_TAG + toJsonp("System Message",name 
     78                             + " has joined.") + END_SCRIPT_TAG);
     79                 res.write("success");
     80                 res.flush();
     81             } else if ("post".equals(action)) {
     82                 String message = req.getParameterValues("message")[0];
     83                 ac.push(BEGIN_SCRIPT_TAG
     84                         + toJsonp(name, message) + END_SCRIPT_TAG);
     85                 res.write("success");
     86                 res.flush();
     87             } else {
     88                 res.setStatus(422);
     89                 res.setMessage("Unprocessable Entity");
     90
     91                 res.write("success");
     92                 res.flush();
     93             }
     94         }
     95     }

First, line 52/53 show how to get the Request/Response object. From the Request object, we get the http method, write some information, and then suspend the request. Once suspended, the connection is parked by the Grizzlet Container. As an example, if the connection was initiated by an iFrame on the client side, the browser logo will spin, waiting for the response to complete, which means the connection has been suspended by the server. From the client, any POSTs will ends up on line 70. Then for the Chat demo, a server push will be initiated when the AsyncConnection.push() method is invoked. As soon as the AsyncConnection.push is invoked, all suspended connections will have a chance to resume and push data back to their associated clients:

     98     public void onPush(AsyncConnection ac) throws IOException{
     99         GrizzletRequest req = ac.getRequest();
    100         GrizzletResponse res = ac.getResponse();
    101
    102         if (ac.hasPushEvent()){
    103             res.write(ac.getPushEvent().toString());
    104             res.flush();
    105             return;
    106         }
    107     }

The interesting part here is line 102 to 104. This is actually where the push happens. Every suspended/parked connections can now push back some data to their client, and then return in the suspended state. This is it! Nothing more need to be written on the server side.

As for the client side, you can use any Ajax libraries to render and communicate with the server side. BTW Download the Grizzlet Container here and the Chat demo from here. But wait, which Web Server supports Grizzlet? As of now, I've build a Grizzlet Container on top of Grizzly Web Server. My upcoming works on Grizzlet will consist of writing a generic Servlet that can redirect requests to a Grizzlet when an application is deployed in GlassFish v2, similar to what Goldspike does for JRuby applications. If peoples are interested to help, just join Project Grizzly!

As usual, I've try to made it extremely simple and easy to start the Grizzlet Container (even faster than GlassFish v3 :-)):

% java -jar grizzly-grizzlet-webserver-1.8.0.jar -p 8080 -a ChatGrizzlet.war com.sun.grizzly.grizzlet.ChatGrizzlet

INFO: New Servicing page from: /home/ja120114/90_appserv/grizzly/trunk/modules/comet/apps
Launching Grizzlet: com.sun.grizzly.grizzlet.ChatGrizzlet
Server startup in 241 ms

Mainly, the first parameters is the port on which the server listen, the second is the application folder, and the last one is the Grizzlet class name to use. The application folder is quite simple:


   4 drwxrwxr-x    3 ja120114 ja120114     4096 Sep 20 22:25 com
   4 drwxrwxr-x    2 ja120114 ja120114     4096 Sep 19 17:31 images
   4 -rw-rw-r--    1 ja120114 ja120114     1634 Sep 19 19:32 index.html
   4 drwxrwxr-x    2 ja120114 ja120114     4096 Sep 19 20:59 javascripts
   4 drwxrwxr-x    2 ja120114 ja120114     4096 Sep 19 21:01 stylesheets

A single index.html, the Grizzlet class and the javascripts/stylesheets. That's it. At least I've find it myself quite simple :-).

The good news is the Grizzlet's extension work like the Grizzly's JRuby on Rails, which means we gonna soon be able to invoke Grizzlet from a JRuby on Rails application.

But wait, from the example above, you can only "deploy" one Grizzlet per Grizzlet Container? That's true....for now, I've made it simple but if the features interest peoples, then it will be quite trivial to do the same trick as the JRuby on Rails extension: plug it into GlassFish v3/hk2 micro-kernel and have all the nice deployments features v3 is offering.

Another long story from the North.... Finally, if you want to see a killer demo on Grizzlet, just stop next week at AjaxWorld when I will unleash the Grizzlets everywhere and demo nice applications....

technorati:


Bookmark blog post: del.icio.us del.icio.us Digg Digg DZone DZone Furl Furl Reddit Reddit
Comments
Comments are listed in date ascending order (oldest first) | Post Comment

  • Hi jfarcand,
    Can i ask you a question on my own case study? Assume that i wanna have 5 ajax applications on my page, and i want them to be updated every time new data is available in database, for that I will write a servlet which will check database every n seconds. But how can i organize connection sharing between 5 ajax apps in round robin fashion, because as you suggested i will use only one connection. is it achievable? thanks.

    Posted by: badboy on September 23, 2007 at 09:30 PM

  • Hi Jean-Francois, sounds great, to have a "framework" for simple comet programming. Wouldn't it be good if something like this would make it into the Servlet-API 3.0 (in case comet will be targeted).

    Posted by: mwessendorf on September 24, 2007 at 07:54 AM

  • seen this: http://www.jroller.com/ferg/entry/resin_comet

    Posted by: mwessendorf on September 25, 2007 at 01:00 AM

  • Salut Jean-Francois, can you use DWR reverse ajax with GlassFish's Comet implementation?

    Posted by: caroljmcdonald on October 02, 2007 at 07:12 AM

  • Hi, DWR only support Jetty Comet right now. One day I will submit a patch to the DWR team so they can support GlassFish as well :-).

    Posted by: jfarcand on October 02, 2007 at 07:41 AM

  • I wouldn't bother with the Euro spec turbo's, you won't gain a lot for the hassle. However a hybridised pair of stock turbo's might be worth it. They are the same externally as the stock turbo's but feature larger compressor and turbine wheels.

    The 550cc injectors will allow you to get close to 550HP with the right turbo's but in reality a small single turbo is required to achieve the power as even the hybrid OEM turbos arn't capable of flowing that much air.how to play roulette
    roulette how to win
    roulette tips
    how to win at roulette
    Run your car on water
    Run Car on Water
    Water Powered Car
    Water Car
    horse racing
    horse racing tips
    horse racing betting
    horse racing software
    horse racing systems
    downloadable movies
    download full version movies
    download movies
    movie downloads
    forex trading systems
    forex currency trading
    forex software
    learn forex
    world of warcraft guide
    wow gold guide
    wow guide
    world of warcraft cheats
    how to play poker
    learn poker
    poker strategy
    poker sites
    poker calculator
    free blackjack
    online blackjack
    blackjack strategy
    how to play blackjack
    iphone downloads
    iphone games download
    iphone download site review
    iphone download sites
    how to make money on ebay
    make money on ebay
    warren buffett
    warren buffet

    Posted by: j_doe1 on May 25, 2008 at 04:40 AM



Only logged in users may post comments. Login Here.


Powered by
Movable Type 3.01D
 Feed java.net RSS Feeds