Introducing the new Servlet API 2.1

A complete description of what's changed since 2.0

1 2 Page 2
Page 2 of 2

The following code shows how a servlet can include content from another component.

// Show an item in an online catalog
out.println("Feast your eyes on this beauty:");
RequestDispatcher dispatcher = getServletContext()
  .getRequestDispatcher("/servlet/CatalogDisplay?item=156592391X");
dispatcher.include(req, res);
out.println("And, since I like you, it's 20% off!");

A servlet can pass information to the delegate using a query string as shown above, or it can put "attributes" in the request using ServletRequest's new setAttribute(String name, Object object) method. For example,

// Show an item in an online catalog
RequestDispatcher dispatcher = getServletContext()
  .getRequestDispatcher("/servlet/CatalogDisplay");
out.println("Feast your eyes on this beauty:");
req.setAttribute("item", new Book("156592391X"));
dispatcher.include(req, res);
out.println("Or how about this one:");
req.setAttribute("item", new Book("0395282659"));
dispatcher.include(req, res);
out.println("And, since I like you, it's 20% off!");

CatalogDisplay can receive the "item" request attribute by calling req.getAttribute("item"), or it can receive the names of all the request attributes using req.getAttributeNames(). Using attributes instead of parameters gives you the ability to pass objects instead of simple strings.

Shared attributes

To further help servlets cooperate on tasks, the Servlet API 2.1 includes a new method for servlets to share information. Previously, it was possible for servlets to share information, but they had to use homegrown mechanisms like a Singleton object or shared files. In 2.1, servlets have been given the ability to share information by setting and getting attributes in their ServletContext.

Several methods have been added to ServletContext to support the setting and getting of attributes. There's setAttribute(String name, Object object), which sets an attribute. Another method is Object getAttribute(String name), which gets an attribute, and a third is EnumerationgetAttributeNames(), which gets a list of attribute names. (Actually, the getAttribute() method has existed since Servlet API 1.0, but until now it could only read attributes hard coded into the server.) Finally, there's removeAttribute(String name), which removes an attribute.

Using these methods, a servlet can easily share information with any other servlets that live in its ServletContext. This functionality helps tremendously when load balancing, because servlets may find themselves spread across a number of back-end servers, making it especially challenging for servlets to use a homegrown mechanism to share information.

How servlets are divided into ServletContext groups depends on the server configuration. Historically, Web servers have put all servlets in the same context. However, now that each context has a "shared state," it's likely servers will begin to segment servlets into individual contexts, with each context thought of as a single "Web application."

To support communication between contexts, there's a new method, ServletContext.getContext(String uripath). This method returns the ServletContext for the given URI, subject to security constraints. You can use this method to share information with server components outside your context.

Resource abstraction

Another new feature in Servlet API 2.1 is resource abstraction, which allows servlets to access a resource without knowing where the resource resides. This abstraction makes servlets into mobile objects that can be moved between servers -- a useful ability when load balancing.

In 2.1, all resources are abstracted into URLs on the server.

Getting an abstract resource

A servlet gains access to an abstract resource using ServletContext.getResource(String uripath). This method returns a URL that can be used to investigate the specified resource and read its content. How the URI path parameter maps to an actual resource (file, database entry, or other) is determined by the Web server. The one restriction is that the URI should not be an active resource (servlet, CGI program, and so on). For active resources you should use a RequestDispatcher.

To demonstrate how to read from an abstract resource, the following code fetches and prints the server's /includes/header.html file:

URL url = getServletContext().getResource("/includes/header.html");
out.println(url.getContent());

The header.html file should be found somewhere under the server's document root. It may exist on a server machine other than the one hosting the servlet, but conveniently that doesn't matter.

Using the returned URL object you can investigate the attributes of the abstract resource. Here's code that examines the Web server's front page.

