4. Pushlet Basics

So what are these Pushlets and how do they work ? In its basic form a Pushlet is luckily extremely simple. Through a few examples I will show the basics. It is by now also time for some code !

4.1. HTTP Streaming

Pushlets are based on HTTP streaming, a technique that is sometimes used in multimedia viewing applications such as QuickTime. Instead of closing the HTTP connection after fetching an HTML page, the connection is kept open while fresh data is pushed to the client.

4.2. Example 1

Taking the idea of HTTP streaming we could develop a JSP (since that it easier to deploy, but it could be a servlet as well) that continuously sends new HTML content back to the client in a timer loop.

<HTML> <HEAD> <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1"> <META HTTP-EQUIV="Pragma" CONTENT="no-cache"> </HEAD> <BODY BGCOLOR="blue" TEXT="white"> <% int i = 1; try { while (true) { out.print("<h1>"+(i++)+"</h1>"); out.flush(); try { Thread.sleep(3000); } catch (InterruptedException e) { out.print("<h1>"+e+"</h1>"); } } } catch (Exception e) { out.print("<h1>"+e+"</h1>"); } %> </BODY> </HTML>

Click example 1 on the examples/basics page. This is not very useful since the pushed content is continuously appended to the page while we would like to refresh it.

4.3. Example 2

Here we jump right into the Pushlet mechanics. Click on example 2 on the examples/basics page and see that the page is refreshed every 3 seconds. How the ... is this done ?

This example consists of three files: push-js-stream.html, push-js-stream-pusher.jsp and push-js-stream-display.html. push-js-stream.html is the main page which contains each of the two other files in HTML FRAMEs. Let's just follow the route of the events.

The following lists push-js-stream-pusher.jsp. This is a JavaServer page that is executed on the server when requested. The main body of this file is listed below.

7: <% 8: /** Start a line of JavaScript with a function call to parent frame. */ 9: String jsFunPre = "<script language=JavaScript >parent.push('"; 10: 11: /** End the line of JavaScript */ 12: String jsFunPost = "')</script> "; 13: 14: int i = 1; 15: try { 16: 17: // Every three seconds a line of JavaScript is pushed to the client 18: while (true) { 19: 20: // Push a line of JavaScript to the client 21: out.print(jsFunPre+"Page "+(i++)+jsFunPost); 22: out.flush(); 23: 24: // Sleep three secs 25: try { 26: Thread.sleep(3000); 27: } catch (InterruptedException e) { 28: // Let client display exception 29: out.print(jsFunPre+"InterruptedException: "+e+jsFunPost); 30: } 31: } 32: } catch (Exception e) { 33: // Let client display exception 34: out.print(jsFunPre+"Exception: "+e+jsFunPost); 35: } 36: %>

NB there may be a problem with examples 1 and 2 when using JSPs: some servlet engines will "eat" the IOException when a client leaves such that the JSP page will never catch the exception. In that case the loop may run forever. This is one of the reasons that the Pushlet implementation uses a Servlet (where the IOException can be and is caught).

Again we see a timer loop which prints (line 21) some HTML to the browser every three seconds. But wait, it is not pushing HTML but JavaScript ! What does this mean ? Effectively it pushes a line like for example <script language=JavaScript >parent.push('Page 4')</script>. What does this mean for the browser ? The browser has its JavaScript engine running and obediently executes each next line coming in. It is calling a JavaScript function parent.push(). Now the parent is the parent of the FRAME it is in, which is our first file push-js-stream.html. Let's see what happens there.

<script LANGUAGE="JavaScript"> var pageStart="<HTML><HEAD></HEAD><BODY BGCOLOR=blue TEXT=white><H2>Server pushes: <para>"; var pageEnd="</H2></BODY></HTML>"; // Callback function with message from server. // This function is called from within the hidden JSP pushlet frame function push(content) { // Refresh the display frame with the content received window.frames['displayFrame'].document.writeln(pageStart+content+pageEnd); window.frames['displayFrame'].document.close(); } </script> </HEAD> <FRAMESET BORDER=0 COLS="*,0"> <!-- frame to display the content pushed by the pushlet --> <FRAME SRC="push-js-stream-display.html" NAME="displayFrame" BORDER=0 SCROLLING=no> <!-- Hidden frame with the pushlet that pushes lines of JavaScript--> <FRAME SRC="push-js-stream-pusher.jsp" NAME="pushletFrame" BORDER=0 SCROLLING=no> </FRAMESET>

We see the push() function called from within the JSP frame (pushletFrame) is writing whatever it gets passed in its argument 'content' into the displayFrame. This is a piece of Dynamic HTML: you can refresh the content of a frame or window by calling 'writeln' of its 'document' object. So the displayFrame is the real View where the content is displayed. It is initially black and displaying a 'Wait...' text until the first content is pushed from the server.

<HTML> <BODY BGCOLOR=black TEXT=white> <H1>WAIT...</H1> </BODY> </HTML>

This is basically the whole idea of Pushlets: we just stream in lines of JavaScript from a Servlet (or JSP for the example). These lines get interpreted by the browser who may do something interesting. So effectively we have a callback from Java in the server to JavaScript in the browser client ! Phew, that was easy !

This example showed the mechanics, but there are still a couple of issues to be solved and features to be added. For this reason I've built a small server-side Pushlet framework shown in the class diagram, plus some JavaScript libraries for the client. Since the client heavily will rely on more DHTML features such as Layers we will walk through some DHTML first. See examples/dthml.