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 |
---|---|---|
ServletContext | ServletContext | You want to know when a context has been created or destroyed. |
ServletContext | ServletContext | You 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( ServletContext | Receive notification that a new attribute has been added to the servlet context. |
void attributeRemoved( ServletContext | Receive notification that an existing attribute has been removed from the servlet context. |
void attributeReplaced( ServletContext | 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:
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.
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.
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.
Coding CtxtListenersServlet
Top
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.
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:
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.
- For application startup via the implemented
ServletContextListener
. - For adding a context attribute via the implemented
ServletContextAttributeListener
.
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.
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.