URL url = getServletContext().getResource("/");  // front page
URLConnection con = url.openConnection();
con.connect();
int contentLength = con.getContentLength();
String contentType = con.getContentType();
long expiration = con.getExpiration();
long lastModified = con.getLastModified();
// etc...

Remember, the content served for the / URI path is entirely determined by the server.

Getting an abstract resource as a stream

The 2.1 API also includes a convenient method, called getResourceAsStream(String uripath), for reading resources as a stream. This method returns an InputStream, which lets you type

InputStream in = getServletContext().getResourceAsStream("/")

instead of

URL url = getServletContext().getResource("/");
InputStream in = url.openStream();

The method doesn't save much typing, but perhaps it can help people who aren't familiar with URL objects.

Writing to an abstract resource

Here's a useful tip: You can also use getResource() to write output, for those resources that permit it. The trick is to get the URL's corresponding URLConnection and write to the connection's OutputStream. For example:

URL url = getServletContext().getResource("/custom.log");
URLConnection con = url.openConnection();
con.setDoOutput(true);
OutputStream out = con.getOutputStream();
PrintWriter pw = new PrintWriter(new OutputStreamWriter(out));
pw.println("That wasn't so hard.");
pw.close();
out.close();

Backward compatibility for resources

For backward compatibility and to ease the transition to servlets for CGI programmers, 2.1 continues to include methods for file access, such as getPathTranslated(). Just remember that anytime you access a resource using a File object you're tying yourself to a particular machine.

Sessions

Servlet developers have been given more control over HttpSession lifecycles in 2.1. Previously, the interval before a session timed out had to be set using administration tools. You can now set the duration of a session programmatically by calling HttpSession.setMaxInactiveInterval(int interval). This method takes an int representing the number of seconds of inactivity that need to occur before the session is timed out and invalidated. A negative value indicates the session should never expire. The current interval can be retrieved using getMaxInactiveInterval().

Future directions: deployment descriptors

Not included in the 2.1 spec, but coming soon, are servlet deployment descriptors. These descriptors, modeled after a similar concept in Enterprise JavaBeans, are a way to simplify the installation of servlets and Web content into a Web server.

Deployment descriptors are expected to allow servlets, support classes, and even content to be packaged in a jar along with a complete declaration of their server configuration requirements. For example, the jar can report where the content should reside, which of the contained classes should be loaded as servlets, what names the servlets should be registered under, what default init parameters the servlets should have, and what ServletContext the servlets should live in. Essentially, with deployment descriptors you'll be able to install an entire "Web application" using just one jar.

Conclusion

The 2.1 API includes a number of changes that make servlet programming easier and more consistent. In exact numbers: version 2.1 offers 1 new class, 24 new methods, 1 deprecated class, and 9 deprecated methods. It's definitely not a large revision, and the core functionality remains the same, but by moving to 2.1 you'll be able to take advantage of consistent APIs and new abilities for request delegation, information sharing, resource abstraction, and session management.

Jason Hunter works as the chief technology officer of K&A Software, where he specializes in Java training and consulting. He is author of the book Java Servlet Programming (O'Reilly) and publisher of the Web site http://www.servlets.com. He belongs to the working group responsible for Servlet API development (and has his fingerprints all over the 2.1 specification). If by some miracle you don't find him at work, he's probably out hiking in the mountains.

Learn more about this topic

  • Servlet API 2.1 specification http://java.sun.com/products/servlet/2.1
  • A site dedicated to helping you learn about, develop, and use servlets http://www.servlets.com
  • Servlets.com accompanies the book Java Servlet Programming http://www.servlets.com/book/buy.html
  • Official home site for servlets http://java.sun.com/products/servlet
  • Official API documentation for the Servlet API 2.0 http://jserv.java.sun.com/products/java-server/documentation/webserver1.1/apidoc/packages.html
  • A comprehensive list of servlet resources http://www.servlets.com/resources/urls/
1 2 Page 2
Page 2 of 2