Home > Articles > Programming > Java

  • Print
  • + Share This
This chapter is from the book

10.10 Example: Monitoring Yacht Orders

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 getValueon its HttpSessionBindingEventargument to obtain the name and value of the modified attribute. The methods also call getServletContexton the session object (obtained with get-Session) to get a reference to the servlet context.

  4. Use the objects. The attribute name is compared to "ordered-Item"(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 logmethod of the servlet context is called.

  5. Declare the listener. Listing 10.27 shows the web.xml file. It declares the listener with the listenerand listener-classele-ments, 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.

Figures 10–16 The order form that sends data to the order handling servlet (Listing 10.28). That servlet adds, replaces, and removes values in the orderedItem and purchasedItem session attributes, which in turn triggers the yacht-watching listener (Listing 10.26).

Figures 10–17 Result of reserving an order for a yacht. The yacht-watching listener makes an entry in the log file (Listing 10.30) saying that a customer ordered a yacht.

Figures 10–18 Result of cancelling an order. If the user had previously reserved an order for a yacht, the yacht-watching listener makes an entry in the log file (Listing 10.30) saying that a customer replaced a yacht order with something else.

Figures 10–19 Result of purchasing a yacht. The yacht-watching listener makes an entry in the log file (Listing 10.30) saying that a customer purchased a yacht.

Listing 10.26 YachtWatcher.java

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 + ".");
   }
  }
}

Listing 10.27 web.xml (Excerpt for yacht-watching 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>
  <!-- ... -->

  <!-- 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>

Listing 10.28 OrderHandlingServlet.java

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\">\n";
   out.println
     (docType +
     "<HTML>\n" +
     "<HEAD><TITLE>" + message + "</TITLE></HEAD>\n" +
     "<BODY BGCOLOR=\"#FDF5E6\">\n" +
     "<H2 ALIGN=\"CENTER\">" + message + "</H2>\n" +
     "</BODY></HTML>");
   }
}

Listing 10.29 orders.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>

Listing 10.30 Sample Log File Entries

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.
  • + Share This
  • 🔖 Save To Your Account