Context ListenersS2C Home « Context Listeners

In the first of three lessons on listeners we learn about context listeners. Before we get started perhaps we should define what a listener actually is. A listener allows us to receive event notifications when a context, request or session state has been altered; whether it be when the lifecycle of the scope in question has changed, or one of the attributes within that scope has been added, removed or replaced.

Knowing when for instance your application's context is loaded is extremely useful, you may wish to create some objects when your application is deployed or keep a log of changes to your application's attributes. By implementing the appropriate interface for that listener we can write code to deal with an event when it happens which is a very powerful reactive tool to have in the armoury.

There are two context listener types we can use, these being javax.servlet.ServletContextListener and javax.servlet.ServletContextAttributeListener. When implemented, these types will trigger from the javax.servlet.ServletContextEvent and javax.servlet.ServletContextAttributeEvent event types respectively.

The context 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
ServletContextListenerServletContextEventYou want to know when a context has been created or destroyed.
ServletContextAttributeListenerServletContextAttributeEventYou want to know when a context attribute has been added, removed or replaced.

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

The ServletContextListener InterfaceTop

We implement the ServletContextListener type when we want to receive notifications about changes to the servlet context the web application is part of. This allows users of the interface to know when a context is about to be initialized or destroyed. This type of notification can be useful for any pre-initialization we need to do in the first instance and for any housekeeping required in the second.

The two methods within the ServletContextListener 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 contextInitialized( ServletContextEvent sce)Receive notification that the web application initialization process is commencing.
void contextDestroyed( ServletContextEvent sce)Receive notification that the servlet context is about to be shut down.

The ServletContextEvent ClassTop

ServletContextEvent is the event class for notifications about changes to the servlet context of a web application and consists of a single method which is used to return the ServletContext object for the event that fired. This class is also the parameter input for both of the ServletContextListener methods we need to implement and is how we are alerted to changes when the event is triggered.

The only method within the ServletContextEvent class is shown in the table below. Click the link in the table below to go to a code example of this method.

Method Declaration Description
ServletContext getServletContext()Return the ServletContext that changed.

The ServletContextAttributeListener InterfaceTop

We implement the ServletContextAttributeListener type when we want to receive notifications about changes to the attribute list of the servlet context the web application is part of. 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 scheduling.

The three methods within the ServletContextAttributeListener 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( ServletContextAttributeEvent scae)Receive notification that a new attribute has been added to the servlet context.
void attributeRemoved( ServletContextAttributeEvent scae)Receive notification that an existing attribute has been removed from the servlet context.
void attributeReplaced( ServletContextAttributeEvent scae)Receive notification that an existing attribute has been replaced within the servlet context.

The ServletContextAttributeEvent ClassTop

ServletContextAttributeEvent is the event class for notifications about changes to the attribute list of the servlet context the web application is part of and consists of two methods which show the key/value pairing of the attribute in question. This class is also the parameter input for all of the ServletContextAttributeListener methods we need to implement and is how we are alerted to changes when the event is triggered.

The two methods within the ServletContextAttributeEvent 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 has changed on ServletContext.
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 Context ListenersTop

We will keep the idea simple so you can see how both the ServletContextListener and ServletContextAttributeListener listeners are implemented and what else we need to do to get our listeners working. 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 in the Java section at Swing - Event Handling.

What we are going to do for the example is set up two listener classes for our context listeners and a simple model class for a fictitious data source we will load up into a context attribute from a context parameter within the DD. Our simple servlet will replace and delete this DD so you can see the various ServletContextAttribute getting invoked. We will also output console messages so we can see where in the application lifecycle the ServletContextListener events are fired.

Folder SetupTop

The first thing we are going to do in our setup is to make a base folder called _ServletsAdv in the root directory of our hard drive which we can put all web applications for this section into.

Lets create a folder for the servlets for this section, in Windows this would be:

double click My Computer icon

double click C:\ drive (or whatever your local drive is)

