New features added to Servlet 2.5

Servlets updated with annotations, web.xml conveniences, and more

On September 26, 2005, Sun Microsystems and the Java Specification Request 154 Expert Group issued a maintenance release of the Servlet API. Under normal circumstances, a JSR maintenance releases includes just a handful of nominally interesting specification clarifications. However, in this case, the release added several new features and changes, and made enough of an impact on servlets to justify a bump in the version number to Servlet 2.5.

In this article, I explain what's new in this Servlet 2.5 release. I describe each change, provide background on why the change was necessary, and show how to use the change in your own servlet-based programs.

This is actually my sixth article documenting Servlet API updates for JavaWorld. I intend these articles to serve two purposes: in the short term, to introduce you to the new features and, in the long term, to act as a historical compendium of changes, so when you find yourself coding against a past Servlet API version, you can determine exactly what features and behavior you can and can't depend on. Check Resources for my previous servlet articles.

Please remember: When experimenting with these new features and capabilities, not all servlet containers or Java Enterprise Edition (JEE) application servers jump immediately to the latest Servlet API release. At the time of this writing, the Jetty 6 server and Sun's GlassFish server are the two best-known servlet containers that include 2.5 support. Apache Tomcat 5.5 and JBoss 4.0 still support Servlet 2.4.

Among the changes introduced in Servlet 2.5:

  • A new dependency on J2SE 5.0
  • Support for annotations
  • Several web.xml conveniences
  • A handful of removed restrictions
  • Some edge case clarifications

Dependency on J2SE 5.0

To begin with, the Servlet 2.5 specification now lists J2SE 5.0 (JDK 1.5) as its minimum platform requirement. While this limits Servlet 2.5 to those platforms with J2SE 5.0 implementations, this change means that all the new language features from J2SE 5.0 (generics, autoboxing, an improved for loop, a new enum type, static importing, varargs, and metadata annotations) are guaranteed available to Servlet 2.5 programmers.

Traditionally, servlet and JEE releases have moved forward at the measured pace of one JDK level at a time, but this time, the servlet release skipped version 1.4. The expert groups considered the double jump to be justified because J2SE 5.0 offered one compelling feature that the servlet and JEE specifications wanted to use themselves: annotations.

Annotations

Annotations are a new language feature provided as part of JSR 175 (A Metadata Facility for the Java Programming Language). Annotations provide a mechanism for decorating Java code constructs (classes, methods, fields, etc.) with metadata information. Annotations aren't executed like code, but, rather, mark code in such a way that code processors may alter their behavior based on the metadata information.

When you think about it, we've been annotating classes and methods all along with different tricks like the Serializable marker interface (to alter serialization) or the @deprecated Javadoc comment (to alter compilation). The new metadata facility simply provides a standard mechanism for doing annotations and a vehicle for libraries to create custom annotation types.

Here's a simple Web service annotation example:

 

import javax.jws.WebService; import javax.jws.WebMethod;

@WebService public class HelloWorldService {

@WebMethod

public String helloWorld() { return "Hello World!"; } }

The @WebService and @WebMethod annotation types, specified in JSR 181 (Web Services Metadata for the Java Platform) and imported just like classes, mark this class as a Web service and mark its helloWorld() method as a Web service method. By themselves, the annotations don't do anything but sit there, kind of like Post-It notes; however, a container, upon loading this class and seeing those annotations in the bytecode, can wire up the class for Web services.

Annotations may accept name/value parameters. The parameter information is kept with the annotation and can be used to alter the behavior requested by the annotation. For example, here's a more advanced annotation example:

 @WebService(
  name = "PingService",
  targetNamespace="http://acme.com/ping"
)
@SOAPBinding(
  style=SOAPBinding.Style.RPC,
  use=SOAPBinding.Use.LITERAL
)
public class Ping {
  @WebMethod(operationName = "Foo")
  public void foo() { }
} 

Upon loading this class, a proper container will respect the annotations and their parameters, and wire up the class as a PingService with a Foo operation using the remote-procedure-call/literal encoding style. In a sense, annotations define the contract a class wishes to have with its container.

The Java language itself (through JSR 175) specifies only a tiny number of annotation types. The interesting annotation types come from other JSRs:

  • JSR 250: Common Annotations for the Java Platform
  • JSR 220: Enterprise JavaBeans 3.0
  • JSR 224: Java API for XML-Based Web Services (JAX-WS) 2.0
  • JSR 181: Web Services Metadata for the Java Platform

See Resources for more details on metadata and annotations.

Annotations in Servlet 2.5

Coming back to Servlet 2.5, the new specification describes how several annotations work in a servlet environment. Simple servlet containers can ignore these rules, while servlets in a JEE container must abide by them.

Some annotations provide an alternative to XML entries that would otherwise go in the web.xml deployment descriptor. Other annotations act as requests for the container to perform tasks that otherwise the servlet would have to perform itself. Some annotations do both.

