In Part 1 of this series (JDJ Vol. 6, issue 4) I developed a simple access control mechanism for my application using HTTP authentication and servlets. In my view, servlets have always been underrated as a technology.
Their use has sometimes been limited to replacing traditional CGI scripts for the processing of HTML form submissions. However, the fact that you can send and receive serialized Java objects to and from servlets means they can be combined with applets as part of simple distributed object architecture, competing with RMI, CORBA, and EJB. No tunneling is required, and it works in browsers that don't support RMI.
Despite my enthusiasm for servlets, for some applications the interactivity and graphical capabilities of applets make them invaluable pieces in the jigsaw. I once wrote an applet that displayed aviation flight paths on a globe projection that could be zoomed and rotated about each axis. Try doing that with a servlet!
Although applets have fallen somewhat out of favor, it's possible to write one without regard to whether it will be downloaded to Internet Explorer or Netscape, on Windows or UNIX. I was doing that four years ago, and now with the Java plug-in down to a relatively trim 5MB in version 1.3 and Java WebStart on the way, the promise of true "write once, run anywhere" applets may yet become a reality.
Applet-Servlet Communication with Applet Parameters
To accommodate the first applet within my architecture, I'll first make a change to the LoginServlet. The code for writing out the user's options as HTML links (see April JDJ) will be replaced by code to download an applet with a set of parameters representing the user's options (see Listing 1).
The resulting HTML, containing an applet tag and a set of parameters, looks like this:
<applet code=com.lotontech.applets.
OptionsApplet
height=30, width=600>
<param name=user value=bill>
<param name=option1 value=getTasks>
<param name=option2 value=transferTasks>
</applet>
This passing of parameters to the OptionsApplet represents the simplest possible servlet-to-applet communication mechanism, although I'll cover a more useful alternative later in this article.
The OptionsApplet will now be responsible for displaying the user options menu, with each option presented as an AWT button (see Figure 1) rather than as an HTML link. I know it's not very fashionable to use AWT, but for this series I've decided to concentrate on the Enterprise aspects and leave the GUI advice to someone else.
There are two important points to look for in the OptionsApplet code included in Listing 2. The first is the retrieval of the applet parameters representing the current user's menu options. The second is the technique I have used for launching a new servlet into a browser frame - via the AppletContext - when an option button is clicked.
The AppletContext is the applet's handle on the browser it's running in. By calling the showDocument() method it's possible to fetch and display any HTML document the server can provide. You could replace the current document - which isn't such a good idea if it contains your applet - or display a new document in a separate frame or a new browser window. I'm doing the latter, and when I say displaying a document in this context, I actually mean running a servlet and displaying its response, where the response might contain yet another embedded applet.
This applet is only slightly more impressive than the original HTML links because I've kept it simple to demonstrate the technique. In applying this to any real scenario, I've often used an applet to display a multilevel menu via a Swing JTree that allows users to expand and contract the various levels in a way that can't be achieved easily with HTML alone.
This kind of multilevel menu wouldn't be as easy to specify as a flat series of applet parameters, so the applet-servlet communication channel would need to be enhanced to handle the transmission of more descriptive data. Two methods for transmitting descriptive data spring to mind: XML and Java serialized objects. I'll cover the latter and, rather than tire you with yet another menu variation, I'll find a different use for serialization within my application.
Applet-Servlet Communication with Serialized Objects
When user "bill" clicks on his getTasks button (see Figure 1), he sees a list of the tasks that are assigned to him. When a different user, "ben", clicks that button, he'll see a different list. A sample Task Page for "bill" can be seen in Figure 2.
Once again I'll use an applet and servlet combination, but this time in a slightly different way. When the TaskServlet is invoked via the getTasks button, with no parameters, it serves up an HTML tag to download the TaskApplet to the browser. As soon as the applet is instantiated in the browser, it makes a second call directly to the same servlet. This time the applet specifies a getdata parameter as part of the URL connection string, and expects the servlet to return a vector of serialized objects representing the user's tasks. In Listing 3 take a look at the first highlighted code, which tests the presence of the getdata parameter. You can then follow the alternate behavior that depends on the presence, or absence, of the parameter.
After constructing the two AWT Lists - one for high-priority tasks and one for low - during initialization, the TaskApplet (see Listing 4) reinvokes the TaskServlet by opening an InputStream on its URL, this time with the getdata parameter included in the URL connection string.
Note that when the applet requests the task data from the servlet, there's no need to specify which user's tasks should be returned because the HttpSession object - accessible from any servlet - already holds the user name for the current session, as set by the LoginServlet at the time of authentication. (For more about the Log-
inServlet, please refer to my earlier article.)
The tasks for the current user are returned in the form of a vector of serialized Java objects - in this case simple Strings - that are immediately ready for use as objects in the receiving applet. The contents of the vector don't need to be Strings, and the container doesn't need to be a vector. The only limitation is that any Java objects transmitted in this way must be serializable, which for your own objects means that their class(es) must implement java.io.Serializable. For Java runtime classes it means that you can't transmit things like JDBC connection objects.
Thus an applet/servlet combination allows a style of distributed object programming that in my opinion is much underused.
Conclusion
This check-in/checkout style of object programming using servlets and serialized objects isn't suitable for every situation. Many applications are more suited to the RMI/CORBA model, in which objects are passed between distributed clients and servers by reference rather than by value (serialized), and remain at all times at their point of origination. The issues to consider include performance (references are smaller than objects in transmission) and consistency (a remotely referenced server-side object appears in the same state to all its clients).
However, my preferred technique is easy to understand, doesn't suffer from tunneling issues (since you're using HTTP anyway), and may just be worth a try before you consider something more complex.
On the subject of complexity, no Enterprise Java series would be complete without the appearance of Enterprise JavaBeans. My next article will introduce the simplest possible EJB architecture - consisting of a lone session bean - and will suggest (but not recommend) how this bean's functionality could instead be provided by a more complex combination of session beans, entity beans, and distributed transactions.
|