 |
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!
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: grizzly
grizzlet
asynchronous request processing comet ajax glassfish
Bookmark blog post: del.icio.us Digg DZone Furl 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
|