Session ListenersS2C Home « Session Listeners

In our third and final lesson on listeners we take an in-depth look at session listeners, which allow us to be alerted by session state alterations; whether it be when the lifecycle of the session has changed, one of the attributes within a session has been added, removed, replaced, bound, unbound, or when the session has been passivated or activated in a distributed environment.

Knowing when your session is about to come into scope can enhance pre-initialisation of session scoped resources and knowing when your session is about to go out of scope is useful for tidying up the resources. Both situations could also help with keeping track of resources on distributed environments or logging them to know when attributes are added, removed, replaced, bound or unbound.

There are four session listener types we can use:

  • javax.servlet.http.HttpSessionListener and javax.servlet.http.HttpSessionAttributeListener act in exactly the same way as the context and request listeners we saw in the previous two lessons. When implemented, these types will trigger from the javax.servlet.http.HttpSessionEvent and javax.servlet.http.HttpSessionBindingEvent event types respectively. The main difference here is that the event type is not called HttpSessionAttributeEvent as is the convention with context and request attribute event types.
  • javax.servlet.http.HttpSessionBindingListener and javax.servlet.http.HttpSessionActivationListener are different to all the other listeners we have seen so far as they are not declared within the DD. When implemented, these types will trigger from the javax.servlet.http.HttpSessionEvent and javax.servlet.http.HttpSessionBindingEvent event types respectively. These are the same event types as the other two listeners but invoke different methods.

The session listeners and their related event types are summarized in the table below, use the links in the table to go to more detailed explanations of each interface and event type.

Listener Interface Event Type Description
HttpSessionListenerHttpSessionEventYou want to know when a session is created or destroyed.
HttpSessionActivationListenerHttpSessionEventYou want to know when a session is passivated on one JVM and then reactivated on another JVM.
HttpSessionAttributeListenerHttpSessionBindingEventYou want to know when a session attribute has been added, removed or replaced.
HttpSessionBindingListenerHttpSessionBindingEventYou want to know when objects are bound or unbound from a session.

We look at each session listener and session event type in more detail in the following sections and finish our discussion of session listeners with some code to see the various components in action.

The HttpSessionListener Interfacego to top of page Top

We implement the HttpSessionListener type when we want to receive notifications about changes to the list of active sessions within a web application. This allows users of the interface to know when a session has been created or invalidated. This type of notification can be useful for any pre-initialization we need to do in the first instance and for any housekeeping, or persisting of session attributes in the second. We can also use the methods within the interface to keep a count of the active sessions for web applications in distributed systems for load balancing across several servers.

The two methods within the HttpSessionListener interface are shown in the table below. Click the links in the table below to go to code examples of the implemented methods.

Method Declaration Description
void sessionCreated(HttpSessionEvent hse)Receive notification that a session has been created.
void sessionDestroyed(HttpSessionEvent hse)Receive notification that a session is about to be invalidated.

The HttpSessionActivationListener Interfacego to top of page Top

We implement the HttpSessionActivationListener type when we have objects that are bound to a session as session attributes and we want to receive notifications when a session has been activated or is about to be passivated. Since this interface is implemented by classes bound to a session, each object we want bound to the session as a session attribute needs to implement the HttpSessionActivationListener type independently. This means that we can't configure this type of listener within the DD as we want the objects that pertain to a particular session.

But why on earth would we want to have individual classes bound to sessions as attributes and each implementing its own HttpSessionActivationListener type? The answer is distributed systems. When an application has large amounts of traffic it is common practice to deploy that application over several web servers. Each web server has identical, but independent, copies of the web application stored on them. When a request comes in from clients they can be passed to whichever server is the least active, which is known as load balancing.

If the client has a session, then the container needs to know about the session so it can recreate the session state for the client on activation and the terminology for this is session migration. With respect to Java, this means that when a session is moved from one JVM to another, or put a different way passivated then activated, then all objects bound to the session are transferred from the first JVM to the second. This is achieved as follows:

  • On passivation all session bound objects need to be serialized.
  • On activation all session bound objects need to be deserialized.

