Skip to content


GWT + Grizzly + Comet

Ok, so you’re probably looking for a simple example of GWT + Grizzly + Comet. Jean Francois and his buddies at JavaOne screwed us with their vague PDF. Bastards! I gotta say this, though, Jean was right, its not too hard to figure out.

This implementation uses XHR long polling, glassfishv2.ur2 and grizzly comet 1.0.9.

The problem: RemoteServiceServlet

GWT loves POST. All RPC calls made back to your subclass of RemoteServiceServlet will hit the doPost method. However, this method is final and cannot be overridden – meaning we cannot create a comet handler for the request in our subclass of RemoteServiceServlet. We want to continue using RPC but we don’t want to use RemoteServiceServlet. WTF?

The solution: SimpleServiceServlet

Pretty much the RemoteServiceServlet is too secretive. So I pulled out its code and gutted it- creating SimpleServiceServlet. It’s new doPost method calls doConnect which you can override in your subclass – allowing you to create a comet handler. Yay.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public class CometServiceImpl extends SimpleServiceServlet implements CometService {
   public CometContext cc;
 
   public CometServiceImpl() {
   }
 
   class GWTCometHandler implements CometHandler<HttpServletResponse> {
      ....
   }
 
   public void doConnect(HttpServletRequest req, HttpServletResponse res) {
      try {
         res.setContentType("text/html;charset=ISO-8859-1");
         GWTCometHandler ch = new GWTCometHandler();
         ch.attach(res);
         ch.attachRequest(req);
         cc.addCometHandler(ch);
      } catch (Exception e) {
         System.out.println("connect: e=" + e);
      }
   }
}

Other issues: The RPC Thing

GWT expects a return value from RPC methods. But what about in the case of comet? There technically isn’t an RPC method – a connection is established and then the client waits. Well, lets not re-write GWT, lets just make it happy. In traditional GWT RPC apps we extend the “RemoteService” interface that’s used by the server and the client. Let’s go ahead and do that:

1
2
3
public interface CometService extends RemoteService {
   Message comet();
}

And lets also create the object we are going to return via comet and RPC:

1
2
3
4
5
6
7
8
9
10
11
public class Message implements IsSerializable{
   private String text;
 
   public void setText(String text) {
      this.text=text;
   }
 
   public String getText() {
      return text;
   }
}

So we basically follow the pattern perscribed to us by GWT – but heres the catch. In our implementation of CometService we do the following:

1
2
3
public Message comet() {
   return null;
}

Yes, we return null! This way we make GWT happy – it can continue to do all of its fancy RPC’ing. And we can do comet without any hassles. But, how do we return serialized objects to the client?

Return serialized objects?

We do it in our subclass of grizzly’s CometHandler -

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
class GWTCometHandler implements CometHandler<HttpServletResponse> {
   HttpServletResponse res;
   HttpServletRequest req;
   public void onEvent(CometEvent ce) throws IOException {
      System.out.println("onEvent");
      // GWTEvent event = (GWTEvent) ce.attachment();
      Message msg = (Message) ce.attachment();
      try {
         //LETS SERIALIZE!!!
         String encoded = RPC.encodeResponseForSuccess(CometServiceImpl.class.getMethod("comet"), msg);
         //LETS WRITE THE RESPONSE
         writeResponse(req, res, encoded);
         removeThisFromContext();
      } catch (SecurityException e) {
         e.printStackTrace();
      } catch (SerializationException e) {
         e.printStackTrace();
      } catch (NoSuchMethodException e) {
         e.printStackTrace();
      }
   }
   ......
}

The Code:

A good sample app is worth a thousand words – download it here. This is a very simple and rough attempt at getting GWT working with Grizzly Comet. I’ll be posting an improved version at some point. It does not work in the GWT shell. You will have to deploy it to glassfish.

Posted in Java, JavaScript.

Tagged with , , , .


3 Responses

Stay in touch with the conversation, subscribe to the RSS feed for comments on this post.

  1. igf1 says

    Hi!! After looking over the source , I truly have to tell you how much I appreciate your efforts. .. ok, that was the prelude to a question :)

    I cant get this to run on glassfish V2u2 for whatever reason, the error I get:
    StandardWrapperValve[CometServiceImpl]: PWC1382: Allocate exception for servlet CometServiceImpl
    java.lang.NoClassDefFoundError: com/google/gwt/user/client/rpc/RemoteService

  2. JensHeyer says

    I deployed your attached war file to a local GlassFish 2.1 instance but somehow it doesn’t work as expected. When clicking a button I just get an “error” message. The server.log comprises a stack trace indicating that the RemoteService class is missing although it is included by the gwt-user.jar in the lib folder:

    [#|2009-02-23T12:35:23.979+0100|SEVERE|sun-appserver2.1|javax.enterprise.system.container.web|_ThreadID=26;_ThreadName=httpSSLWorkerThread-8080-2;_RequestID=680bcb0b-9f87-41b2-be80-587e6859a27f;|StandardWrapperValve[CometServiceImpl]: PWC1382: Allocate exception for servlet CometServiceImpl
    java.lang.NoClassDefFoundError: com/google/gwt/user/client/rpc/RemoteService
    at java.lang.ClassLoader.defineClass1(Native Method)
    at java.lang.ClassLoader.defineClass(ClassLoader.java:620)
    at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:124)
    at org.apache.catalina.loader.WebappClassLoader.findClass(WebappClassLoader.java:983)
    at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1501)
    at java.lang.ClassLoader.loadClassInternal(ClassLoader.java:319)

    Can you help me concerning that problem?

  3. tojewel says

    Hello rock, May I know, which GWT version have you used? Does this work with GWT 1.5.3 ? Thanks.