The exact list of annotations isn't completely finalized, because the Servlet specification itself doesn't define the annotations; it only helps interpret how they affect a servlet environment. Here's a short summary of the annotations you can expect in JEE 5 along with their intended use:

  • @Resource and @Resources: @Resource is placed on a class or variable to request a "resource injection" by the servlet container. When the container sees this annotation, it will prepopulate the annotated variable with an appropriate value before the servlet gets placed into service. By using this annotation, you avoid the need to make a JNDI (Java Naming and Directory Interface) lookup call and declare the resource manually in the web.xml deployment descriptor file. The server takes care of both tasks through introspecting the servlet. The name and type of the variable are determined automatically by reflection, although you can override that with annotation parameters. An injected resource may be a datasource, Java Message Service destination, or environment entry variable. Here's a basic example:

     

    @Resource javax.sql.DataSource catalog;

    public getData() { Connection con = catalog.getConnection(); }

    Now, before putting a servlet with this code into service, the container will locate the JNDI variable named catalog of type DataSource and manually assign that reference to the catalog variable.

    For efficiency, only certain classes support resource injection: servlets, servlet filters, servlet event listeners, JavaServer Pages tag handlers and JSP library event listeners, JavaServer Faces scoped managed beans, and a few other class types unrelated to servlets.

    The @Resources annotation is similar to @Resource, but used to hold an array of @Resource annotations. Both annotations are from JSR 250, the Common Annotations for the Java Platform.

  • @PostConstruct and @PreDestroy: Attached to methods to make them act as lifecycle methods. The @PostConstruct method is called after the resource injection as a chance to initialize the injected resources. The @PreDestroy method is called when the servlet is taken out of service to give it a chance to release injected resources. The callback methods must be instance methods that return void and do not throw any checked exceptions. In a servlet, these annotations essentially let arbitrary methods act as secondary init() and destroy() methods. These properties also come from JSR 250.
  • @EJB: Similar to @Resource, except designed for injecting Enterprise JavaBeans references. It has somewhat different parameters than @Resource in that @EJB parameters are specifically designed to locate EJB references. This annotation comes from the EJB 3.0 specification.
  • @WebServiceRef: Similar to @Resource and @EJB, except designed for injecting Web service references. From the JAX-WS 2.0 Specification.
  • @PersistenceContext, @PersistenceContexts, @PersistenceUnit, and @PersistenceUnits: Annotations from the EJB 3.0 Specification to support Java object persistence.
  • @DeclareRoles: Defines the security roles used within the application. When defined on a servlet class, this annotation offers an alternative to <security-role> entries in the web.xml file. From JSR 250.
  • @RunAs: Used to declare the role under which a class should run. When defined on a servlet class, it's an alternative to <run-as> entries in the web.xml file. From JSR 250.

Annotation performance

Whether or not you use annotations—and especially if you don't—it's important to understand the performance impact they can have on a server at startup. In order for the server to discover annotations on classes, it must load the classes, which means that at startup, a server will look through all the classes in WEB-INF/classes and WEB-INF/lib, looking for annotations. (Per the specification, servers don't have to look outside these two places.) You can avoid this search when you know you don't have any annotations by specifying a metadata-complete attribute on the <web-app> root like this:

 <web-app xmlns="http://java.sun.com/xml/ns/javaee"
         version="2.5" metadata-complete="true">
</web-app> 

When you're not using annotations, this reenables lazy class loading.

web.xml conveniences

Servlet 2.5 introduces several small changes to the web.xml deployment descriptor file format to make its use more convenient.

Servlet name wildcarding

First, when writing a <filter-mapping>, you can now use an asterisk in a <servlet-name> entry to represent all servlets (and thus all JSP pages as well). Previously, you could only bind one servlet at a time to a filter, like this:

 <filter-mapping>
  <filter-name>Image Filter</filter-name>
  <servlet-name>ImageServlet</servlet-name>
</filter-mapping> 

Now you can bind all servlets at once:

 <filter-mapping>
  <filter-name>Image Filter</filter-name>
  <servlet-name>*</servlet-name>  <!-- New -->
</filter-mapping> 

This proves most useful when creating general rules like, "Execute a filter on all forwards to a servlet," which is written like this:

 <filter-mapping>
  <filter-name>Dispatch Filter</filter-name>
  <servlet-name>*</servlet-name>
  <dispatcher>FORWARD</dispatcher>
</filter-mapping> 

Multiple patterns in mappings

Second, when writing a <servlet-mapping> or <filter-mapping>, you can now provide multiple match criteria in the same entry. A <servlet-mapping> previously supported just one <url-pattern> element. Now it supports more than one. For example:

 <servlet-mapping>
  <servlet-name>color</servlet-name>
  <url-pattern>/color/*</url-pattern>
  <url-pattern>/colour/*</url-pattern>
</servlet-mapping> 

Likewise, a <filter-mapping> previously allowed just one <url-pattern> or one <servlet-name>. Now it supports any number of each:

 <filter-mapping>
  <filter-name>Multipe Mappings Filter</filter-name>
  <url-pattern>/foo/*</url-pattern>
  <servlet-name>Servlet1</servlet-name>
  <servlet-name>Servlet2</servlet-name>
  <url-pattern>/bar/*</url-pattern>
</filter-mapping> 

Both these changes are syntactic sugar, but so be it. There's no reason we should program low carb.

HTTP method names

Lastly, you can now place any legal HTTP/1.1 method name into an <http-method> element. As you may recall, the <http-method> element specifies the methods on which a <security-constraint> entry should apply. It's historically been limited to the seven standard HTTP/1.1 methods: GET, POST, PUT, DELETE, HEAD, OPTIONS, and TRACE. However, HTTP/1.1 allows for extension methods, and WebDAV is a popular technology using extensions. With Servlet 2.5, you can now apply security constraints on any conceivable HTTP method name, standard or extension, including WebDAV methods like LOCK, UNLOCK, COPY, and MOVE.

Just don't look for doLock() or doCopy() methods if you're writing a WebDAV servlet. You'll have to write your own service() method and peek at the request.getMethod() for dispatching. You just won't have to manage your own security, thanks to this change.

Restriction removal

1 2 Page 1
Page 1 of 2