This of course means that all session bound objects in a distributed application need to implement the java.io.Serializable interface or an exception will occur.

The two methods within the HttpSessionActivationListener interface are shown in the table below.

Method Declaration Description
void sessionDidActivate(HttpSessionEvent hse) Receive notification that a session has just been activated.
void sessionWillPassivate(HttpSessionEvent hse) Receive notification that a session is about to be passivated.

The HttpSessionEvent Classgo to top of page Top

HttpSessionEvent is the event class for notifications about changes to sessions within a web application and consists of one method which is used to return the HttpSession that changed. This class is also the parameter input for the sessionCreated() and sessionDestroyed() methods of the HttpSessionListener interface and the sessionDidActivate() and sessionWillPassivate() methods of the HttpSessionActivationListener interface. Implementation of either or both interfaces is how we are alerted to changes when the event is triggered.

The single method within the HttpSessionEvent class is shown in the table below. Click the link in the table below to go to a code example of the implemented method.

Method Declaration Description
HttpSession getSession()Return the session that changed.

The HttpSessionAttributeListener Interfacego to top of page Top

We implement the HttpSessionAttributeListener type when we want to receive notifications about changes to the attribute list of sessions within a web application. This allows users of the interface to know when an attribute has been added, removed or replaced. This type of notification can be useful for logging, messaging and housekeeping.

The three methods within the HttpSessionAttributeListener interface are shown in the table below. Click the links in the table below to go to code examples of the implemented methods.

Method Declaration Description
void attributeAdded(HttpSessionBindingEvent hsbe)Receive notification that a new attribute has been added to a session.
void attributeRemoved(HttpSessionBindingEvent hsbe)Receive notification that an existing attribute has been removed from a session.
void attributeReplaced(HttpSessionBindingEvent hsbe)Receive notification that an existing attribute has been replaced within a session.

The HttpSessionBindingListener Interfacego to top of page Top

We implement the HttpSessionBindingListener type when we want an object is being bound (added) to or unbound (removed) from a session. Since this interface is implemented by classes bound to a session, each object we want bound to the session as a session attribute needs to implement the HttpSessionBindingListener type independently. This means that we can't configure this type of listener within the DD as we want the objects that pertain to a particular session. This type of notification can be useful for refreshing rendered information as we get notified when an object gets rebound to the session and may have changed in the meantime. An object can become unbound programmatically, through a session being invalidated or when a session times out.

The three methods within the HttpSessionBindingListener interface are shown in the table below. Click the links in the table below to go to code examples of the implemented methods.

Method Declaration Description
void valueBound(HttpSessionBindingEvent hsbe)Send notification to an object that it is being bound (added) to an identified session.
void valueUnbound(HttpSessionBindingEvent hsbe)Send notification to an object that it is being unbound (removed) from an identified session.

The HttpSessionBindingEvent Classgo to top of page Top

HttpSessionBindingEvent is the event class for notifications about objects being bound (added), unbound (removed) or replaced within a session and consists of three methods which show the key/value pairing of the attribute and session in question. This class is also the parameter input for the attributeAdded(), attributeRemoved() and attributeReplaced() methods of the HttpSessionAttributeListener interface and the valueBound() and valueUnbound() methods of the HttpSessionBindingListener interface. Implementation of either or both interfaces is how we are alerted to changes when the event is triggered.

The three methods within the HttpSessionBindingEvent class are shown in the table below. Click a link in the table below to go to a code example of the method.

Method Declaration Description
java.lang.String getName()Return the name of the attribute that was bound to, or unbound from, the session.
HttpSession getSession()Return the session that changed.
java.lang.Object getValue()Returns the value of the attribute that was added, removed, or replaced.

If the attribute was added, this is the value of the added attribute.
If the attribute was removed, this is the value of the removed attribute.
If the attribute was replaced, this is the old value of the attribute.

Example Of Session Listenersgo to top of page Top

We will keep the idea simple so you can see how the HttpSessionListener HttpSessionAttributeListener and HttpSessionBindingListener listeners are implemented and what else we need to do to get our listeners working. There is no example of the HttpSessionActivationListener as we are not running a distributed system but hopefully you got the idea of how to use it above. It is not an intention of this tutorial to go into details about event handling, although if you are interested it works in the same way as Swing for example. For more details on event handling you can find information on my Java6 Tutor site at Swing - Event Handling.

