dev@grizzly.java.net

Re: Dead Simple Comet example

From: Jeanfrancois Arcand <Jeanfrancois.Arcand_at_Sun.COM>
Date: Thu, 01 May 2008 16:52:43 -0400

Hi Jim,

Jim Driscoll wrote:
> 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.

Yes

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

Right :-) All version of that demo have this issue :-)

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

which write the new counter value to the suspended connection, and then
resume it.

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

Looking at the code, I see:

> if (CometEvent.NOTIFY == event.getType()) {
> int count = counter.get();
> PrintWriter writer = response.getWriter();
> writer.write("<script type='text/javascript'>parent.updateCount('" + count + "')</script>\n");
> writer.flush();
> //event.getCometContext().resumeCometHandler(this);
> }

The resumeCometHandler is commented out. Which means the connection is
never closed when an event happens. Which means you are now using
http-streaming instead of long polling. So from that the connection
doesn't seems to be terminated, but instead stay in "comet state" for 20
seconds.


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

So, what happens if two iframes connect? Both connection will be
suspended and the browser might not be able to send any more data. Let
me compile your demo :-)



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

My skills cannot help here....

  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.


Right, as you first need to reconnect. I know this is possible to do,
but I don't know how to do that :-) I think you need to register a
callback that gets invoked when the connection die.


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

Great. I'm playing with your demo now.

A+

-- Jeanfrancois


>
> Jim
>
>
> ------------------------------------------------------------------------
>
>
>
>
>
>
>
>
>
>
> Comet Example: Counter with Hidden Frame
>
> *...*
>
>
>
>
>
> ------------------------------------------------------------------------
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: dev-unsubscribe_at_grizzly.dev.java.net
> For additional commands, e-mail: dev-help_at_grizzly.dev.java.net