dev@grizzly.java.net

Dead Simple Comet example

From: Jim Driscoll <Jim.Driscoll_at_Sun.COM>
Date: Thu, 01 May 2008 10:59:08 -0700

OK, it kinda bugged me that Shing's first example didn't quite work, and
worse, that I didn't fully understand the control flow.

So I pulled it apart and put it back together, and it's considerably
simpler now. It's down to about 100 lines, not including spacing,
comments and web.xml, and it's only two files.

I'm pretty proud of myself :-) but I wouldn't have been able to get
started without Shing's work, so thanks for that! The second version is
always easier, right?

the 2 Files are attached, along with the web.xml.

So, here's the things I changed: remove frameset. Use only a single
iframe, and collapse the extra html into the index file. Add another
method to do a XMLHttpRequest instead of the form post, which gets rid
of the refresh problem (which is why I started working on the example in
the first place). Got rid of the forward in the doPost method (I never
really understood why it was there...)

Now, let me try to describe the program flow, so I'm sure I actually
understand what's going on. Please, read over this so I'm sure I've got
it right:

First, on startup, the servet is initialized, and registers itself with
with the Comet Engine. We set a timeout of 2 minutes.

Then on the first load of index.html in the browser, the hidden iframe
makes a call to the doGet of the servlet - this call suspends, awaiting
further action. It does this by attaching the response to a handler (of
type CounterHandler), and attaching the handler to the servlet's
CometContext. This also gives rise to the first bug of the program -
there's no display of initial result.

Next, someone, somewhere, who's also using the program, hits the button
marked "click". This calls the onclick method, postMe(). postMe sends
an empty POST to the servlet, triggering the doPost method.

The doPost method increments the counter, and then sends a notify event
to the servlet's CometHandler.

Now, you get an index.html file with a single iFrame, and some included
code. A button has an onclick() that posts to the servlet via
XMLHttpRequest, and ignores the response. The iFrame does a long poll
to the doGet, and the button triggers a Comet Event via the servlet's
CometContext.

This event now wakes up that initial GET request, and sends a bit of
javascript down the line. Since the event doesn't resume the handler,
that terminates the connection.

Back at the client, that javascript that got sent down gets put into the
hidden iFrame, and then executed. This calls the updateCount function,
which updates the counter with the new value. Then, we set the iframes'
location object, which reconnects with GET to the servlet, and we're
ready for our next request.

That is, unless we time out. If we time out (remember, we set the
timeout to 2 minutes, not "infinite"), the iframe goes dead, the GET
loop is broken, and we never again update the counter on the webpage,
though the user's increasing frustrated button pushing on the client
will happily update counter on the server. So, to get around this, we
add a single line at the end of our postMe function, updating the hidden
iframe's location again. This is the one really hacky part of the
program, and I'd love to know a better way to do it. Also, it gives
rise to the second bug of our program, related to the first - if the
connection dies, you need to click the button twice to see an update of
the counter on the client.

So - ta da! We have a bare bones, long polling comet application in two
files and about 100 lines.

I *really* want to know how to fix those two bugs I mentioned, so please
shoot back any ideas.

I'll be blogging based on this later today.

Jim

Comet Example: Counter with Hidden Frame

Comet Example: Counter with Hidden Frame

...