- Monitoring Creation and Destruction of the Servlet Context
- Example: Initializing Commonly Used Data
- Detecting Changes in Servlet Context Attributes
- Example: Monitoring Changes to Commonly Used Data
- Packaging Listeners with Tag Libraries
- Example: Packaging the Company Name Listeners
- Recognizing Session Creation and Destruction
- Example: A Listener That Counts Sessions
- Watching for Changes in Session Attributes
- Example: Monitoring Yacht Orders
- Using Multiple Cooperating Listeners
- The Complete Events Deployment Descriptor
10.2 Example: Initializing Commonly Used Data
Suppose that you are developing a Web site for a dot-com company that is a hot commodity. So hot, in fact, that it is constantly being bought out by larger companies. As a result, the company name keeps changing. Rather than changing zillions of separate servlets and JSP pages each time you change the company name, you could read the company name when the Web application is loaded, store the value in the servlet context, and design all your servlets and JSP pages to read the name from this location. To prevent confusion among customers, the site can also prominently display the former company name, initializing and using it in a manner similar to the current company name.
The following steps summarize a listener that accomplishes this task.
Implement the ServletContextListener interface. Listing 10.1 shows a class (InitialCompanyNameListener) that implements this interface.
Override contextInitialized and contextDestroyed. The InitialCompanyNameListenerclass uses context-Initializedto read the current and former company names and store them in the servlet context. Since the contextDestroyed method is not needed, an empty body is supplied.
Obtain a reference to the servlet context. The context-Initializedmethod calls getServletContexton the ServletContextEventargument and stores the result in the contextlocal variable.
Use the servlet context. The listener needs to read the company-Nameand formerCompanyNameinitialization parameters and store them in a globally accessible location. So, it calls getInit-Parameteron the context variable, checks for missing values, and uses setAttributeto store the result in the servlet context.
Declare the listener. The listener is declared in the deployment descriptor with the listenerand listener-classelements, as below.
<listener> <listener-class> moreservlets.listeners.InitialCompanyNameListener </listener-class> </listener>
The web.xml file is shown in Listing 10.2.
Provide any needed initialization parameters. The company-Nameand formerCompanyNameinit parameters are defined in web.xml (Listing 10.2) as follows.
<context-param> <param-name>companyName</param-name> <param-value>not-dot-com.com</param-value> </context-param> <context-param> <param-name>formerCompanyName</param-name> <param-value>hot-dot-com.com</param-value> </context-param>
Listings 10.3 and 10.4 present two JSP pages that use the predefined application variable (i.e., the servlet context) to access the companyName and former-CompanyName attributes. Figures 101 and 102 show the results. See Section 3.3 for a full list of the predefined JSP variables (request, response, application, etc.).
Figures 101 Home page for the company with the frequently changing name.
Figures 102 Informational page for the company with the frequently changing name.
Listing 10.1 InitialCompanyNameListener.java
package moreservlets.listeners; import java.io.*; import javax.servlet.*; import javax.servlet.http.*; /** Listener that looks up the name of the company when * the Web application is first loaded. Stores this * name in the companyName servlet context attribute. * Various servlets and JSP pages will extract it * from that location. * <P> * Also looks up and stores the former company name and * stores it in the formerCompanyName attribute. */ public class InitialCompanyNameListener implements ServletContextListener { private static final String DEFAULT_NAME = "MISSING-COMPANY-NAME"; /** Looks up the companyName and formerCompanyName * init parameters and puts them into the servlet context. */ public void contextInitialized(ServletContextEvent event) { ServletContext context = event.getServletContext(); setInitialAttribute(context, "companyName", DEFAULT_NAME); setInitialAttribute(context, "formerCompanyName", ""); } public void contextDestroyed(ServletContextEvent event) {} // Looks for a servlet context init parameter with a given name. // If it finds it, it puts the value into a servlet context // attribute with the same name. If the init parameter is missing, // it puts a default value into the servlet context attribute. private void setInitialAttribute(ServletContext context, String initParamName, String defaultValue) { String initialValue = context.getInitParameter(initParamName); if (initialValue != null) { context.setAttribute(initParamName, initialValue); } else { context.setAttribute(initParamName, defaultValue); } } /** Static method that returns the servlet context * attribute named "companyName" if it is available. * Returns a default value if the attribute is unavailable. */ public static String getCompanyName(ServletContext context) { String name = (String)context.getAttribute("companyName"); if (name == null) { name = DEFAULT_NAME; } return(name); } /** Static method that returns the servlet context * attribute named "formerCompanyName" if it is available. * Returns an empty string if the attribute is * unavailable. */ public static String getFormerCompanyName (ServletContext context) { String name = (String)context.getAttribute("formerCompanyName"); if (name == null) { name = ""; } return(name); } }
Listing 10.2 web.xml (Excerpt for initial company name listener)
<?xml version="1.0" encoding="ISO-8859-1"?> <!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" "http://java.sun.com/dtd/web-app_2_3.dtd"> <web-app> <!-- Since the company name changes so frequently, supply it as a servlet context parameter instead of embedding it into lots of different servlets and JSP pages. The InitialCompanyNameListener will read this value and store it in the servlet context. --> <context-param> <param-name>companyName</param-name> <param-value>not-dot-com.com</param-value> </context-param> <!-- Also store the previous company name. --> <context-param> <param-name>formerCompanyName</param-name> <param-value>hot-dot-com.com</param-value> </context-param> <!-- ... --> <!-- Register the listener that sets up the initial company name. --> <listener> <listener-class> moreservlets.listeners.InitialCompanyNameListener </listener-class> </listener> <!-- ... --> <!-- If URL gives a directory but no filename, try index.jsp first and index.html second. If neither is found, the result is server specific (e.g., a directory listing). Order of elements in web.xml matters. welcome-file-list needs to come after servlet but before error-page. --> <welcome-file-list> <welcome-file>index.jsp</welcome-file> <welcome-file>index.html</welcome-file> </welcome-file-list> <!-- ... --> </web-app>
Listing 10.3 index.jsp
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> <HTML> <HEAD> <%@ page import="moreservlets.listeners.*" %> <% String companyName = InitialCompanyNameListener.getCompanyName(application); String formerCompanyName = InitialCompanyNameListener.getFormerCompanyName(application); String formerCompanyDescription = ""; if (!formerCompanyName.equals("")) { formerCompanyDescription = "(formerly " + formerCompanyName + ")"; } %> <TITLE><%= companyName %></TITLE> <LINK REL=STYLESHEET HREF="events-styles.css" TYPE="text/css"> </HEAD> <BODY> <TABLE BORDER=5 ALIGN="CENTER"> <TR><TH CLASS="TITLE"> <%= companyName %><BR> <%= formerCompanyDescription %> </TABLE> <P> Welcome to the home page of <B><%= companyName %></B> <%= formerCompanyDescription %> <P> <B><%= companyName %></B> is a high-flying, fast-growing, big-potential company. A perfect choice for your retirement portfolio! <P> Click <A HREF="company-info.jsp">here</A> for more information. </BODY> </HTML> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> <HTML> <HEAD> <%@ page import="moreservlets.listeners.*" %> <% String companyName = InitialCompanyNameListener.getCompanyName(application); String formerCompanyName = InitialCompanyNameListener.getFormerCompanyName(application); String formerCompanyDescription = ""; if (!formerCompanyName.equals("")) { formerCompanyDescription = "(formerly " + formerCompanyName + ")"; } %>
Listing 10.4 company-info.jsp
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> <HTML> <HEAD> <%@ page import="moreservlets.listeners.*" %> <% String companyName = InitialCompanyNameListener.getCompanyName(application); String formerCompanyName = InitialCompanyNameListener.getFormerCompanyName(application); String formerCompanyDescription = ""; if (!formerCompanyName.equals("")) { formerCompanyDescription = "(formerly " + formerCompanyName + ")"; } %> <TITLE><%= companyName %></TITLE> <LINK REL=STYLESHEET HREF="events-styles.css" TYPE="text/css"> </HEAD> <BODY> <TABLE BORDER=5 ALIGN="CENTER"> <TR><TH CLASS="TITLE"> <%= companyName %><BR> <%= formerCompanyDescription %> </TABLE> <P> Learn more about <B><%= companyName %></B> <%= formerCompanyDescription %> <UL> <LI><A HREF="products.jsp"><%= companyName %> products</A> <LI><A HREF="services.jsp"><%= companyName %> services</A> <LI><A HREF="history.jsp"><%= companyName %> history</A> <LI><A HREF="invest.jsp">investing in <%= companyName %></A> <LI><A HREF="contact.jsp">contacting <%= companyName %></A> </UL> .</BODY> </HTML>