Pushlets - Whitepaper
Author: Just van den Broecke
Date: August 6, 2002
Pushlets are a servlet-based mechanism where data is pushed directly from server-side Java objects to (Dynamic) HTML pages within a client-browser without using Java applets or plug-ins. This allows a web page to be periodically updated by the server.
Server-side notification to browser-clients is often implemented using applets with RMI, CORBA or custom TCP/IP messaging. These techniques are often complex to implement, have firewall restrictions, and require additional server development/maintenance. Also it is hard to integrate the state of the client-applet with the browser's page-content other than refreshing the page or doing all content-layout within the applet.
Now that more and more Servlets and JavaServer Pages (JSPs) are being deployed on the web, there is often a need to notify and synchronize client web-browsers from state changes in server objects after the browser has loaded a page.
These changes can be caused by users updating an EJB through a servlet or database record or by events in a multi-user application such as chat and shared whiteboard. These type of applications often use a distributed Model View Controller (MVC) pattern where the Model is on the server (with possible caching in clients) and the Control and View (possibly combined) reside within the client.
There are also applications where we would like to subcribe to dynamic content that is continuously pushed from the server. Examples stock feeds, system status, weather conditions or other monitoring applications. This follows an Observer (a.k.a. Publish/Subscribe) pattern where remote clients (Observers) register for updates from server objects (Subjects).
How can we notify browser-clients after their HTML page has loaded ? Or what to do if we would like to selectively update only parts of a page. For example only the stock item in an HTML TABLE whose rate has changed ?
Let's assume that we have a Java web/application server from which we want to notify client browsers. Solutions we have can be categorized as "polling", "server-side callbacks" and "messaging".
Each of the above solutions has its advantages/disadvantages in complexity, security, performance, scalability, browser Java compatibility and restrictions like firewalls. The most optimal solution strongly depends on what your application is supposed to do. For example, when users require a direct interaction with the state such as in a shared whiteboard, server side-callbacks or messaging can be a powerful technique.
But we are still within a browser and unless the applet constitutes the entire client application, it is hard to integrate updates coming from the server with the HTML content. How can we alter this content from within the applet when it gets the callback or message ? One solution is to refresh the page by calling AppletContext.showDocument(URL) within the callback method.
Since HTML is meant for layout, wouldn't it be nice to be able to directly alter parts of the HTML content with incremental data coming from the server ? This would be an ideal scheme for web-applications where content on the server is dynamically changing and the required user-to-server interaction is minimal, e.g. driven by HTML FORMs.
In addition to the above solutions I have developed a technique that is lightweight, thin on the client, requires no applets or plug-ins, directly integrates with scripting/HTML, uses standard HTTP connections and can be deployed (in theory!) in any Java servlet-server. It is certainly not meant to replace the above solutions. My intention is to add another option to your toolbox. You as Java architects/developers should determine the trade-offs and choose what is best for your particular application.
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 !
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.
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.
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.
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.
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).
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.
Long gone (in Internet time) are the days when websites could be produced by the local sysop who scanned in some images from the company's brochure and knew a few HTML-tags. The possibilities for manipulating content and user interaction within the browser are expanding through something called "Dynamic HTML" (DHTML). As a Java programmer using servlets and JSPs, DHTML is something that should become part of your toolkit.
This hits an issue that has witheld many developers from embracing DHTML. First of all you need a version 4+ browser. The "official" standards body for DHTML-related specifications is the World Wide Web Consortium (W3). However the Microsoft and Netscape type 4+ browsers each have proprietary DHTML extensions that you must track as well.
So with Java gaining more market on the server and DHTML having these powerful features on the client, my idea with Pushlets was to directly couple these two great technologies in a very direct way. For this I have implemented a lightweight framework for the server and some DHTML libraries for the client. These are discussed next in the Design section.
The Pushlet framework allows clients to subscribe to subjects within a server from which they subsequently receive events. The framework's basic design pattern is Publish-Subscribe also known as Observer and has both server and client components:
Below is the UML class diagram of the server-side Java classes [reflects v0.0.4; rework required].
Figure 1. Pushlet Framework Class Diagram.
The key classes are the Pushlet servlet, the Publisher class, Subscriber interface, and the Event class (see class diagram). By invoking the Pushlet servlet through an HTTP request, clients subscribe to receive Events. In the request is indicated:
Subject identifiers are organized as an hierarchical "topic-tree". For example, "/stocks" identifies all Events related to stock rates, while "/stocks/aex" identifies stock rates for the Amsterdam EXchange. Likewise the subject "/" indicates all events.
Currently the only receiver protocol is a client HTTP response stream. In a future extension also the receiver protocol and address can be indicated, e.g. TCP, UDP, RMI, HTTP POSTing, or even SMTP (email).
An Event is merely a set of name/value String pairs (implemented with java.util.Properties). The Publisher has an interface through which classes that generate Events can publish them. The Publisher keeps a list of Subscribers and sends each Event to those Subscribers whose subject matches to the Event's subject. Events may be originating within the server through EventGenerators who may listen to external events such as a stock feed. In addition clients may publish Events through HTTP with the Postlet class. The responsibilities of other classes in class diagram, PushletSubscriber and its contained classes can best be explained through scenario's.
Figure 2. Subscribe Sequence Diagram.
Above is the UML sequence diagram for a browser client subscribing for events from the Publisher. The Pushlet is invoked with the servlet method doGet(). Because multiple clients may invoke the same Pushlet object, it should itself not be a Subscriber. Instead it delegates all subscription (and subsequent Event handling) by creating a new PushletSubscriber object for each doGet() and letting it run until finished with eventLoop(). The PushletSubscriber is a Subscriber object towards the Publisher where it registers with the join() method. To deal with different client formats and protocols it creates a specialized ClientAdapter object, in this case a BrowserPushletAdapter. For browsers supporting Multipart MIME such as Netscape 4+, this would be a MultipartBrowserClientAdapter. The final call in this scenario is a "wait for event loop". Note that deQueue() is a method that suspends the execution of the current thread until an Event becomes available (indicated with half-arrow). This is explained through the next scenario.
Figure 3. Publish Sequence Diagram.
Above is the UML sequence diagram for sending an Event. It shows how an Event is generated and dispatched to the browser client. In this scenario an EventGenerator creates an Event and calls Publisher.publish() to have it dispatched. The Publisher walks through its list of Subscribers and asks each if the Event matches its subscription criteria (currently only the subject). If it matches it calls send() on the Subscriber.
Each PushletSubscriber object has a GuardedQueue object in which it queues incoming Events when send() is called. So why isn't it just directly pushing the Event to the BrowserPushletAdapter ? First of all we want to suspend execution of the BrowserPushletAdapter-thread until an Event becomes available, i.e. we don't want to do a "busy-wait" (a.k.a. as polling). The second reason is that a Publisher may notify multiple clients. Having a synchronous send() call a slow client on the other end of the line may block all other clients that are to be notified next. This is actually a design pitfall which I see also in RMI or CORBA callback examples where a list of clients is called back synchronously. Client #13 on a slow connection and 386 processor may spoil it for the rest.
By now we have arrived on the client browser side. The Pushlet itself was assigned to a hidden HTML FRAME. The parent of that FRAME is called and has to implement the push() method. Since this is a common task for all browser clients, two reusable files are provided for the client: pushlet.html (see /src/nl/justobjects/pushlet/pushlet.html) and pushlet.js (see /src/nl/justobjects/pushlet/pushlet.js).
Next push() calls updateStatusFrame() to show a blinking light to indicate we are still receiving events and if a parent.onPush() function exists, it calls it with the PushletEvent. parent.onPush() is the application-specific event handling function that in this case may update the 'philips' stock-related Layer in a DHTML page.
This ends the description of the basic framework design.
Pushlets allow many types of web applications to be developed. Since the framework also allows for clients to upload events (through the Postlet), possible applications are not just passive pushing of data. Each application can be categorized according to:
Below is a range of applications. On the Pushlets website several simple demos are provided.
Various data sources may be monitored live such as stocks, weather, votes, flight arrivals and systems.
See a real-world FX stocks/news application that I worked on at www.rabotreasuryweb.com (IE only).
I also discovered other real-time stock/news sites that are deploying Pushlets or a variant:
From a two-user tic-tac-toe up and chess up to more elaborate Risk and Monopoly.
This refers to a design pattern often found in user interface frameworks such as Java Swing and Microsoft MFC. In the distributed variant a Model (often the data) resides on a server while clients hold the Views and Controls. Through the Controls the Model is modified. The Model will then notify all attached Views who will subsequently refresh themselves.
Many applications may have a web front-end through which data on the server is updated by multiple users. Examples are reservation systems and bookings. If one client makes an update, the others won't see the update unless they continuously refresh their pages. In some cases this is a simple and workable solution, but there are also cases where users need to be synchronized with the update as it happens. This type of application is easily done with Pushlets pushing a URL as the single event. When a client receives the URL it will refresh the page with it.
One notable example are the much discussed Enterprise JavaBeans (EJBs). Although Java clients are able to talk directly to an EJB (through RMI or CORBA), more often servlets and JSPs are used as a front-end. In this case notification becomes much harder. With Pushlets an EJB could notify its attached web-clients whenever its state changes.
Also known as WebTours or like I dubbed once: "Are you being surfed ?". This is actually an application from which I derived Pushlets. I abandoned PowerPoint for making Java course content and developed a content management framework based on XML with presentation (slides etc) in HTML. Since in many situations the classroom had no beamer but all students a networked computer, I developed a simple application (WebPres) that allowed me to change HTML slides with all students automatically following them in their browsers.
This type of application can also be useful in situations like call centers, banks or help-desks or e-commerce web applications in general. When I phone in with a question the agent may surf me to URLs with solutions, offers or other information.
A real-world application where this example of Pushlet-technology is currently used is a foreign-exchange trading application I helped developing at one of my clients. See the result at www.rabotreasuryweb.com (IE only).
Using a back-end of EJBs and a JSP front-end, clients can buy or sell foreign currencies. An "AutoTrader" object automates the offering process. If somehow the automatic offering fails or the client requests a human dealer, a "Dealer Intervention" takes place, whereby a dealer is notified and enters a new offer which is pushed to the client browser using Pushlet technology.
Various applications where multiple users can join in a live session. I originally had a prototype of the framework where a multi-user session was realized as a collection of HTTP Session objects. I am planning to extend the Pushlet framework with these capabilities. For now I have a simple web-chat and what I call WCQ (in Dutch this sounds almost like We Seek You), a simple ICQ-like desktop window where you can monitor the presence of friends.
Other applications in this area include live forums and shared document editing.
This chapter describes the consequences of using Pushlets
As with any mechanism or design pattern there are obvious advantages and disadvantages with Pushlets as compared to Java-based applet solutions that use messaging or client callbacks with CORBA/RMI.
I am further testing the viability of Pushlets. The Pushlet framework is actually a generic Publish/Subscribe pattern with HTTP-based Pushlet clients as a special case. I am evolving the framework with the following extensions
One interesting area is the possibility to call an applet that receives UDP messages from within the Pushlet frame on the client. This would mean that we don't keep the HTTP connection. In general clients will subscribe with a HTTP request on which they indicate through which protocol (TCP, UDP, RMI, HTTP-stream, HTTP POST) they want to receive events and in which format (XML, Java serialized objects,...). Where required the address of the receiver is specified. For example to receive XML formatted stock events through UDP on port 5001:
With UDP a lease time may need to be specified (since the server would never know when the client leaves). If the lease is not renewed after this time the server will drop the client.
Currently events are generated internally or through the Postlet by using the HTTP POST request. Additional protocols such as RMI, TCP and UDP may be applied.
Currently a subject is just an hierarchical string and a client that subscribes gets no history that may have been built up. For example in a chat some discussion may have been going on. In a next version subjects will become first class objects such that when clients subscribe they may implicitly get the current state or may explicitly request the state.
Although some multi-user applications are possible there is no knowledge or management on the server. In earlier versions I have experimented with combining multiple HTTP Sessions into a multi-user HTTP session.
An in-depth look at RMI callbacks (4/20/99); www.javaworld.com/javaworld/javaqa/1999-04/05-rmicallback.html
Java Tip 34: POSTing via Java/ Learn how to POST data to Web servers in Java; www.javaworld.com/javaworld/javatips/jw-javatip34.html/
Java Tip 41: POSTing via Java revisited. Learn how to display the HTML document returned by the Web server; www.javaworld.com/javaworld/javatips/jw-javatip41.htm
Connect to a Java server via HTTP; www.javaworld.com/javaworld/javaqa/1999-12/02-qa-firewall.html
Networking our whiteboard with servlets.; www.javaworld.com/javaworld/jw-01-1998/jw-01-step.html
Subject-oriented programming through RMI (Gerald de Jong); www.javaworld.com/javaworld/jw-08-1998/jw-08-subjectop.html
Jason Hunter's ("Java Servlet Programming", O'Reilly) servlet site.; http://www.servlets.com
Doug Lea - Concurrent Programming in Java - 2nd edition.; www.amazon.com
The Dynamic Duo; Cross-Browser Dynamic HTML; dansteinman.com/dynduo
Scott Isaacs' ("Inside DHTML") community site on DHTML; www.siteExperts.com and www.insideDHTML.com
WebMonkey (Wired Magazine) DHTML zone http://hotwired.lycos.com/webmonkey/collections/dynamic_html.html/?tw=dynamic_html