Java EE Tutorials - The Servlet Context and Friends

So far our Java EE tutorial series has covered Servlets and Servlet Filters. Now we need to look a little deeper into the configuration and lifecycle of a Servlet.

When your web application fires up, the server is responsible for loading the classes and initiating each Servlet. This procedure is more complicated than simply calling a couple of init() methods. There are a variety of app-wide configuration options available to your web application, and these need to be made available to your code.

To support this, the Servlet API uses two different configuration objects - ServletConfig and ServletContext.

ServletContext - The web server will create one instance of this class to be used across the entire web application. As such, it contains information about the entire web application. You can get info on every Servlet and Filter, as well as access to any global properties you’ve set.

ServletConfig - Each of your Servlets will get its own instance of this class. It contains Servlet-specific config options, as well as a reference to the global ServletContext object.

Let’s see how to use each of them. The code can be found in the servlet_context branch of my example Github repository. If you’re not using Git, you can download the branch as a ZIP file here

This code example ditches the Servlet Filters we created in the last post, since they aren’t really relevant to this topic. Instead, we’ll start with our BasicServlet again and work from there.

We’ll start by modifying BasicServlet. We’ll also rename the class to ServletContextExample; we’ll see why soon:

package net.cmw;

import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRegistration;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;

/**
 * Demonstration of how to use the ServletContext class.
 */
public class ServletContextExample extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

        ServletContext servletContext = this.getServletContext();

        // We can retrieve config properties set in web.xml
        String param = servletContext.getInitParameter("webXMLLocation");

        // We can also get information about our application and environment
        int majorVersion = servletContext.getMajorVersion();
        int minorVersion = servletContext.getMinorVersion();

        PrintWriter writer = resp.getWriter();
        writer.println("Our web XML Location param is: " + param);
        writer.println("Servlet major version: " + majorVersion);
        writer.println("Servlet minor version: " + minorVersion);
    }
}

We retrieve and display a property named “webXMLLocation”, as well as the version number of the Servlet API that we are using. There a quite a few more bits of info you can retrieve from the Context, which you are welcome to explore on your own.

If you do explore on your own, you will also find that the ServletContext object has methods named addServlet and addFilter. If you try to use these methods in this example, they will fail. I’ll show you how to use these in a future post. For now, sitck to playing with read-only methods.

Now it is time to demonstrate the ServletConfig class. We’ll create a new Servlet, ServletConfigExample:

import javax.servlet.ServletConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRegistration;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;

/**
 * Demonstration of how to use the ServletConfig class.
 */
public class ServletConfigExample extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

        // Let's get the ServletConfig object, and use it to read some properties
        ServletConfig servletConig = this.getServletConfig();
        String testParam = servletConig.getInitParameter("testParam");
        String servletName = servletConig.getServletName();

        // We can get the ServletContext object from the ServletConfig,
        // or on its own by calling this.getServletContext()
        ServletContext servletContext = servletConig.getServletContext();

        // Now we can run all the same code we ran in the ServletContextExample class
        String param = servletContext.getInitParameter("webXMLLocation");

        // We can also get information about our application and environment
        int majorVersion = servletContext.getMajorVersion();
        int minorVersion = servletContext.getMinorVersion();

        PrintWriter writer = resp.getWriter();
        writer.println("Servlet name is" + servletName);
        writer.println("Our Servlet property is " + testParam);
        writer.println("Our web XML Location param is: " + param);
        writer.println("Servlet major version: " + majorVersion);
        writer.println("Servlet minor version: " + minorVersion);
    }
}

It isn’t too much different. We first grab the ServletConfig object. We then use it to grab the ServletContext (as I mentioned earlier, each Config object has a reference to the global Context). We also grab the Servlet’s name, which is one of the only standard fields available to the ServletConfig class. You can also set custom properties on it; in this case, we try to retrieve a custom property named testParam.

Now that we have our two Servlets, let’s see how to wire them up in the web.xml:

<?xml version="1.0" encoding="UTF-8"?>
<web-app
        version="3.0"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns="http://java.sun.com/xml/ns/javaee"
        xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">

    <display-name>
        Basic Servlet Example
    </display-name>

    <!-- This param is available to the whole web app. -->
    <context-param>
        <param-name>
            webXMLLocation
        </param-name>
        <param-value>
            classpath:web.xml
        </param-value>
    </context-param>

    <servlet>
        <servlet-name>
            Servlet Context Example
        </servlet-name>
        <servlet-class>
            net.cmw.ServletContextExample
        </servlet-class>
    </servlet>

    <servlet>
        <servlet-name>
            Servlet Config Example
        </servlet-name>
        <servlet-class>
            net.cmw.ServletConfigExample
        </servlet-class>
        <init-param>
            <param-name>testParam</param-name>
            <param-value>1</param-value>
        </init-param>
    </servlet>

    <servlet-mapping>
        <servlet-name>
            Servlet Context Example
        </servlet-name>
        <url-pattern>
            /servlet-context
        </url-pattern>
    </servlet-mapping>

    <servlet-mapping>
        <servlet-name>
            Servlet Config Example
        </servlet-name>
        <url-pattern>
            /servlet-config
        </url-pattern>
    </servlet-mapping>
</web-app>

We’ve added a contextParam block, containing a key-value pair. This is the property we retrieved from the ServletContext in both examples. Remember that since this property was added to the Context, it is available to all Servlets in the application.

Next, take a look at line 39. We add an <init-param> block containing a property. The property’s name is testParam, which is what we try and retrieve in the ServletConfigExample class. This property is only available to this Servlet, which you can tell because it is retrieved from a ServletConfig object (which is exclusive to each Servlet).

General Observations

You may not find yourself referencing either of these objects all that much in your own code, but they’re used quite a lot by web frameworks. Spring in particular relies on the existence of certain properties in the ServletContext. Knowing what these things are, and how they’re configured, will make life much easier next time you have to read the web.xml file of some application you’ve inherited.