[ Team LiB ] Previous Section Next Section

Application Lifecycle Events

You can imagine that there are resources that are shared among JSPs and servlets. For example, there might be a common facility to perform logging, or perhaps some global initialization data. The ServletContext object is frequently used to provide access to shared services or resources. Using it, Web application developers can obtain initialization parameters, store attributes by name, and access resources such as GIFs that have been packaged in the WAR file.

During the lifecycle of an application, other objects come into play also. You have worked with the ServletRequest, for example. Although, so far you've only worked with short-lived requests that are serviced by a single JSP or servlet, a ServletRequest can interact with a number of Web application components. And, although we haven't discussed it yet, the HttpSession object is another that may persist beyond the service methods of a JSP or servlet.

In particular, you can monitor changes in attributes or the lifecycle of these objects. Collectively, the objects and operations that provide this capability are known as the application event facilities.

Using Listeners

A servlet context is created by a container when an application starts up. By implementing ServletContextListener, you can perform actions relating to the initialization and closing of the application. The methods of ServletContextListener are


public void contextInitialized ( ServletContextEvent sce );
public void contextDestroyed ( ServletContextEvent sce );

A container will invoke contextInitialized when the application is created and contextDestroyed when it is shut down. The parameter, ServletContextEvent, provides access to the servlet context.

Listing 5.3 is an example of a ServletContextListener that records information to a system log when an application starts up or is shut down.

Listing 5.3 Source Code for MyAppListener.java
 1:  package examples;
 2:
 3:  import java.io.*;
 4:  import javax.servlet.*;
 5:  import javax.servlet.http.*;
 6:
 7:  public class MyAppListener
 8:          implements ServletContextListener {
 9:
10:      public void contextInitialized(ServletContextEvent event) {
11:          ServletContext context = event.getServletContext();
12:          context.log("***ShowLifecycles - Created the servlet context");
13:      }
14:
15:      public void contextDestroyed(ServletContextEvent event) {
16:          ServletContext context = event.getServletContext();
17:          context.log("***ShowLifecycles - Destroyed the servlet context");
18:      }
19:  }

In each case this simple example obtains the servlet context from the ServletContextEvent and outputs text into one of the container's logs.

Listing 5.4 is a companion JSP that logs its own lifecycle events.

Listing 5.4 Source Code for ShowLifecycles.jsp
 1:  <html>
 2:  <body>
 3:
 4:  <%!
 5:      public void jspInit()
 6:      {
 7:          log("***ShowLifecycles.jsp  - Invoked jspInit()");
 8:      }
 9:  %>
10:  <%!
11:      public void jspDestroy()
12:      {
13:          log("***ShowLifecycles.jsp - Invoked jspDestroy()");
14:      }
15:  %>
16:
17:      log("***ShowLifecycles.jsp - Invoked jspService()");
18:  %>
19:
20:  The current date is: <%= new java.util.Date() %>
21:  </body>
22:  </html>

The only thing tricky about this JSP is the log method itself. Reading the JSP specification, you might note that there is no specific mention of the log method. However, remember that a JSP ultimately becomes a servlet; log is a method of GenericServlet, which in most cases is a superclass of the servlet generated by the JSP container.

For Your Convenience

graphics/bytheway_icon.gif

The log method is actually a shortcut method. It's usually equivalent to the log method that is part of the ServletContext and saves you the trouble of having to call getServletContext().log().


Since the container must somehow know about a ServletContextListener that is defined for an application, you would expect that you have to add an entry into the application deployment descriptor. Listing 5.5 show the content of web.xml for this application:

Listing 5.5 Source Code for web.xml
 1:  <?xml version="1.0" encoding="ISO-8859-1"?>
 2:  <web-app xmlns="http://java.sun.com/xml/ns/j2ee"
 3:      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 4:      xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
 5:      http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"
 6:      version="2.4">
 7:      <display-name>ShowLifecycles</display-name>
 8:      <description>An example of how to use lifecycle events</description>
 9:
10:      <listener>
11:          <listener-class>
12:              examples.MyAppListener
13:          </listener-class>
14:      </listener>
15:  </web-app>

This is the first time you've seen a deployment descriptor associated with a JSP. It's necessary because we're defining a Web application that includes a JSP and a ServletContextListener. Fortunately, the deployment descriptor doesn't look terribly different. The only part of it that is new to you is the listener element, which defines the class that responds to lifecycle events for the application.

After compiling MyAppListener.java, the WAR file is created by placing the files in the directories as shown:


ShowLifecycles.jsp
WEB-INF/web.xml
WEB-INF/classes/examples/MyAppListener.class

The jar utility neatly packages these into a WAR file using the command


jar cfv ShowLifecycles.war *

The application can now be deployed. If you use Tomcat's application manager, it's easy to deploy the application; and you will be able to stop the application so that you can see the results when the servlet context is destroyed.

To start the application, point your browser to

http://localhost:8080/ShowLifecycles/ShowLifecycles.jsp

Understanding Context Paths

graphics/bytheway_icon.gif

Remember that Tomcat adds a URL prefix. In this case, because the WAR file was named ShowLifecycles.war, the URL prefix is /ShowLifecycles. This is actually a context path, which is used to identify the context programmatically.


What we are interested in is in the container's log files. For Tomcat you'll find them in logs/. The particular file will be named localhost_log.date.txt, where date is the date the log was created. Of course, you'll want the most recent one. Other servlet containers put logs in different places. Check your documentation for the location and names.

If you examine the log for your JSP/servlet container, you will see entries that look like this:


2003-05-16 12:45:08 HTMLManager: install: Installing web application at 'null'
     from  'jar:file:/opt/jakarta-tomcat-5/webapps/ShowLifecycles.war!/'
2003-05-16 12:45:08 ***ShowLifecycles - Created the servlet context
2003-05-16 12:45:58 jsp: ***ShowLifecycles.jsp - Invoked jspInit()
2003-05-16 12:45:58 jsp: ***ShowLifecycles.jsp - Invoked _jspService()
2003-05-16 12:46:08 HTMLManager: stop: Stopping web application at
        '/ShowLifecycles'
2003-05-16 12:46:08 ***ShowLifecycles - Destroyed the servlet contex
2003-05-16 12:46:08 jsp: ***ShowLifecycles.jsp - Invoked jspDestroy()

Here you can see that the following steps occurred:

  1. The ShowLifecycles application was installed.

  2. The servlet context was created at the same time.

  3. The JSP was loaded and initialized.

  4. The JSP's jspService method was invoked.

  5. If you stopped the application, the servlet context was destroyed.

  6. jspDestroy was invoked in the JSP.

In addition to receiving notifications about application lifecycle events, you can also find out when an attribute that is associated with the application is added, changed, or removed. Simply implement the ServletContextAttributeListener and add the listener to the deployment descriptor in the same way you did for the example. Attributes are discussed in additional detail in Hour 6.

Following the same pattern, you can observe lifecycle events and attribute changes for ServletRequest and HttpSession objects.

Using a ServletRequestListener, you can discover when a request has started to be processed by your application.

AServletRequestAttributeListener will let you know when an attribute is added, modified, or deleted from a ServletRequest.

An HttpSession object is used to create a session between an HTTP client and server that lasts across multiple requests. In essence, it provides a way to store the state of an application or user while using the stateless HTTP protocol. You'll learn more about HTTP sessions in the next hour. Like its siblings, you can use HttpSessionListener and HttpSessionAttributeListener to track the creation and destruction of a session, or changes to attributes associated with a session.

    [ Team LiB ] Previous Section Next Section