Chapter 10. Groupware Servlets

In Part I and Part II we saw how the core Internet client applications—mail, news, and web—can singly and in combination enable a group to create, share, catalog, and find documents that form the basis of collaborative work. Here in Part III, we’ve begun to explore ways to extend the core services, using the Web’s CGI and namespace APIs and the NNTP API to create customized groupware. We’ll do more of this in later chapters, because the core Internet services—and in particular, web servers—are amazingly versatile components. But conventional web servers are really just specialized file servers that have been outfitted with a mechanism—the CGI gateway—to launch external programs. In this chapter we’ll focus on an alternative mechanism that’s more naturally attuned to the delivery of network services. Java servlets present the same kinds of web APIs as do conventional CGI scripts. They’re inherently fast, reliable, lightweight, and threaded, and they can capably manage the kinds of complex data structures that groupware services typically involve. For all these reasons, servlets belong in every groupware developer’s toolkit.

We’ll look at two groupware servlets: Polls and GroupCal. Polls, which we saw briefly in Chapter 4, is a URL-driven survey tool that you can use to quantify the sense of a group regarding some question or issue. GroupCal is a shared bulletin board that presents free-form data in a calendar format. Writing these two servlets convinced me that Java’s best use, at least for now, is server side, not client side. The current buzz surrounding Java application servers such as Sun’s NetDynamics ( and IBM’s WebSphere ( supports that view. So before we look at some simple ways to deliver servlet-based groupware, let’s consider why Java is so effective in this role.

Why Server-Side Java Matters

If you search for calendar software in the utilities area of URLs: and similar sites, you’ll find lots of Java applets that create graphical displays of calendar data. From this perspective, the user interface of my GroupCal servlet, which is just dynamically generated HTML and a smidgen of JavaScript, seems primitive. It’s nothing like the GUI applications and components that Java can create. But is that the best use of Java?

The Web has created a universal standard client—namely, the HTML/JavaScript browser. It’s fashionable to sneer at the humble browser, but it remains the workhorse of the Web. The network services that matter—ordering books, reserving airline tickets, tracking packages—are delivered using HTML, not applets. And for good reason. When Southwest Airlines sells you a ticket, it doesn’t want to have to ask you to upgrade your browser or wait for a downloadable component. It just wants to send you an electronic form that will work well enough in any browser, over any kind of network connection. The Web’s basic client/server mechanism isn’t broken and never really needed a client-side-Java fix. Innovative, high-quality graphical user interfaces certainly do matter. But Dynamic HyperText Markup Language (DHTML) may prove to be a more practical means to that end than Java.

Java’s early emergence as a browser-based portable GUI was a red herring. The job that Java is best qualified for isn’t to reinvent the browser, but rather to feed it more of the kinds of services that it is already well positioned to consume. If you view Java as a toolkit for the construction of network services, its features appear in a very different light than if you view Java as a way to deploy portable and graphical client-side applications. The following are some of the reasons Java is attractive for server-side use.

Safe Memory

Buffer overruns create a whole class of pernicious Internet security holes. An oddly constructed email message, for example, may cause a certain Internet Message Access Protocol (IMAP) server to overflow a statically allocated buffer, which in turn can enable an attacker to gain control of that host. Recognizing the danger, thoughtful developers work hard to combat it. The Apache Group, for example, has devoted much effort to ensure that the Apache web server’s data structures grow dynamically and won’t cause buffer overruns. You can of course implement safe memory in C or C++, but it requires great diligence and above-average skill. In Java, safe memory is just an aspect of the language. You don’t have to do anything special to take advantage of it.

As network services proliferate, the number of programmers involved in creating them will grow. Not all of these programmers will be able to write memory-safe C or C++ programs. Java can help offset the security risks that come with new network services. What about Visual Basic? It’s true that VB programs are memory-safe. But VB alone is not very useful. As a provider of network services, it relies heavily on packaged components written, for the most part, in C++. The memory safety of these components will vary according to the skills and inclinations of the programmers who build them.

Simple and Portable Multithreading

Network services need to handle lots of concurrent requests and respond quickly to all of them. Multithreaded software isn’t the whole answer to this problem, but it’s a key ingredient of many solutions. Java’s thread model is simple and accessible. Again this means that a new wave of developers will be able to exploit a capability that was formerly available only to a more elite group. The tricky problem of thread synchronization, for example, becomes very simple in Java, as we’ll see in this chapter.

The portability of multithreaded Java software plays an important role here too. The platform on which network services run needn’t be a monolithic superserver. Web APIs can stitch together a cluster of commodity servers. That cluster can be compact, tightly coupled, and homogeneous, or it can be far-flung, loosely coupled, and diverse. Either way, Java’s portable multithreading can help you build responsive network services.

Network Awareness

Java’s Remote Method Invocation (RMI) provides an elegant way to build distributed software. RMI was invented because JavaSoft saw a need for a simple, lightweight alternative to object request broker (ORB) technologies such as the Object Management Group’s common object request broker architecture (CORBA) and Microsoft’s distributed component object model (DCOM). With CORBA and DCOM, building a distributed version of even the simplest “Hello, world” program is—without specialized tools—a daunting exercise. In an all-Java environment, RMI can simplify this chore.

But even RMI can be overkill. The applications that inhabit the Internet groupware environment are, after all, just good old-fashioned socket clients and socket servers. Java has excellent facilities for interacting with, and implementing, socket-oriented applications. And its URL classes, and, make it very easy for Java clients to use HTTP-based services. We’ll see later in this chapter how it might make sense for a servlet, which is a provider of HTTP-based services, to also be a consumer of other HTTP-based services.

Java Object Storage

When we use web technology to connect server applications to data, we tend to think in terms of SQL databases and relational data. Java servlets can do that, using the Java Database Connectivity ( JDBC) APIs, just as Perl or other kinds of CGI scripts can, using various kinds of SQL adaptors. But servlets can also manage object data. How? Using serialization, a Java program can write in-memory Java objects to disk storage and reconstitute those objects when reading them back into memory. JavaSoft introduced serialization in Version 1.1 of the Java Development Kit (JDK) to support RMI, which required the ability to send serialized objects over network connections. But you can also serialize Java objects to files, and that means you can create and use very simple object databases.

The servlets we’ll explore in this chapter do just that. They are both, in essence, just web APIs to in-memory Java objects that are made persistent using serialization. These objects aren’t constrained by SQL’s tabular row-and-column format. Like Perl, Java has hashtables and lists, and can combine these to make arbitrarily complex structures—such as the hashes-of-hashes-of-lists (HoHoLs) or lists-of-hashes (LoHs) that we found to be so useful in earlier chapters. Groupware needs these kinds of data structures because it has to model what people really do, and that’s messy. Relationships among people, tasks, events, and resources are complex and fluid. Forcing these organic structures into the Procrustean bed of normalized relational tables can be a painful and unproductive exercise. Object storage can model webs of relationships much more directly than SQL databases can.

The basic object persistence exploited by Polls and GroupCal isn’t an exclusive capability of Java. Perl CGI scripts using modules such as Data::Dumper can achieve similar results. But Java currently offers a better upgrade path to real object database technology. Why would you need that? There’s a limit to the amount of object storage that you can manage in memory and serialize en masse to disk. An object database, such as ObjectDesign’s ObjectStore ( or POET Software’s POET (, creates a kind of object cache, mapping between in-memory structures and disk storage as needed. You don’t need to change your Java code to gain this benefit, because these products can work transparently with your existing hashtables (java.util.Hashtable objects) and lists (java.util.Vector objects). They also provide transaction controls and search capabilities.

Groupware needs object storage. Java servlets can manage simple object stores. And because object database vendors are creating Java bindings to their products, servlets can be easily (sometimes transparently) upgraded to industrial-strength object storage.

Servlet Efficiency

A servlet runs in the context of a host that may be a conventional web server, a Java-based web server, or a Java-based application server. In all these cases, the host keeps a Java virtual machine always running, with servlets loaded and ready to respond to requests. To achieve this effect with scripting languages such as Perl or Python, you need special and server-specific adaptations of these languages. mod_ perl ( binds Perl into the Apache web server and caches Perl code so that scripts run with almost no startup delay. mod_ python does the same thing for Python under Apache. ISAPI Perl and PerlEx ( likewise adapt Win32 Perl for low-latency invocation under the control of Win32 web servers such as Microsoft’s IIS.

The servlet programming model is attractive because it’s a standard way to do what these various script-engine adaptors achieve by very different means. mod_ perl, for example, is a powerful technology that I use and recommend. But it’s a discipline unto itself, with a learning curve that even seasoned Perl CGI programmers must climb. Because of the way mod_ perl embeds Perl in Apache, for example, you have to be very careful not to contaminate the Perl global namespace visible to all instances of the Apache daemon. In the servlet realm, servlets are more effectively isolated from one another, because a servlet’s scope ends at its package boundary and because each servlet runs on its own separate thread of execution. And once you learn this drill, it’s pretty much the same from one servlet host to the next. Servlets mostly keep the “write once, run anywhere” promise.

How much does this thread-based dispatching enhance the efficiency of servlets? That depends on several things. A Java implementation for Solaris or Win32, where Java threads can map directly to native operating system threads, may run threaded servlets more efficiently than a Java implementation for a version of Unix that has to provide its own pseudothread mechanism. However, it’s not clear that the native-thread approach always wins out over the pseudothread approach. In either case, another key factor is the load placed on the servlet host. The thread-per-request model works pretty well, but it isn’t infinitely scalable.

At very high levels of traffic, the overhead required to create a thread for each request becomes a real burden. That situation calls for a thread-pool model in which the server manages a fixed-size pool of request-handling threads. Should you worry? Not unless you plan to deploy servlets on a very busy public server. On an intranet server that handles hundreds of requests per day, or even on an Internet server that handles thousands, the thread-per-request model is good enough.

Java performance

Java servlets don’t raise the same concerns about Java performance as do Java applets and GUI applications. I ran GroupCal in the standard JDK virtual machine (VM) for several years; its performance was never an issue. Servlets persist, so they don’t suffer from the download-and-activate lag that plagues Java applets. Nor do servlets have to push through layers of Java GUI code in order then to push through more layers of native operating system GUI code. Servlets operate behind the scenes, using network- and data-access procotols, providing network-based services that interact with other services and with browsers. In this middleware environment, the performance of interpreted Java looks pretty good.

Even though the performance of unassisted Java may be acceptable for your servlet, faster is always better. When I compiled GroupCal to a native Win32 binary, using Asymetrix’s SuperCede compiler, the resulting servlet was indeed noticeably faster, especially for calendar searches. SuperCede was acquired in early 1999 by Instantiations ( and, sadly, discontinued. Although other native-code Java compilers are available, including Instantiations’ JOVE and Tower Technology’s TowerJ (, these are high-end commercial products beyond the reach of most intranet groupware developers. The techniques that SuperCede pioneered will, let’s hope, emerge in more affordable commercial products or in open-source products.

The native-code approach is vastly more convenient for a servlet than for an applet. The SuperCede product bound the native-code programs that it compiled to a special Java VM. It’s no problem to run a specialized VM on a server. Browsers don’t know or care; they only consume services provided by the servlets running in that VM. For client-side Java, the story is very different. A client that wants to run a native-code applet must first acquire its supporting VM. This requirement largely negates the zero-footprint benefit of client-side Java.

Flexible Servlet-Hosting Options

Pure Java-based web servers are one way to host servlets. Sun’s Java Web Server (JWS,, a commercial product, was the first servlet host I used. Open-source Java Web servers include Jetty (, Jigsaw (, and Acme.Serve (

You can also host servlets using conventional web servers. Sun’s Java Servlet Development Kit (JSDK) includes an adaptor that enables the Netscape, Microsoft, and Apache web servers to host servlets. (The JSDK also comes with servletrunner , a stripped-down servlet host that you can use to exercise servlets in a standalone fashion.) A free adaptor for Netscape’s web servers is Gefion Software’s WAICoolRunner ( Commercial adaptors for various web servers are available from Live Software (JRun,, and other vendors. O’Reilly & Associates’ WebSite Pro includes servlet support.

Should you use a Java-based web server or a conventional web server to host servlets? That depends on what kind of web server you prefer. Sun’s JWS, for example, is a full-featured web server. It has a complete authentication model that can restrict access to URLs based on user and group permissions; it comes with a GUI administration and monitoring tool that runs as a Java applet; it can establish SSL-secured sessions with browsers. JWS is a fine general-purpose web server. But, if like many people, you’re already committed to Apache, IIS, or another conventional web server, you don’t need to switch to JWS or another Java web server just to host servlets. Servlet-hosting adaptors enable you to leverage what you already have while adding servlets to the arsenal of tools that you can use to create groupware applications.

A servlet host can also be a pure application server. For example, I like to run servlets under the control of Acme.Serve, because it’s so easy to control the services provided by this small and simple Java web server. Its file-serving capability is just another servlet, which you can easily disable. In that configuration Acme.Serve responds only to the URLs handled by the servlets you attach to it. Contrast this with JWS, which, because it’s a full-fledged web server that installs all sorts of default behaviors, creates a whole new set of potential security risks that need to be analyzed and doors that need to be locked.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.