Archive

Archive for September, 2007

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

What’s really cool with GlassFish v2.

Kaboom! Today we have announced the official release of GlassFish v2, aka our 9.1 version. Tons of blogs will pops up about the subject, but none of them will tell you what’s really cool with v2! If you expect reading stuff about Servlet, JSP, Toplink or EJB, then move away as I personally don’t consider those technologies cool enough those days :-). GlassFish v2 hidden features (or not officially ‘marketed’) are much much cool. So what are they? Here we come:

v2.JPG

JRuby on Rails Support. Although not officially supported in v2, JRuby on Rails is what I consider the coolest thing you can do with GlassFish v2. The Grizzly’s native support (which is also the foundation of GlassFish v3 support) makes JRuby on Rails experience really cool…and fast!

Comet support. This is my favorite one as I can’t stop having fun with it! :-). As AJAX based applications are becoming the de facto technology when designing a web based application, it is becoming essential that such applications can react “on the fly”, or real time to both client and server events. When data are manipulated either by clients or servers components, it is fundamental to have the capability to update web based applications in real time. The Comet request protocol can be used as a technique to enable real-time updates of both clients and server component which are part of a web application. GlassFish v2 is one of the first Application Server that support Comet via the Grizzly Asynchronous request processing (ARP) extension. Fully asynchronous application (client and/or server side) can be easily written (and already used in cool product like this one). More important, Grizzly’s Comet is the only one that fully support server side asynchronous read and write operations (neither Jetty nor Tomcat have it ready like GlassFish :-)). Interested to learn what is Comet and how to use it? Here is a list of GlassFish related blogs:

Virtual Hosting: Virtual Hosting features of v2 are greatly improved over our previous version. Check here for more info.

Http compression: v2 now support Http Compression. For people that care about bandwidth, http compression is the way to go.

Java Web Start Support: that feature is really cool when it’s time to distribute your application. More info here.

No native code anymore!. OK that one is really my favorite one! SJS AS 7.0, 8.1/8.2 EE version shipped with the Sun native WebServer as front end, where 8.x and 9.0 shipped with Grizzly. After months, and months, and months of debates and discussions, we where able to convince peoples internally that a pure Java based Web Server can perform as well (and faster!) than a native C server. Trust me it wasn’t easy at all to manage to remove that C monster (event at Sun!). Hence our 9.1 EE (enterprise edition) release is our FIRST release that doesn’t contains C code for the http path. The internal war is finally over…and the winner is: JAVA

Finally, there are tons of new things coming from the Web team that can be found here. Innovation is back 🙂

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

technorati:

Categories: Uncategorized