Within the _ServletsAdv folder create a new folder for this lesson called sessionlisteners

Within the sessionlisteners folder we will create separate folders to hold our DD, source files and our compiled byte code and these will be called dd, src and classes.

Within the src folder create a subfolder called controller.

So after creating these folders your directory structure should look something like the following screenshot:

sessionlisteners directory structure

Coding The Listenersgo to top of page Top

We are now ready to code our listeners which will consist of implementations of the HttpSessionListener, HttpSessionAttributeListener and HttpSessionBindingListener interfaces.

Coding ImplHttpSessionListener

The ImplHttpSessionListener class implements the sessionCreated() and sessionDestroyed() methods of the HttpSessionListener interface. Within the overridden sessionCreated() and sessionDestroyed() methods we get the HttpSession object using the HttpSessionEvent object. We then output some session information message to the console.

Cut and paste the following code into your text editor and save in the   c:\_ServletsAdv\sessionlisteners\src\controller directory as ImplHttpSessionListener.java.


package controller;

import javax.servlet.http.*;

public class ImplHttpSessionListener implements HttpSessionListener {

    @Override
    public void sessionCreated(HttpSessionEvent event) { 
        // Write to console
        System.out.println("Within the sessionCreated() method"); 
        // Get HttpSession from event
        HttpSession sess = event.getSession(); 
        // Write some session information
       System.out.println("Unique Session identifier: " + sess.getId());
    }

    @Override
    public void sessionDestroyed(HttpSessionEvent event) { 
        // Write to console
        System.out.println("Within the sessionDestroyed() method");  
        // Get HttpSession from event
        HttpSession sess = event.getSession(); 
        // Write some session information
       System.out.println("Unique Session identifier: " + sess.getId());
       System.out.println("Session removal after: "  + sess.getMaxInactiveInterval() 
               + " seconds inactivity");
    }
}

Compiling ImplHttpSessionListener

Open your command line editor:

Change to directory  c:\_ServletsAdv\sessionlisteners\src\controller

Compile ImplHttpSessionListener.java using the java compiler with the -cp and -d options as below, making sure you change apache-tomcat-6.0.37 to wherever you downloaded Tomcat to.

javac -cp c:\apache-tomcat-6.0.37\lib\servlet-api.jar -d ..\..\classes ImplHttpSessionListener.java

The following screenshot shows that we get a clean compile and also the ImplHttpSessionListener class now compiled into the classes\controller directory.

compile ImplHttpSessionListener class
Coding ImplHttpSessionAttributeListener

The ImplHttpSessionAttributeListener class implements the attributeAdded(), attributeRemoved() and attributeReplaced() methods of the HttpSessionAttributeListener interface. We write the name of the session parameter and its old or new value to the console along with information about the method used.

Cut and paste the following code into your text editor and save in the   c:\_ServletsAdv\sessionlisteners\src\controller directory as ImplHttpSessionAttributeListener.java.


package controller;

import javax.servlet.http.*;

public class ImplHttpSessionAttributeListener implements HttpSessionAttributeListener {

    @Override
    public void attributeAdded(HttpSessionBindingEvent event) { 
        // Write to console
        System.out.println("Within the session attributeAdded() method"); 
        // Get attribute name and value and write to console
        String attrName = event.getName();
        String val = (String) event.getValue();
        System.out.println("Session attribute added. Name: " + attrName + " Value: " + val);
    }

    @Override
    public void attributeRemoved(HttpSessionBindingEvent event) { 
        // Write to console
        System.out.println("Within the session attributeRemoved() method"); 
        // Get attribute name and value
        String attrName = event.getName();
        String val = (String) event.getValue();
        System.out.println("Session attribute removed. Name: " + attrName + " Value: " + val);
    }

