[ Team LiB ] Previous Section Next Section

Recipe 16.1 Setting ServletContext Attributes in Servlets

Problem

You want to make an object available to all servlets in a context or web application.

Solution

Bind an object to the ServletContext using the javax.servlet.ServletContext.setAttribute( ) method.

Discussion

A ServletContext attribute is available to all servlets and JSPs in a context or web application. Here are the steps to bind an object to a ServletContext:

  1. Create the Java class that you want to bind to a ServletContext.

  2. Place the class in the WEB-INF/classes directory, including the necessary package-related directories. You can also store the class in a JAR file in WEB-INF/lib.

  3. Create a servlet that binds the object to the ServletContext using the javax.servlet.ServletContext.setAttribute( ) method.

  4. Access the object using ServletContext.getAttribute( ) in (other) servlets whenever it is needed.

I'll first show the object that this recipe binds to the ServletContext. The recipe then demonstrates a servlet that stores the object attribute in the ServletContext. Example 16-1 shows a simple object wrapped around a java.util.Map type. Use the Map to store a characteristic of each request made to the web application. In this example, each Map key is the IP address of the client making the request. Each Map value is the date it requested the servlet.

Example 16-1. The object that a servlet binds to the ServletContext
package com.jspservletcookbook;           

import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

public class ContextObject  {

    private Map map;

  public ContextObject( ){

      map = Collections.synchronizedMap(new HashMap( ));
  }

  public void put(Object key, Object value){

      if (key == null || value == null)
        throw new IllegalArgumentException(
            "Invalid parameters passed to ContextObject.put");
   
      map.put(key,value);
  }

  public String getValues( ){

      StringBuffer buf = new StringBuffer("");
      Set set = map.keySet( );  

      //you have to explicitly synchronize when an Iterator is used
      synchronized(map) {  
  
          Iterator i = set.iterator( ); 

          while (i.hasNext( ))
              buf.append((String) i.next( ) + "<br>");
      }//synchronized
  
      return buf.toString( );
 
}

  public String toString( ){

      return getClass( ).getName( ) + "[ " +map+ " ]";

  }//toString

}

The ContextObject class has methods to add keys and values to the Map (put(Object key, Object value)) as well as to output the Map's current key values (getValues( )). The Map is synchronized, which is essentially thread-safe; it is created in the ContextObject's constructor in the following manner:

map = Collections.synchronizedMap(new HashMap( ));

When you generate a Map using the static java.util.Collections.synchronizedMap( ) method, only one thread at a time can call the Map's methods. This is important with ServletContext attributes that may be accessed by several servlets and/or multiple threads at the same time.


Example 16-2 shows the skeleton of the ContextBinder servlet that binds an instance of the ContextObject class in Example 16-1 to the ServletContext.

Example 16-2. A servlet binds an object to the ServletContext
package com.jspservletcookbook;           

import javax.servlet.*;
import javax.servlet.http.*;

public class ContextBinder extends HttpServlet {

  public void doGet(HttpServletRequest request, HttpServletResponse response) throws 
  ServletException, java.io.IOException {
    
    //bind an object to the ServletContext
    getServletContext( ).setAttribute(
            "com.jspservletcookbook.ContextObject", new ContextObject( ));
    
    //display some HTML
      ...
  } //end doGet
}

The servlet method getServletContext( ) returns a javax.servlet.ServletContext instance. You then call that instance's setAttribute( ) method with the String attribute name and the bound object as parameters. As a convention, you should consider naming attributes after their fully qualified class name—in this case, "com.jspservletcookbook.ContextObject."

See Also

Recipe 16.2 on setting ServletContext attributes in JSPs; Recipe 16.3 on accessing or removing a ServletContext attribute; Recipe 16.5-Recipe 16.8 on handling session attributes in servlets and JSPs; Recipe 16.9-Recipe 16.12 on handling request attributes in servlets and JSPs; Recipe 14.5 on using a ServletContext event listener; the Javadoc for javax.servlet.ServletContextAttributeListener: http://java.sun.com/j2ee/1.4/docs/api/javax/servlet/ServletContextAttributeListener.html.

    [ Team LiB ] Previous Section Next Section