[ Team LiB ] Previous Section Next Section

Recipe 11.10 Using a Listener to Monitor Session Attributes

Problem

You want a listener class to be notified when a session attribute is added, removed, or replaced.

Solution

Create a Java class that implements the HttpSessionAttributeListener interface. Register this class using the web application's deployment descriptor.

Discussion

The HttpSessionAttributeListener interface has three methods: attributeAdded( ) , attributeRemoved( ), and attributeReplaced( ); all have a parameter of the type HttpSessionBindingEvent. This listener is notified when the session sets, removes, or changes an attribute. Therefore, the method calls in the web application that cause an HttpSessionAttributeListener notification are:

  • HttpSession.setAttribute( String name,Object value).

  • HttpSession.removeAttribute( String name).

  • A call to HttpSession.setAttribute( ) when an attribute of the same name is already bound to the session. The original attribute is replaced, triggering a call to the attributeReplaced(HttpSessionBindingEvent event) method.

Example 11-16 displays a message to the console when a session object is bound, including the value of the object (which is a String in this simple example). Messages are also displayed when the attribute is removed or replaced. To make this listener available to the application:

  1. Give the class a zero-argument constructor.

  2. Add the class to the web application's WEB-INF/classes or lib directory (when it's in a JAR).

  3. Declare the listener in the deployment descriptor.

  4. Restart the web container (if necessary) so it can instantiate the listener.

Example 11-16. Listening for session object binding or unbinding
package com.jspservletcookbook;

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

public class SessionAttribListen implements HttpSessionAttributeListener {

    //Creates new SessionAttribListen 
    public SessionAttribListen( ) {
        
        System.out.println(getClass( ).getName( ));
    }
    
   public void attributeAdded(HttpSessionBindingEvent se) {
       
        HttpSession session = se.getSession( );

        String id = session.getId( );

        String name = se.getName( );

        String value = (String) se.getValue( );

        String source = se.getSource( ).getClass( ).getName( );

        String message = new StringBuffer(
         "Attribute bound to session in ").append(source).
           append("\nThe attribute name: ").append(name).
             append("\n").append("The attribute value:").
               append(value).append("\n").
                 append("The session ID: ").
                   append(id).toString( );

        System.out.println(message);
     }
   
     public void attributeRemoved(HttpSessionBindingEvent se) {
         
         HttpSession session = se.getSession( );

         String id = session.getId( );

         String name = se.getName( );

         if(name == null)
             name = "Unknown";

         String value = (String) se.getValue( );

         String source = se.getSource( ).getClass( ).getName( );

         String message = new StringBuffer(
           "Attribute unbound from session in ").append(source).
              append("\nThe attribute name: ").append(name).
                append("\n").append("The attribute value: ").
                  append(value).append("\n").append(
                    "The session ID: ").append(id).toString( );

         System.out.println(message);
     }
   
     public void attributeReplaced(HttpSessionBindingEvent se) {
         
          String source = se.getSource( ).getClass( ).getName( );

          String message = new StringBuffer(
            "Attribute replaced in session  ").
              append(source).toString( );

          System.out.println(message);
     }
}

When attributes are added, replaced, and removed from a session in the web application, this class prints information about the attribute and the session to the web container's console. The HttpSession type that binds the attribute can be accessed by calling the HttpSessionBindingEvent class's getSession( ) method. In all three of the listener's methods, you can get the ID of the session associated with the attribute, as well as the attribute's name and value. Inside the listener class's constructor is a line of code that prints the listener class name to the console when it is instantiated:

System.out.println(getClass( ).getName( ));

This message indicates to the developer that the listener is properly referenced in web.xml, and that the web container has created an instance of the listener. Finally, this listener class prints a message to the console about the session class that is the source of the event. The listener uses the java.util.EventObject.getSource( ) method (which is inherited by the HttpSessionBindingEvent object) to get a reference to the source of the session-binding event:

String source = se.getSource( ).getClass( ).getName( );

The se variable is the HttpSessionBindingEvent object. Here is the information that is printed to the Tomcat console:

Attribute bound to session in org.apache.catalina.session.StandardSession
The attribute name: session-attribute
The attribute value: Hello
The session ID: 9ED2C34964778265A34F7AB0DEA4B884
Attribute replaced in session  org.apache.catalina.session.StandardSession
Attribute unbound from session in org.apache.catalina.session.StandardSession
The attribute name: session-attribute
The attribute value: Hello there.
The session ID: 9ED2C34964778265A34F7AB0DEA4B884

The listener allows you to get the session ID, as well as the name and value of the session attribute, during the attribute's removal from the session. The HttpSessionBindingEvent.getValue( ) method returns the value of the attribute as a java.lang.Object. Therefore, if you want access to the attribute in the listener, then you would have to cast the Object type to its appropriate type during its addition, removal, or replacement. For example, imagine that you have stored a java.util.Map in a session. You want to check the Map contents in the listener's attributeRemoved method. If the variable be is of type HttpSessionBindingEvent, then this code checks the return type of be.getValue( ):

java.util.Map map = null;

Object value = null;

if((value = be.getValue( )) instanceof java.util.Map){

    map = (java.util.Map) value;
    System.out.println("HashMap value: " + map.get("key"));

}

This method returns the value of the session-bound object that's being removed. If the return type is a Map, the local variable value is cast to a java.util.Map, then the get( ) method is called on that Map (given that the Map instance contains a key called "key").

See Also

Chapter 14 on using listeners to log messages; Recipe 11.4 on checking the validity of a session; Recipe 11.9 on using a listener to track session lifecycle; Chapter 1 on web.xml; Chapter 7 of the Servlet v2.3 and 2.4 specifications on sessions; the javax.servlet.http.HttpSession API at http://java.sun.com/j2ee/sdk_1.3/techdocs/api/javax/servlet/http/HttpSession.html.

    [ Team LiB ] Previous Section Next Section