![]() ![]() ![]() |
|
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
Articles
Index
What's New in Java Servlet API 2.2?By Jason Hunter; Reprinted from JavaWorld(October 1999)On August 23, Sun Microsystems published the first public release of the specification for JavaTM Servlet API 2.2 (see the Resources section below for a link to the formal specification). Included in the specification are some very exciting enhancements to servlets. This article describes what's new in version 2.2 of the API, explains the decision-making process behind the changes, and demonstrates how to write servlets using API 2.2 features. To keep the article somewhere near a reasonable length, I'm going to assume that you're familiar with the classes and methods of previous versions of the Java Servlet API. If that's not the case, you can peruse Resources for links to sites that will help get you up to speed. Java Servlet API 2.2 includes many enhancements that make servlets more powerful than ever:
Java 2 Platform, Enterprise EditionOne of the first things one notices when reading the Java Servlet API 2.2 specification is that the term servlet engine has been replaced by servlet container. This minor change is indicative of a larger one: the Java Servlet API is now a required API of the Java 2 Platform, Enterprise Edition (J2EE) specification and, throughout J2EE's terminology, container is preferred over engine. The addition of servlets to J2EE has no real effect on pure servlet developers (except for the fact that we have to stop saying "engine"). But it does guarantee that enterprise developers using J2EE will always have support for servlets. (Lucky developers!)Web ApplicationsJava Servlet API 2.2 includes one new feature so significant it may change the way the Web works. That feature: Web applications. A Web application, as defined in the servlet specification, is a collection of servlets, JavaServer Pages (JSPs), HTML documents, images, and other Web resources that are set up in such a way as to be portably deployed across any servlet-enabled Web server. Installing a Web application is simple. Gone are the days of detailed instruction sheets telling you how to install third-party Web components, with different instructions for each type of Web server. With Web apps, the entire application can be contained in a single archive file and deployed by placing the file into a specific directory.War: What's it Good for?Web application archive files have the extension.war , which stands
for Web application archive. War files are actually jar files
(created using the jar utility) saved with an alternate extension.
Using the jar format allows jar files to be stored in compressed form and have
their contents digitally signed. The .war file extension was
chosen over .jar to let people and tools know to treat them
differently.
Inside a war file you might find a file listing like this: index.html howto.jsp feedback.jsp images/banner.gif images/jumping.gif WEB-INF/web.xml WEB-INF/lib/jspbean.jar WEB-INF/classes/MyServlet.class WEB-INF/classes/com/mycorp/frontend/ CorpServlet.class WEB-INF/classes/com/mycorp/frontend/ SupportClass.classOn install, a war file can be mapped to any URI prefix path on the server. The war file then handles all requests beginning with that prefix. For example, if the war file above were installed under the prefix /demo , the
server would use it to handle all requests beginning with /demo . A
request for /demo/index.html would serve the
index.html file from the war file. A request for
/demo/howto.jsp or /demo/images/banner.gif would also
serve content from the war file.
About the WEB-INF DirectoryTheWEB-INF directory is special. The files there are not served
directly to the client; instead, they contain Java classes and configuration
information for the Web app. The directory behaves like a jar file's
META-INF directory; it contains metainformation about the archive
contents.
The
The servlets under
The
web.xml file can be found in the Resources section. A full description of all the elements
in the DTD would extend this article beyond a reasonable length, and may be of
little interest in the long run, as these files are likely to be generated by
graphical tools; thus, I will not describe the elements here.
The structure of the As Java Servlet API 2.2 gains in popularity, it's likely that a commercial market for war files will develop. War files will become pluggable Web components, capable of being downloaded and installed and put to work right away -- no matter what your operating system or Web server. $19.95 for a site search engine, anyone? Deployment descriptors also provide Web-hosting companies with a convenient way to support multiple customers on the same server. Customers can be given control over their individual domains. They can individually manage servlet registration, URL mappings, MIME types, and page-level security constraints -- without needing general access to the Web server. Now let's take a look at how Web apps are implemented. Web Applications: A Programmer's ViewFrom a programmer's point of view, a Web application corresponds to oneServletContext object. All servlets inside a Web application share
the same ServletContext instance. All Web servers have at least
one context, called the default context. It handles requests whose URI
paths match no other context prefix. (So, for example, it would handle
requests for /index.html or /images/tile.gif .)
Parameter information for the Web application (specified in the deployment
descriptor) is available using two new methods in
A servlet can determine the URI prefix of the context in which it's
running using the new
When using the context object to request resources, it's important
to remember not to include the context path in the request.
After all, the context knows its own path, and by not specifying
the path in code, you ensure that the application can be moved to a different
path
prefix without recompiling. For example, when getting a
The following servlet public void doGet( HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException { res.setContentType("text/plain"); PrintWriter out = res.getWriter(); out.println("My context path is: " + req.getContextPath()); ServletContext context = getServletContext(); out.println("My context instance is: " + context); out.println("My context parameters are:"); Enumeration e = context.getInitParameterNames(); while (e.hasMoreElements()) { String name = (String) e.nextElement(); Object value = context.getAttribute( name); out.println(name + ": " + value); } // Now let's dispatch RequestDispatcher dispatcher = context.getRequestDispatcher( "/servlet/BuyNow"); dispatcher.include(req, res); }This code first prints the current context path, the context reference, the init parameters, and finally includes
output from the BuyNow servlet.
Lifecycle ClarificationsSome additional clarifications have been made in the Java Servlet API 2.2 specification pertaining to Web apps and the servlet lifecycle.
It's now defined that, for servlets that don't implement
It's also defined that Web servers must guarantee that servlets
sharing information via user sessions or servlet contexts must not
experience unexpected Distributed ApplicationsA few clarifications were also made in 2.2 with regards to distributed applications, in which application components can be spread across multiple back-end server machines.
The specification dictates that, for an application marked as distributable in
its deployment descriptor, there will be a single
An application marked as distributable also has special rules for user
sessions. Servers will use session affinity to efficiently
manage user state across multiple back-end servers. This means that all
requests that are part of a single session from a particular user
are to be handled by only one JVM at a time. This in turn eliminates
the need to constantly replicate session information across all the
back-end servers. Responsibility for the session can be moved to
another server between user requests, though in practical terms this
is unlikely to occur frequently. Still, to enable the moving of a
session, all objects placed into a session by servlets in a
distributed application must implement Response BufferingOne of the most useful features added in version 2.2 of the servlet API is response buffering. A servlet now has control over whether the server buffers its response, and may dictate how large a buffer the server can use.In previous versions of the API, most Web servers implemented response buffering as a way to improve performance. Exactly how large that buffer was depended on the server. Generally, servers had buffers in the neighborhood of 8 KB. The important change for 2.2 is that a servlet now can specify a minimum buffer size for its output. This improves the flexibility of servlet error handling. How does this work? Well, the structure of HTTP dictates that the first line of an HTTP response includes a status code indicating the success or failure of the client request. To be sure to correctly set the status code, servlets have had to do full error checking before generating any output. If an error was encountered halfway through the response, it was just too bad. The response was already sent (or committed) and the status code and headers could not be changed. A response buffer allows a servlet to write some amount of output with a guarantee that the response won't be immediately committed. If the servlet finds an error, the status code and headers can still be changed so long as the buffer has not been flushed. Five New MethodsFive methods were added toServletResponse in order to support
response buffering:
public void doGet( HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException { // 16K buffer res.setBufferSize(16 * 1024); res.setContentType("text/html"); PrintWriter out = res.getWriter(); // returns 16384 or greater int size = res.getBufferSize(); out.println("The client won't see this"); res.reset(); out.println("Nor will the client see this!"); res.reset(); out.println("And this won't be seen if sendError( ) is called"); if (req.getParameter(" important_parameter") == null) { res.sendError( res.SC_BAD_REQUEST, "important_parameter needed"); } }This servlet sets the buffer to 16 KB, then checks the buffer size. The returned size should be 16 KB or greater. Then the servlet tests out the reset() method by calling it both directly and via
sendError() .
Support for double headersIn the new version of the API, servlets have the ability to retrieve more information than ever before, and send a little more as well. There's a new method inHttpServletRequest called
getHeaders() that can return multiple values for a
given header. This was needed because some headers, such as
Accept-Language , can send multiple header values:
Accept-Language: en Accept-Language: fr Accept-Language: jaPreviously, servlets using getHeader() could retrieve
only one value per header. With the new version of getHeaders() , a
servlet
can retrieve multiple values as an enumeration of
string objects.
Servlets have also been given the ability to send multiple values
for the same response header using methods in
Now this is just temporaryAnother new piece of information was made available in 2.2, but this change didn't require a new method.
The context object now contains a new standard attribute --
available using The following code shows how to write to a temp file in the temporary directory. public void doGet( HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException { // The directory is given //as a File object File dir = (File) getServletContext() .getAttribute( "javax.servlet.context.tempdir"); // Construct a temp file in the temp //dir (JDK 1.2 method) File f = File.createTempFile( "xxx", ".tmp", dir); // Prepare to write to the file FileOutputStream fout = new FileOutputStream(f); // ... }First, this servlet locates its temporary directory. Then, it uses the createTempFile() method to create a temporary file
in that directory with an xxx prefix and .tmp
suffix. Finally it constructs a FileOutputStream to
write to the temporary file.
No More AmnesiaThe last bit of new information available to a servlet is the servlet's own name. In theServletConfig interface
(which GenericServlet implements) there's a new method,
getServletName() , that returns the servlet's registered
name. If the servlet is unregistered, the method returns the
servlet's class name. This method proves useful when logging and
storing a servlet instance's state information into such resources
as databases or servlet contexts.
As an example, the following code demonstrates how to use the servlet's name to retrieve a value from the servlet context, using the name as part of the lookup key. public void doGet( HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException { // inherited from GenericServlet String name = getServletName(); ServletContext context = getServletContext(); Object value = context.getAttribute( name + ".state"); } So, Where are You from?Internationalization has become an important topic on the Web, and the new version of the API includes some enhancements that simplify the challenge of dealing with clients from multiple locales.
With Java Servlet API 2.2, a servlet can determine the preferred locale of the
client
using a few new convenience methods. public void doGet( HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException { res.setContentType("text/html"); Locale locale = req.getLocale(); res.setLocale(locale); PrintWriter out = res.getWriter(); // Write output based on //locale.getLanguage() }Note that these methods aren't as powerful as the com.oreilly.servlet.LocaleNegotiator class (available
in the Resources section).
Hark, Who Goes There?Before Java Servlet API 2.2, servlets had very little control over server security. Page access restrictions were set up using server administration tools, and all a servlet could do was view the remote user's basic authentication login name by callingreq.getRemoteUser() . Now, however, servlets have slick
built-in support for portable role-based user authentication and
authorization.
Using tags in the Web application deployment descriptor, security constraints can be set up to indicate that certain pages in the Web app are to be accessed only by users with certain credentials. Specifically, since this is role-based user authorization, access will only be granted to users who are part of a given role. For example, you might want to set up your site so that pages that display salary information can be restricted to only those users who are in a manager role. The deployment descriptor specifies the type of access granted to each role, but does not specify that role to user or group mapping. That's done during deployment of the Web app, using server-specific tools. The ultimate mapping may come from many locations -- the Web server, the operating system, a relational database, and so on.
Two new methods were introduced in
The final new security method in Here's a code snippet showing the new methods in action: public void doGet( HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException { res.setContentType("text/plain"); PrintWriter out = res.getWriter(); out.println("The current user is: " + req.getUserPrincipal()); out.println("Is the user a Manager? " + req.isUserInRole("Manager")); out.println("Is our connection secure? " + req.isSecure()); } Nit-picky on ParametersIf you look closely at the specification, you'll see that a much-needed clarification was made on how parameters are handled in API 2.2.
It's now guaranteed that parameters specified in the query string of
a post request will be read and made available to servlets.
Furthermore, in the event that any query string parameter names collide
with post parameter names, the query string values are to be made
available first via <FORM METHOD="POST" ACTION="/servlet/Testing?a=b">This clarification also allows a special query string parameter to be used for session tracking and passed even during post requests. Better dispatchingFinally, Java Servlet API 2.2 provides more convenient request dispatching.
There's a new
There's also a new
Lastly, the ConclusionAs described in this article, Java Servlet API 2.2 includes many enhancements designed to make servlets part of a complete Web application framework. Whole subsections of Web sites will be able to be configured and deployed to any Web server that supports API 2.2. Servlets can also be distributed across multiple back-end servers, or can indicate via their deployment descriptor that they'd rather stick to one machine. Response buffering has been added to make error handling more robust, HTTP header control has been improved, and request dispatching has been made easier with support for relative paths and named dispatchers.All in all, there are 29 new methods, 2 new constants, and just 6 deprecated methods. For a cheat sheet on moving from 2.1 to 2.2, see the sidebar. 2.1 to 2.2 cheat sheet
RESOURCES:A site dedicated to helping you learn about, develop, and use servlets: Servlets.comThat site accompanies my book, Java Servlet Programming (O'Reilly, 1998) Official home site for servlets Official documentation for Java Servlet API 2.1 A comprehensive list of servlet resources Information on the Java 2 Platform, Enterprise Edition Project Jakarta, the open source servlet reference implementation.
Home page for "Introducing the new Servlet API 2.1," Jason Hunter (JavaWorld, (December 1998) -- describes differences between Java Servlet API 2.0 and 2.1: JavaWorld Servlet API BrowserHawk4J, a commercial product I'm proud to have worked on.
Reprinted with permission from the September 1999 edition of JavaWorld magazine. Copyright Web Publishing Inc., an IDG Communications company. Regis ter for editorial e-mailalerts
About the AuthorJason Hunter is the Chief Technology Officer of K&A Software, where he specializes in Java training and consulting. He is author of Java Servlet Programming, and publisher of Servlets.com. He belongs to the working group responsible for Java Servlet API development (his fingerprints are all over the 2.2 specification and reference implementation). If you don't find him at work, he's probably out hiking in the mountains. Reader FeedbackTell us what you think of this article.
|