You’re “promoted” to sales manager. (OK, ok, so that is too horrible a fate to contemplate. All right then, you are asked to help the sales manager.) You want to track buying patterns for a specific item (a yacht, in this case). Of course, you could try to find all servlets and JSP pages that process orders and change each one to record yacht purchases. That’s an awful lot of work for what sounds like a simple request, though. Pretty hard to maintain, anyhow.
A much better option is to create a session attribute listener that monitors the attributes corresponding to order reservations or purchases and that records the information in the log file for later perusal by the sales manager.
The following steps summarize a listener that accomplishes this task.
1. |
Implement the HttpSessionAttributeListener interface.
Listing 10.26 shows a class (YachtWatcher) that implements this interface. |
2. |
Override attributeAdded, attributeReplaced, and attributeRemoved.
The first of these (attributeAdded) is used to log the fact that a yacht was reserved (tentative) or purchased (permanent). The other two methods are used to print retractions of order reservations (but not purchases—all sales are final). |
3. |
Obtain references to the attribute name, attribute value, session, and servlet context.
Each of the three methods calls getName and getValue on its HttpSessionBindingEvent argument to obtain the name and value of the modified attribute. The methods also call getServletContext on the session object (obtained with getSession) to get a reference to the servlet context. |
4. |
Use the objects.
The attribute name is compared to "orderedItem" (attribute addition, replacement, and removal) and "purchasedItem" (attribute addition only). If the name matches, then the attribute value is compared to "yacht". If that comparison also succeeds, then the log method of the servlet context is called. |
5. |
Declare the listener.
Listing 10.27 shows the web.xml file. It declares the listener with the listener and listener-class elements, as below. <listener> <listener-class> moreservlets.listeners.YachtWatcher </listener-class> </listener> |
Listings 10.28 and 10.29 show a servlet that handles orders and an HTML form that sends it data, respectively. Figures 10-16 through 10-19 show the results. Listing 10.30 shows a portion of the resultant log file.
package moreservlets.listeners; import java.io.*; import javax.servlet.*; import javax.servlet.http.*; /** Listener that keeps track of yacht purchases by monitoring * the orderedItem and purchasedItem session attributes. */ public class YachtWatcher implements HttpSessionAttributeListener { private String orderAttributeName = "orderedItem"; private String purchaseAttributeName = "purchasedItem"; private String itemName = "yacht"; /** Checks for initial ordering and final purchase of * yacht. Records "Customer ordered a yacht" if the * orderedItem attribute matches "yacht". * Records "Customer finalized purchase of a yacht" if the * purchasedItem attribute matches "yacht". */ public void attributeAdded(HttpSessionBindingEvent event) { checkAttribute(event, orderAttributeName, itemName, " ordered a "); checkAttribute(event, purchaseAttributeName, itemName, " finalized purchase of a "); } /** Checks for order cancellation: was an order for "yacht" * cancelled? Records "Customer cancelled an order for * a yacht" if the orderedItem attribute matches "yacht". */ public void attributeRemoved(HttpSessionBindingEvent event) { checkAttribute(event, orderAttributeName, itemName, " cancelled an order for a "); } /** Checks for item replacement: was "yacht" replaced * by some other item? Records "Customer changed to a new * item instead of a yacht" if the orderedItem attribute * matches "yacht". */ public void attributeReplaced(HttpSessionBindingEvent event) { checkAttribute(event, orderAttributeName, itemName, " changed to a new item instead of a "); } private void checkAttribute(HttpSessionBindingEvent event, String orderAttributeName, String keyItemName, String message) { String currentAttributeName = event.getName(); String currentItemName = (String)event.getValue(); if (currentAttributeName.equals(orderAttributeName) && currentItemName.equals(keyItemName)) { ServletContext context = event.getSession().getServletContext(); context.log("Customer" + message + keyItemName + "."); } } } |
<?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> <!-- ... --> <!-- Register the yacht-watching event listener. --> <listener> <listener-class> moreservlets.listeners.YachtWatcher </listener-class> </listener> <!-- ... --> <!-- Assign the name OrderHandlingServlet to moreservlets.OrderHandlingServlet. --> <servlet> <servlet-name>OrderHandlingServlet</servlet-name> <servlet-class> moreservlets.OrderHandlingServlet </servlet-class> </servlet> <!-- ... --> <!-- Assign the URL /HandleOrders to the servlet that is named OrderHandlingServlet. --> <servlet-mapping> <servlet-name>OrderHandlingServlet</servlet-name> <url-pattern>/HandleOrders</url-pattern> </servlet-mapping> <!-- ... --> </web-app> |
package moreservlets; import java.io.*; import javax.servlet.*; import javax.servlet.http.*; /** Servlet that handles submissions from the order form. If the * user selects the "Reserve Order" button, the selected item * is put into the orderedItem attribute. If the user selects * the "Cancel Order" button, the orderedItem attribute is * deleted. If the user selects the "Purchase Item" button, * the selected item is put into the purchasedItem attribute. */ public class OrderHandlingServlet extends HttpServlet { private String title, picture; public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { HttpSession session = request.getSession(true); String itemName = request.getParameter("itemName"); if ((itemName == null) || (itemName.equals(""))) { itemName = "<B>MISSING ITEM</B>"; } String message; if (request.getParameter("order") != null) { session.setAttribute("orderedItem", itemName); message = "Thanks for ordering " + itemName + "."; } else if (request.getParameter("cancel") != null) { session.removeAttribute("orderedItem"); message = "Thanks for nothing."; } else { session.setAttribute("purchasedItem", itemName); message = "Thanks for purchasing " + itemName + "."; } response.setContentType("text/html"); PrintWriter out = response.getWriter(); String docType = "<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 " + "Transitional//EN"> "; out.println (docType + "<HTML> " + "<HEAD><TITLE>" + message + "</TITLE></HEAD> " + "<BODY BGCOLOR="#FDF5E6"> " + "<H2 ALIGN="CENTER">" + message + "</H2> " + "</BODY></HTML>"); } } |
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<HTML>
<HEAD>
<TITLE>Orders</TITLE>
<LINK REL=STYLESHEET
HREF="events-styles.css"
TYPE="text/css">
</HEAD>
<BODY>
<TABLE BORDER=5 ALIGN="CENTER">
<TR><TH CLASS="TITLE">Orders
</TABLE>
<P>
Choose a valuable item below.
<P>
Select "Reserve Order" to hold the order for 30 days. Due to
unprecedented demand, you can only reserve a single item:
selecting another item will replace the previous choice.
<P>
Select "Purchase Item" to finalize your purchase. After
finalizing a purchase, you can reserve a new item.
<FORM ACTION="HandleOrders">
<DL>
<DT><B>Item:</B>
<DD><INPUT TYPE="RADIO" NAME="itemName" VALUE="yacht">Yacht
<DD><INPUT TYPE="RADIO" NAME="itemName" VALUE="chalet">Chalet
<DD><INPUT TYPE="RADIO" NAME="itemName" VALUE="car">Lamborghini
<DD><INPUT TYPE="RADIO" NAME="itemName" VALUE="msajsp" CHECKED>
<I>More Servlets and JavaServer Pages</I>
<DD><INPUT TYPE="RADIO" NAME="itemName" VALUE="csajsp">
<I>Core Servlets and JavaServer Pages</I>
</DL>
<CENTER>
<INPUT TYPE="SUBMIT" NAME="order" VALUE="Reserve Order">
<INPUT TYPE="SUBMIT" NAME="cancel" VALUE="Cancel Order">
<INPUT TYPE="SUBMIT" NAME="purchase" VALUE="Purchase Item">
</CENTER>
</FORM>
</BODY>
</HTML> |
2001-11-07 11:50:59 Customer ordered a yacht. 2001-11-07 11:51:06 Customer changed to a new item instead of a yacht. 2001-11-07 11:52:37 Customer cancelled an order for a yacht. 2001-11-07 11:53:05 Customer finalized purchase of a yacht. 2001-11-07 11:53:35 Customer ordered a yacht. 2001-11-07 11:53:50 Customer cancelled an order for a yacht. 2001-11-07 11:54:20 Customer changed to a new item instead of a yacht. 2001-11-07 11:54:27 Customer changed to a new item instead of a yacht. 2001-11-07 11:54:42 Customer cancelled an order for a yacht. 2001-11-07 11:54:44 Customer ordered a yacht. 2001-11-07 11:54:47 Customer changed to a new item instead of a yacht. |
18.189.188.121