|
The ever-popular servlet cleanly and simply develops and deploys Web-based applications. However, although the Java platform is independent, the Web as a whole is not. The language and the servlet API do not provide such niceties as optional session-persistence schemas (that is, store in memory, in a database, or in a cookie), and they don't easily accommodate ad hoc solutions to shortcomings in cookie handling. To handle such issues, Thomas Davis and Craig Walker have developed an unobtrusive framework, an invisible layer between your servlets and the servlet engine, that gives you greater control over the environment. The ubiquitous servlet flourishes in all areas of Web development. Authors devote entire books to servlets. Almost every major Web server and application server supports them, if not directly, then through a plethora of third-party plug-ins. An integral part of the Java 2 Platform, Enterprise Edition (J2EE) framework, they provide the foundation for JavaServer Pages. If you are a Java fanatic, and your project has a Web interface, you use servlets.
Servlets are a simple concept, and the Java Servlet API reflects
that. As Figure 1 illustrates, a
Sun's Java Servlet API does an excellent job of hiding all the dirty work from the programmer, leaving the servlet engine to manage it instead. However, the programmer occasionally needs to peek behind the curtain and twiddle the knobs. Sometimes the programmer wants to override the engine's functionality. This series will cover these issues. Over the next few months, we will explain how you can take control of your servlet environment. We will also exploit that control and demonstrate some useful real-world tricks that can increase the performance and scalability of your projects. Most servlet engines store the user's session data in memory. This prevents you from implementing a truly load-balanced farm of Web servers because each visitor must be sticky to the server that assigned him or her a session. Once a load-balancing mechanism directs a visitor to a specific server, it keeps sending that visitor back to the same server; thus, the visitor becomes stuck to a single server, rather than being rotated or balanced across all servers. To solve this problem, do you need to migrate to another servlet engine vendor or purchase a third-party solution? Absolutely not. We'll explain why in this series. Have you ever run into the cookie subdomain bug? For example, if you access a cookie-writing page at http://drum.rudiment.net/ then hit the same page using the address http://www.drum.rudiment.net/, you will have two cookies with the exact same name. When you return to http://drum.rudiment.net/ and the page requests the cookie that it originally wrote, it's a toss-up as to which version the engine will return. We will crack that problem as well in this series of articles. In Part 1, we will introduce the foundation for inserting an invisible layer of logic between the servlet engine and your servlet code. This layer will use simple and common design patterns and open the doors to many clever and powerful enhancements. Even though Java is a young language, it already features numerous legacy issues. To avoid confusion, we must point out that the code discussed in these articles was written for, and compiled and tested with, the following API versions:
WrappersThe secret to taking control of the servlet environment is to wrap the API. Essentially, you build an invisible wall between your servlets and the servlet engine. Because it exposes (or implements) the same API, the wrapper is invisible to the servlet and the engine. For the purposes of this article, we will refer to the set of wrapper classes as RSEF (the rudimental servlet extension framework). This title has little meaning other than the fact that the package structure contains the word rudiment. Mainly, the acronym will eliminate the need for us to compose clever pronouns each time we refer to the framework.
From the programmer's point of view, RSEF is virtually transparent. The only
RSEF-specific class that the programmer must know about is
Normally, your servlet would extend the
Under the Covers
Once in place, the RSEF can work its magic. The first and fundamental task
of RSEF is to wrap the core servlet objects. As stated above, the core
objects are the
Erich Gamma, Richard Helm, Ralph Johnson, John Vlissides (the so-called Gang of Four),
in their book Design Patterns (see Resources),
define this behavior as the Decorator pattern. Their definition of the this pattern
reads, "Attach additional responsibilities to an object dynamically." The Decorator
pattern derives its strength by aggregating the target object (dynamic) rather than
inheriting (static). When your servlet interacts with a In some cases, the wrapper classes also act as a Proxy. A Proxy pattern "provide[s] a surrogate ... for another object to control access to it," according to the Gang of Four. You'll see this demonstrated in future installments of this series. To see how a similar problem is tackled with the Adapter pattern, see the recent JavaWorld article entitled "Use Microsoft's Internet Information Server as a Java Servlet Engine" (direct link available in Resources).
As you can see from Figure 3, wrapping Put it all Together
In order to pull off some of the tricks we will discuss in future articles,
each wrapper has to talk to its brethren. The
This hodgepodge of relationships creates a rather nasty order-of-operations problem.
The
For example, say you want to use the
If you know which
If, on the other hand, you are unsure about which combination you wish to
use and whether that mapping will be applied globally to the product, then
you need to control the mappings at runtime. But how? One alternative is
to use flags: simple static final values that trigger a
The wonderful Gang of Four comes to our aid again. The pattern we need
this time is the Factory Method. As defined in Design Patterns,
the Factory Method is "...an interface for creating an object ... [that]
lets the class defer instantiation to the subclass." In English: rather than
telling the
The black box is a factory. Factories simply produce objects, usually of a
single specific type but with a generic interface. Just as a toy factory produces
toys, a The CodeBy now you might be thoroughly confused, so let's jump straight into the code. The code below illustrates the wrappers' constructor signatures:
The Why such a convoluted train wreck of relationships? You'll discover the answer in future articles. For now, simply understand that for each wrapper to perform its tricks, it needs handles to its brethren wrappers, and, in some cases, the raw counterparts. The Factory Explained
Now, why does our code need a
Here's the
This interface features only one little method, a method responsible for instantiating
the desired Bootstrap the Framework
With all the pieces in place, we can now analyze the assembled puzzle. The RSEF
Aha! What are those two abstract methods doing there? This framework isn't so invisible after all, now, is it? To answer the question, let's take the sandwich analogy a little further. If the servlet engine represents one slice of bread and your servlet the other slice, then RSEF signifies the meat in the middle. Wouldn't that sandwich taste a whole lot better with a slice of cheese? That slice of cheese is your bootstrap layer, where you define the wrapper combinations that you wish to use.
The two abstract methods in the RSEF version of
The The framework is now in place. You've configured your bootstrap. Your last step is to extend the bootstrap servlet instead of the RSEF version, like so:
And you're ready to go! It couldn't possibly be simpler ... or could it? Stay tuned to find out! ConclusionThe framework we introduced here will open the doors to a multitude of performance and scalability enhancements -- completely transparent to your existing servlet-based project. In the next installment, we will discuss session management and touch on database storage. Part 3 will focus on the cookie-domain bug. Then you will begin to see the real power of RSEF. Resources
Books
About the AuthorsThomas E. Davis is a Sun-certified Java developer and the chief technology officer of his second successful Internet-related company. In addition to being a Java advocate, Thomas is a strong proponent of the extreme programming, design patterns, and refactoring philosophies, which he preaches to his colleagues and supports within his own department. Thomas welcomes constructive criticism and intelligent comments on his articles. Craig Walker is a Sun-certified Java programmer (awaiting the results of his developer exam) and senior software engineer. A former consultant for IBM who worked on that company's internal Java initiatives, Craig has pursued the mastery of many Java APIs ranging from the presentation layer to the enterprise and everything in between.
Reprinted with permission from the November 2000 edition of JavaWorld magazine. Copyright ITworld.com, Inc., an IDG Communications company. Register for editorial e-mail alerts. | ||||||||||||
|
| ||||||||||||