right click the mouse in the window

from the drop down menu select New

click the Folder option and call the folder _ServletsAdv and press enter.

Within the _ServletsAdv folder we will create separate folders for each web application we use and our first web application will be called contextlisteners

Within the contextlisteners 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 two subfolders called controller and model.

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

contextlisteners directory structure

Coding The DataSource ClassTop

The DataSource class is just a simple class that holds a file name and uses the JavaBeans standard of get<someProperty> and set<someProperty>. For a refresher on JavaBeans you can find information in the Java section at Encapsulation - Getters & Setters.

Cut and paste the following code into your text editor and save it in the   c:\_ServletsAdv\contextlisteners\src\model directory as DataSource.java.


package model;

public class DataSource {

    private String fileName;
    
    // Constructor
    public DataSource(String fileName) { 
        this.fileName = fileName;
    }
    // Getters and setters
    public String getFileName() { 
        return fileName;
    }
    public void setFileName(String fileName) { 
        this.fileName = fileName;
    }
}

Compiling The DataSource Class

Open your command line editor:

Change to directory  c:\_ServletsAdv\contextlisteners\src\model

Compile DataSource.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 DataSource.java

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

compile DataSource class

Coding The ListenersTop

We are now ready to code our listeners and we will code the ServletContextListener implementation first.

Compiling ImplServletContextListener

The ImplServletContextListener class implements the contextInitialized() and contextDestroyed() methods of the ServletContextListener interface. We extract the context initialisation parameter and create a DataSource object from the context. We also create a context attribute containing the create DataSource object and output a few simple messages to the console.

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


package controller;
import javax.servlet.*;
import model.DataSource;

public class ImplServletContextListener implements ServletContextListener {

    @Override
    public void contextInitialized(ServletContextEvent event) { 
        // Write to console
        System.out.println("Within the contextInitialized() method"); 
        // Get ServletContext using event
        ServletContext sc = event.getServletContext(); 
        // Get data source intital parameter using ServletContext
        String fileName = sc.getInitParameter("datasource"); 
        // Create an arbitrary DataSource source object
        DataSource ds = new DataSource(fileName); 
        // Set ServletContext attribute
        sc.setAttribute("datasource", ds);
    }

    @Override
    public void contextDestroyed(ServletContextEvent event) { 
        // Write to console
        System.out.println("Within the contextDestroyed() method"); 
    }
}

Compiling ImplServletContextListener

Open your command line editor:

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

Compile ImplServletContextListener.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 ImplServletContextListener.java

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

compile ImplServletContextListener class
Compiling ServletContextAttributeListener

Our second listener is for the implementation of the ServletContextAttributeListener interface. The ImplServletContextAttributeListener class implements the attributeAdded(), attributeRemoved() and attributeReplaced() methods of the ServletContextAttributeListener interface. We write the name of the context parameter and its old or new value to the console along with information about the method used.

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


package controller;
import javax.servlet.*;
import model.DataSource;

public class ImplServletContextAttributeListener implements ServletContextAttributeListener {

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

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

    @Override
    public void attributeReplaced(ServletContextAttributeEvent event) { 
        // Write to console
        System.out.println("Within the attributeReplaced() method"); 
        // Get attribute name and value
        String attrName = event.getName();
        DataSource ds = (DataSource) event.getValue();
        System.out.println("Context attribute replaced. Name: " + attrName + " Old value: " 
                + ds.getFileName());
    }
}

Compiling ImplServletContextAttributeListener

Open your command line editor:

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

Compile ImplServletContextListener.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 ImplServletContextAttributeListener.java

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

compile ImplServletContextAttributeListener class

Coding CtxtListenersServletTop

We are now ready to code up a simple servlet that gets the DataSource created in the ImplServletContextListener listener implementation and to also make sure our ImplServletContextAttributeListener writes out messages on context attribute change events.

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


package controller;
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.*;
import javax.servlet.http.*;
import model.DataSource;

