A ServletContext listener is useful when you need to perform an action upon application start-up or shutdown, such as initialize application wide variables from a data store.
Let’s look at what Java EE classes we’ll be using for this demonstration: ServletContextEvent and ServletContextListener
// This is the event class for notifications about changes
// to the servlet context of a web application.
import javax.servlet.ServletContextEvent;
// Implementations of this interface receive notifications
// about changes to the servlet context of the web
// application they are part of. To receive notification
// events, the implementation class must be configured in
// the deployment descriptor for the web application.
import javax.servlet.ServletContextListener;
Our first step is to create a class that implements the ServletContextListener interface. There are only two methods that require implementations: contextInitialized and contextDestroyed.
From the Javadoc:
void contextInitialized(ServletContextEvent sce)
-
Notification that the web application initialization process is starting. All ServletContextListeners are notified of context initialization before any filter or servlet in the web application is initialized.
-
void contextDestroyed(ServletContextEvent sce)
-
Notification that the servlet context is about to be shut down. All servlets and filters have been destroy()ed before any ServletContextListeners are notified of context destruction.
Below is our listener class. You’ll notice that I’ve included a @PersistenceUnit annotation. Since context listeners are created by the servlet container, all dependency injections occur as requested.
package com.manko.servlet.listener;
public class MyAwesomeContextListener implements ServletContextListener {
/* Needed in order to get the application values from our data store */
@PersistenceUnit
private EntityManagerFactory emf;
@Override
public void contextInitialized(ServletContextEvent sce) {
}
@Override
public void contextDestroyed(ServletContextEvent sce) {
}
}
Now, let’s add code to contextInitialized. Assuming we have an entity class ApplicationConfiguration
EntityManager em = null;
Query query = null;
Hashtable table = null;
try {
// Get configuration entries
em = emf.createEntityManager();
query = em.createNamedQuery("ApplicationConfiguration.findAll");
List<ApplicationConfiguration> configs = (List<ApplicationConfiguration>) query.getResultList();
// Put them in a Hashtable for easy reference
table = new Hashtable(configs.size());
for (ApplicationConfiguration config:configs){
table.put(config.getId(), config.getValue());
}
// Save the Hashtable as a ServerContext variable
sce.getServletContext().setAttribute("MyApplicationConfiguration", table);
} catch (Excception e) {
// do stuff
}
em = null;
query = null;
table = null;
Of course, simply coding a context listener is meaningless without informing the container. There are two ways to accomplish this.
- If you are running within a version 2.5 servlet container, an xml deployment descriptor is your only option.
- For version 3.0 containers, you may annotate your class with @WebListener
v2.5 (web.xml – Glassfish 2.1 for example):
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5"
xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
<listener>
<listener-class>com.manko.servlet.listener.MyAwesomeContextListener</listener-class>
</listener>
</web-app>
v3.0 (annotations – Glassfish 3.0 for example):
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.annotation.WebListener;
@WebListener
public class MyAwesomeContextListener implements ServletContextListener
IMPORTANT – This is from the Servlet 3.0 specification (p180):
The web application deployment descriptor contains a metadata-complete attribute on the web-app element. The metadata-complete attribute defines whether the web.xml descriptor is complete, or whether other sources of metadata used by the deployment process should be considered. Metadata may come from the web.xml file, web-fragment.xml files, annotations on class files in WEB-INF/classes, and annotations on classes in jar files in the WEB-INF/lib directory. If metadata-complete is set to “true”, the deployment tool only examines the web.xml file and must ignore annotations such as @WebServlet, @WebFilter, and @WebListener present in the class files of the application, and must also ignore any web-fragment.xml descriptor packaged in a jar file in WEB-INF/lib. If the metadata-complete attribute is not specified or is set to “false”, the deployment tool must examine the class files and web-fragment.xml files for metadata,as previously specified.
That’s it! We now have a servlet context listener in our application. Please, do yourself a favor and read the Servlet 3.0 specification.