    @Override
    public void attributeReplaced(HttpSessionBindingEvent event) { 
        // Write to console
        System.out.println("Within the session attributeReplaced() method"); 
        // Get attribute name and value
        String attrName = event.getName();
        String val = (String) event.getValue();
        System.out.println("Session attribute replaced. Name: " + attrName + " Value: " + val);
    }
}

Compiling ImplHttpSessionAttributeListener

Open your command line editor:

Change to directory  c:\_ServletsAdv\sessionlisteners\src\controller

Compile ImplHttpSessionAttributeListener.java using the java compiler with the -cp and -d options as below, making sure you change apache-tomcat-6.0.37 to wherever you downloaded Tomcat to.

javac -cp c:\apache-tomcat-6.0.37\lib\servlet-api.jar -d ..\..\classes ImplHttpSessionAttributeListener.java

The following screenshot shows that we get a clean compile and also the ImplHttpSessionAttributeListener class now compiled into the classes\controller directory.

compile ImplHttpSessionAttributeListener class
Coding ImplHttpSessionBindingListener

The ImplHttpSessionBindingListener class implements the valueBound() and valueUnbound() methods of the HttpSessionBindingListener interface.

Remember that bound session objects are not declared in the DD and each will need its own implementation of the HttpSessionBindingListener interface.

On object binding and unbinding we output some messages to the console.

Cut and paste the following code into your text editor and save in the   c:\_ServletsAdv\sessionlisteners\src\controller directory as ImplHttpSessionBindingListener.java.


package controller;

import javax.servlet.http.*;

public class ImplHttpSessionBindingListener implements HttpSessionBindingListener {

    private String ihsblStr;

    // Constructor
    public ImplHttpSessionBindingListener(String ihsblStr) {
        this.ihsblStr = ihsblStr;
    }    

    @Override
    public void valueBound(HttpSessionBindingEvent event) { 
        // Write to console
        System.out.println("Within the session valueBound() method"); 
        // Get and write instance variable to console
        System.out.println("Binding object:" + getIhsblStr());
    }

    @Override
    public void valueUnbound(HttpSessionBindingEvent event) { 
        // Write to console
        System.out.println("Within the session valueUnbound() method"); 
        // Get and write instance variable to console
        System.out.println("Unbinding object:" + getIhsblStr());
    }

    // Getter and setter
    public String getIhsblStr() {
        return ihsblStr;
    }    

    public void setIhsblStr(String ihsblStr) {
        this.ihsblStr = ihsblStr;
    }    
}

Compiling ImplHttpSessionBindingListener

Open your command line editor:

Change to directory  c:\_ServletsAdv\sessionlisteners\src\controller

Compile ImplHttpSessionAttributeListener.java using the java compiler with the -cp and -d options as below, making sure you change apache-tomcat-6.0.37 to wherever you downloaded Tomcat to.

javac -cp c:\apache-tomcat-6.0.37\lib\servlet-api.jar -d ..\..\classes ImplHttpSessionBindingListener.java

The following screenshot shows that we get a clean compile and also the ImplHttpSessionBindingListener class now compiled into the classes\controller directory.

compile ImplHttpSessionBindingListener class

Coding The SessionServlet Classgo to top of page Top

What we are going to do is create a simple servlet that just creates some bound and not bound session attributes. There is no HTML output for this example as we are using the Tomat 6 logs to check our results.

Cut and paste the following code into your text editor and save it in the   c:\_ServletsAdv\sessionlisteners\src\controller directory as SessionServlet.java.


package controller;

import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.*;
import javax.servlet.http.*;

public class SessionServlet extends HttpServlet {

    private static final long serialVersionUID = 871964L;

    public void doGet(HttpServletRequest request, HttpServletResponse response) 
            throws ServletException, IOException {
        response.setContentType("text/html");
        PrintWriter writer = response.getWriter();
        // Get a HttpSession 
        HttpSession session = request.getSession();
        // Add some bound objects
        ImplHttpSessionBindingListener boundObj1 = new ImplHttpSessionBindingListener("IHSBL1");
        ImplHttpSessionBindingListener boundObj2 = new ImplHttpSessionBindingListener("IHSBL2");
        // Add bound objects to session attributes
        session.setAttribute("Bound1", boundObj1);
        session.setAttribute("Bound2", boundObj2);
        // Add some non-bound session attributes
        session.setAttribute("non_boundObj1", "Non Bound 1");
        session.setAttribute("non_boundObj2", "Non bound 2");
        // Remove a bound and non-bound session attributes
        session.removeAttribute("Bound2");
        session.removeAttribute("non_boundObj2");
    }
}

Compiling The SessionServlet Class

Open your command line editor:

Change to directory  c:\_ServletsAdv\sessionlisteners\src\controller

Compile SessionServlet.java using the java compiler with the -cp and -d options as below, making sure you change apache-tomcat-6.0.37 to wherever you downloaded Tomcat to.

  javac -cp c:\apache-tomcat-6.0.37\lib\servlet-api.jar;..\..\classes -d ..\..\classes SessionServlet.java

The following screenshot shows that we get a clean compile and also the SessionServlet class now compiled into the classes\controller directory.

compile SessionServlet class

Coding The DDgo to top of page Top

There are no DD entries for this application that we haven't seen before.


<?xml version="1.0" encoding="UTF-8"?>
<web-app xsi:schemaLocation="http://java.sun.com/xml/ns/javaee 
                             http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" 
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
         xmlns="http://java.sun.com/xml/ns/javaee" version="2.5">
   <listener>
      <listener-class>controller.ImplHttpSessionListener</listener-class>
   </listener>
   <listener>
      <listener-class>controller.ImplHttpSessionAttributeListener</listener-class>
   </listener>
   <servlet>
      <servlet-name>SessListeners</servlet-name>
      <servlet-class>controller.SessionServlet</servlet-class>
   </servlet>
   <servlet-mapping>
      <servlet-name>SessListeners</servlet-name>
      <url-pattern>/example</url-pattern>
   </servlet-mapping>
</web-app>

Save the web.xml file in the DD folder.

Tomcat Deploymentgo to top of page Top

Go to your Tomcat installation which in my case is:

C:\apache-tomcat-6.0.37\webapps\

Within the webapps folder create a folder for our web application called sessionlisteners

Within the sessionlisteners folder create the WEB-INF folder.

Copy the web.xml file and the classes directory and contents from our development environment into the WEB-INF folder.

After creating these folders and copying the files from development your Tomcat directory structure within the webapps\sessionlisteners folder should look something like the following screenshot:

Tomcat directory structure
Testing Our Servletgo to top of page Top

Open a command prompt and change the directory to the location of our Tomcat 6 bin directory and then type in startup (Windows 7) or startup.sh (Linux/Unix/OSX). Press Enter and the Tomcat 6 server should open up in a new window.

You can also start up Tomcat by double-clicking the startup batch file within your Tomcat /bin folder.

With Tomcat up and running type the following into your web browser address bar and press enter:

  http://localhost:8080/sessionlisteners/example

We should see some new entries in the Tomcat 6 logs (at the bottom) as we added listeners for session creation, destruction, session attribute addition, replacement, removal, binding and unbinding. The following screenshot shows the System.out.println messages we sent to the console from the ImplHttpSessionListener, ImplHttpSessionAttributeListener and ImplHttpSessionBindingListener implementations. These appear in the Tomcat 6 server window and I have highlighted the relevant lines in yellow so you can see them easier.

Run SessionServlet

There are a few points to note when looking at the output:

  1. When you implement ImplHttpSessionBindingListener as well as ImplHttpSessionAttributeListener:
    • The container will always invoke the valueBound() method of the ImplHttpSessionBindingListener implementation before the attributeAdded and attributeReplaced methods of the ImplHttpSessionAttributeListener implementation.
    • The container will always invoke the valueUnbound() method of the ImplHttpSessionBindingListener implementation after the attributeRemoved method of the ImplHttpSessionAttributeListener implementation.
  2. I let the session time out so you can see the attributeRemoved and valueUnbound() methods being invoked and their ordering.

Lesson 3 Complete

In this lesson we looked at the various session listeners and when to use them.

What's Next?

In the next lesson we learn all about filters.

go to home page Homepage go to top of page Top