public class CtxtListenersServlet 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 datasource datasourceattribute
        DataSource ds = (DataSource) getServletContext().getAttribute("datasource");
        System.out.println("Context attribute stored on context initialisation: " + ds.getFileName());
        // Create a new DataSource object and replace ServletContext datasource attribute
        DataSource ds2 = new DataSource("anotherFile.txt");
        getServletContext().setAttribute("datasource", ds2);
        // Remove ServletContext datasource attribute
        getServletContext().removeAttribute("datasource");
    }
}

Compiling CtxtListenersServlet

Open your command line editor:

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

Compile CtxtListenersServlet.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 CtxtListenersServlet.java

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

compile CtxtListenersServlet class

Coding The DDTop

This DD has a new element we haven't seen before, the <listener> top-level element.


<?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">
   <context-param>
      <param-name>datasource</param-name>
      <param-value>file.txt</param-value>
   </context-param>
   <listener>
      <listener-class>controller.ImplServletContextListener</listener-class>
   </listener>
   <listener>
      <listener-class>controller.ImplServletContextAttributeListener</listener-class>
   </listener>
   <servlet>
      <servlet-name>CtxtListeners</servlet-name>
      <servlet-class>controller.CtxtListenersServlet</servlet-class>
   </servlet>
   <servlet-mapping>
      <servlet-name>CtxtListeners</servlet-name>
      <url-pattern>/example</url-pattern>
   </servlet-mapping>
</web-app>

Save the web.xml file in the DD folder.

The <listener> ElementTop

The top-level <listener> element is optional and can appear in the DD mutiple times.

Within <listener>, the <listener-class> sub-level element is optional, can only appear once and represents the fully qualifed name of the listener class. There is no need to state which kind of listener is being used as the web container works this out using the Java Reflection API, which is beyond the scope of these tutorials.

The listeners are called in top-down order which may be of importance if you have more than one listener class implementing the same interface and care about invocation order. On shutdown the order is reversed, so you can think of it as a Last-In-First-Out (LIFO) sequence.

Tomcat DeploymentTop

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 contextlisteners

Within the contextlisteners 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\contextlisteners folder should look something like the following screenshot:

Tomcat directory structure
Testing Our ServletTop

Open a command prompt and change the directory to the location of our Tomcat bin directory and then type in startup (Windows 7) or startup.sh (Linux/Unix/OSX). Press Enter and the Tomcat 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.

Ok we should see some entries in the Tomcat logs on deployment as we added listeners for context initialisation and we also added a new context attribute. These listeners are for the application and will be invoked before any servlets are initialised. The following screenshot shows the System.out.println messages we sent to the console, which appear in Tomcat server window. I have highlighted the relevant lines in yellow so you can see them easier.

  1. For application startup via the implemented ServletContextListener.
  2. For adding a context attribute via the implemented ServletContextAttributeListener.
Deploy contextlisteners App

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

  http://localhost:8080/contextlisteners/example

The web browser should be directed to the CtxtListenersServlet servlet class within Tomcat and execute. We won't see a web page as we didn't render any HTML tags, but we should see some new entries in the Tomcat logs (at the bottom) as we added listeners for context attribute replacement and removal. The following screenshot shows the System.out.println messages we sent to the console from the CtxtListenersServlet servlet, which appear in the Tomcat server window. I have highlighted the relevant lines in yellow so you can see them easier.

Run CtxtListenersServlet App

As you can see from the two screenshots above we took a context initialisation parameter and created a DataSource object from it, which we then used to create a context attribute. All this was achieved at application deployment via our implemented listeners before any servlets had run. Using declarative programming in this way enables us to change entities within our web applications via the DD without having to alter any servlet code.

Lesson 1 Complete

In this lesson we looked at context listeners and some uses for them.

What's Next?

In the next lesson we look at request listeners, their event types and how to use them.

go to home page Homepage go to top of page Top