devxlogo

Servlet 3.0: A Sneak Preview

Servlet 3.0: A Sneak Preview

part from the addition of functionalities such as filters and web application events, the Servlet specification?one of the key Java APIs for web application development?has not undergone any major changes since its introduction. However, the specification has remained robust, and the release of the new Servlet 3.0 specification (JSR 315) will affect a major change in the way developers build Java web applications.

This article offers a brief overview to the new features in Servlet 3.0. Then, using code samples, it dives into the details of using annotations for Servlet 3.0 filters and listeners. The discussion also touches on how to plug frameworks and other libraries into a web application using web fragments. The article concludes with a brief discussion of Servlet 3.0’s support for asynchronous processing and highlights of the enhancements made to the existing APIs.

The New Features in Servlet 3.0: An Overview

The Servlet 3.0 specification has three goals for the developers who employ it:

  • Simplicity
  • Ease of development
  • Adherence to Web 2.0 principles

To make the development process easier, Servlet 3.0 introduces annotations. Similar to the changes in EJB 3.1, the introduction of annotations makes the web deployment descriptor –web.xml optional.

Pluggability

Whenever you use a third-party framework such as Struts, JSF, or Spring, you need to have a corresponding entry for the respective Servlet in web.xml. This requirement makes the web deployment descriptor cumbersome and difficult to maintain. Enter the new pluggability feature in Servlet 3.0, which makes web applications modular and easier to maintain. Implemented through web fragments, pluggability relieves the developer from making too many Servlet configuration entries in the web.xml file.

Asynchronous Processing

Another significant change in the new Servlet specification is the support for asynchronous processing, a useful feature for AJAX applications. When a Servlet creates a thread to make a request, it often has to wait for a response from a resource like a database or message connection before it can perform another operation on that thread. Asynchronous processing avoids such blocking requests by allowing the thread to perform some other operation.

Apart from the features mentioned here, several other enhancements have been made to the existing API. The sections towards the end of the article will explore these features one by one in detail.

Author’s Note: To run a Servlet developed with Servlet 3.0, your Servlet container should run Java SE 6 and above.

Annotations in Servlet

One of the major changes in Servlet 3.0 is the support for annotations. Using annotations to define Servlets and filters eliminates the need for the Servlet/Filter entry in the web deployment descriptor (web.xml).

@WebServlet

To define a Servlet component in a web application, you use @WebServlet. You use it on a class that extends the javax.servlet.http.HttpServlet class. The @WebServlet annotation has many attributes, such as name, urlPatterns, and initParams, which you use to define the Servlet’s behavior. For the url pattern, you must specify it either with the annotation itself or with an attribute of the annotation.

You can define a simple Servlet with @WebServlet as follows:

@WebServlet(name = "GetQuoteServlet",  urlPatterns = {"/getquote"} )public class GetQuoteServlet extends HttpServlet {    @Override    protected void doGet(HttpServletRequest request, HttpServletResponse response)            throws ServletException, IOException {        PrintWriter out = response.getWriter();        try {            String symbol = request.getParameter("symbol");            out.println("

Stock Price is

" + StockQuoteBean.getPrice(symbol); } finally { out.close(); } }}public class StockQuoteBean {private StockQuoteServiceEntity serviceEntity = new StockQuoteServiceEntity(); public double getPrice(String symbol) { if(symbol !=null ) {return serviceEntity.getPrice(symbol); } else { return 0.0; } }}

You can modify the same Servlet to address requests from multiple URLs with the annotation attributes.

@WebServlet(name = "GetQuoteServlet",  urlPatterns = {"/getquote",  "/stockquote"} )public class GetQuoteServlet extends HttpServlet {    @Override    protected void doGet(HttpServletRequest request, HttpServletResponse response)            throws ServletException, IOException {        PrintWriter out = response.getWriter();        try {            String symbol = request.getParameter("symbol");            out.println("

Stock Price is

" + StockQuoteBean.getPrice(symbol); } finally { out.close(); } }}

@WebFilter

You use the @WebFilter annotation to define a filter. This annotation also has optional parameters. You can use @WebFilter on any class that implements the javax.servlet.Filter interface. Similar to the @WebServlet annotation, you must specify the url pattern on this annotation as well.

@WebFilter(filterName = "AuthenticateFilter", urlPatterns = {"/stock.jsp", "/getquote"})public class AuthenticateFilter implements Filter {    public void doFilter(ServletRequest request, ServletResponse response,            FilterChain chain)     throws IOException, ServletException {        String username = ((HttpServletRequest) request).getParameter("uname");        String password = ((HttpServletRequest) request).getParameter("password");          if (username == null || password == null) {                 ((HttpServletResponse) response).sendRedirect("index.jsp");            } if (username.equals("admin") && password.equals("admin")) {                chain.doFilter(request, response);      } else {                ((HttpServletResponse) response).sendRedirect("index.jsp");         }         }    public void destroy() {    }    public void init(FilterConfig filterConfig) {    }}

@WebInitParam

You use the @WebInitParam annotation to specify the init parameters to the Servlet or filter. Alternatively, you can specify the init parameters with the initParam attributes of the @WebServlet and @WebFilter annotations.

@WebServlet(name = "GetQuoteServlet", urlPatterns = {"/getquote"})@WebInitParam(name = "default_market", value = "NASDAQ")public class GetQuoteServlet extends HttpServlet {    @Override    protected void doGet(HttpServletRequest request, HttpServletResponse response)            throws ServletException, IOException {        response.setContentType("text/html;charset=UTF-8");        PrintWriter out = response.getWriter();        try {            String market = getInitParameter("default_market");            String symbol = request.getParameter("symbol");            out.println("

Stock Price in " + market + " is

" + StockQuoteBean.getPrice(symbol, market)); } finally { out.close(); } }}

Here is an alternate example that uses the @WebInitParam annotation as part of the @WebServlet and @WebFilter initParams attribute:

@WebServlet(name = "GetQuoteServlet",            urlPatterns = {"/getquote"},            initParams={@WebInitParam(name="default_market",  value="NASDAQ")}           )public class GetQuoteServlet extends HttpServlet {    @Override    protected void doGet(HttpServletRequest request, HttpServletResponse response)            throws ServletException, IOException {        response.setContentType("text/html;charset=UTF-8");        PrintWriter out = response.getWriter();        try {            String market = getInitParameter("default_market");            String symbol = request.getParameter("symbol");            out.println("

Stock Price in " + market + " is

" + StockQuoteBean.getPrice(symbol, market)); } finally { out.close(); } }}

@WebListener

You use the @WebListener annotation on a class that acts as a listener to various web application events in a given web application context. You can use @WebListener to annotate a class that implements ServletContextListener, ServletContextAttributeListener, ServletRequestListener, ServletRequestAttributeListener, HttpSessionListener, and HttpSessionAttributeListener. Here is an example with ServletContextListener:

@WebListenerpublic class QuoteServletContextListener implements ServletContextListener {   public void contextInitialized(ServletContextEvent sce) {   ServletContext context = sce.getServletContext();context.setInitParameter(“default_market”, “NASDAQ”);}public void contextDestroyed(ServletContextEvent sce) {}}

@MultipartConfig

Use the @MultipartConfig annotation to specify the multipart MIME type request for the Servlet. The MIME attachments are read from the request object.

The Metadata and Common Annotations

Apart from the Servlet-specific annotations described above, Servlet 3.0 continues to support all the annotations that are defined as part of JSR 175 (Java Metadata Specification) and JSR 250 (Common Annotations for the Java Platform), including:

  • Annotations related to security, such as @DeclareRoles and @RolesAllowed
  • Annotations to use EJB, such as @EJB and @EJBs
  • Annotations for resource injection, such as @Resource and @Resources
  • Annotations to use JPA, such as @PersistenceContext, @PersistenceContexts, @PersistenceUnit, and @PersistenceUnits
  • Life cycle annotations, such as @PostConstruct and @PreDestroy
  • Annotations to provide references to web services, such as @WebServiceRef and @WebServiceRefs

Annotations or web.xml?

The introduction of annotations makes the web deployment descriptor (web.xml) optional when configuring web components. However, if you have to make any changes or updates to the configuration, you can still use the deployment descriptor. The container will decide to use web.xml or annotations depending on the value for the element metadata-complete in the web.xml descriptor. If the attribute has a value true, then the container does not process the annotations and web fragments; the deployment descriptor is the only source for all the metadata information. The container will process annotations and web fragments only if the element metadata-complete is not there or does not have a value true.

Pluggability Through Web Frameworks

As discussed previously, Servlet 3.0 includes enhancements to enable you to plug frameworks and libraries into a web application. This pluggability reduces the number of configurations and provides good modularity for web applications. Servlet 3.0 achieves pluggability through web module deployment descriptor fragments (or web fragments, for short).

A web fragment is a part of the web.xml file specified and included in the framework-specific JAR’s META-INF directory. A web fragment provides logical partitioning of the web application without your having to edit the web deployment descriptor for framework-specific components.

The elements (tags) used in the web fragment are almost the same set of elements (tags) used in the deployment descriptor, except the root element (parent tag). The root element for the web fragment should be web-fragment, and hence the file should be called web-fragment.xml. The container will look for web-fragment.xml only in the JAR file placed under the WEB-INFlib folder. If the JAR file under the lib directory has any web-fragment.xml files, the container will load the required classes and process them.

Just as the Servlet name is expected to be unique in a given web.xml file, the same logic applies to web fragments as well. In addition, the Servlet name must be unique in the entire web application, including the web.xml and all the web fragments.

As an example, the following web-fragment.xml is placed under the jarsMETA-INF directory of frameworks:

web-fragment.xmlControllerServletcom.app.control.ControllerServletcom.listener.AppServletContextListener

The framework JAR file is placed under the WEB-INFlib directory. The Servlet 3.0 specification does not define the ordering of configuration from web-fragment.xml and annotations, but it does define the ordering of configuration of web.xml and web-fragment.xml as follows:

  1. Absolute ordering
  2. Relative ordering
Figure 1. Absolute Ordering in Servlet 3.0: You achieve absolute ordering with the help of the element in the web.xml file.

You achieve absolute ordering with the help of the element in the web.xml file (see Figure 1). This element has a child element that specifies the names of web fragments and thus the absolute ordering of the web fragments to be processed. If multiple web fragments have the same name, the container ignores the web fragment that appears second.

web.xmlDemoAppWebFragment1WebFragment2...
Figure 2. Relative Ordering in Servlet 3.0: You achieve relative ordering with the help of the element in the web-fragment.xml file.

You achieve relative ordering with the help of the element in the web-fragment.xml file (see Figure 2). The container would look upon this element only if there is no entry of in web.xml. The ordering of the web fragments is decided by the , , and elements. If any of the web fragments has a child element, the file will be moved to the beginning of the list of sorted documents. Similarly, if any of the web fragments has an child element, the document will be moved to the end of the list of sorted documents.

To understand the relative ordering better, consider some examples. The following example assumes that three JAR files each has a web-fragment.xml file.

web-fragment.xmlWebFragment1WebFragment2...web-fragment.xmlWebFragment2..web-fragment.xmlWebFragment3..

The files will be processed in the following order:

  1. WebFragment3
  2. WebFragment2
  3. WebFragment1

The JAR file having WebFragment3 will be processed first because of the element. This setup insures that the document is placed on top of the list. The JAR file having WebFragment2 will be processed next, because the JAR file with WebFragment1 uses the element, which pushes the document to the end of the list of documents to be processed. The element nested within the and elements ensures that the documents are pushed to the top and the bottom of the list, respectively.

If web.xml encounters both and elements, it ignores the element; it considers only the absolute ordering because that element appears first. Similarly, if the element appears first and is followed by the element, then the container ignores because it considers only the relative ordering. If a deployment descriptor does not have (in the web.xml) and (in the web-fragment.xml), then the documents are assumed not to have any ordering dependency.

Asynchronous Processing in Servlet

In many situations, a Servlet has to interact with a resource for processing data. It could be a database resource, a web service, or a message resource. While interacting with these resources, the Servlet has to wait until it gets a response from the resource before it actually generates a response. This makes the Servlet call to the resource a blocking call and results in inefficiency. Servlet 3.0 addresses this issue with the introduction of asynchronous processing. Asynchronous processing allows the thread to issue a call to the resource and return back to the container without getting blocked. The thread can perform other tasks, which makes Servlet 3.0’s performance more efficient. AsyncContext, which manages the response from the resource, decides whether the response from the resource will be handled by the same thread or dispatched to a new resource in the container. AsyncContext has methods such as start, dispatch, and complete to perform the asynchronous process.

Servlet 3.0’s asynchronous processing is supported through the asyncSupported attribute available in both @WebServlet and @WebFilter annotations. This attribute takes a Boolean value, which by default has a false value. You enable asynchronous processing in Servlet by setting a true value to this attribute in the Servlet or in the filter.

When combined with comet, Servlet asynchronous processing becomes an ideal solution for AJAX applications. In the init method of a Servlet, the thread can start any database operation or read/write a message to a queue. In the doGet or doPost method, you can start the asynchronous processing and the AsyncContext will manage the thread related to the database or message operation with the help of AsyncEvent and AsyncListener.

Enhancements to Existing APIs

In addition to the introduction of new concepts/techniques, the Servlet 3.0 specification also made the following enhancements to existing APIs.

HttpServletRequest

To support the multipart/form-data MIME type, the following methods have been added to the HttpServletRequest interface:

  • Iterable getParts()
  • Part getPart(String name)

Cookies

To avoid certain types of cross-site scripting attacks, Servlet 3.0 supports HttpOnly cookies. HttpOnly cookies are not exposed to the client-side scripting code. The following methods are added to the Cookie class to support HttpOnly cookies:

  • void setHttpOnly(boolean isHttpOnly)
  • boolean isHttpOnly()

ServletContext

With the addition of the following methods to the ServletContext API, Servlet 3.0 allows Servlets and filters to be programmatically added to a context:

  • addServlet(String servletName, String className)
  • addServlet(String servletName, Servlet servlet)
  • addServlet(String servletName, Class extends Servlet> servletClass)
  • addFilter(String filterName, String className)
  • addFilter(String filterName, Filter filter)
  • addFilter(String filterName, Class extends Filter>filterClass)
  • setInitParameter (String name, String Value)?This method was added to set the context initialization parameter.

The Servlet 3.0 Specification Features

As you can see, the Servlet 3.0 specification offers a lot of interesting features, including ease of development through annotations, fewer configurations of frameworks through the introduction of web fragments, and enhanced response with the introduction of asynchronous processing. This major release is sure to attract a large developer community.

Authors’ Acknowledgements: The authors would like to sincerely thank Mr. Subrahmanya SV (VP, ECOM Research Group, E&R) for his ideas, guidance, support, and constant encouragement, and Mr. Piramanayagam Manickam (Senior Technical Architect, ECOM Research Group, E&R) for kindly reviewing this article and providing valuable comments.

devxblackblue

About Our Editorial Process

At DevX, we’re dedicated to tech entrepreneurship. Our team closely follows industry shifts, new products, AI breakthroughs, technology trends, and funding announcements. Articles undergo thorough editing to ensure accuracy and clarity, reflecting DevX’s style and supporting entrepreneurs in the tech sphere.

See our full editorial policy.

About Our Journalist