Home > Uncategorized > Introducing Grizzlet! Building Ajax/Comet based application with POJO

Introducing Grizzlet! Building Ajax/Comet based application with POJO

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….

_uacct = “UA-3111670-1”;
urchinTracker();

technorati:

Categories: Uncategorized
  1. No comments yet.
  1. No trackbacks yet.

Leave a Reply

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

WordPress.com Logo

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

Twitter picture

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

Facebook photo

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

Google+ photo

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

Connecting to %s

%d bloggers like this: