| <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> |
| |
| <html> |
| <head> |
| <meta name="author" content="troy.giunipero@sun.com"> |
| <meta http-equiv="content-type" content="text/html; charset=UTF-8"> |
| <meta name="description" content="This tutorial unit demonstrates how to implement shopping cart functionality into the application."> |
| |
| <meta name="keywords" content="NetBeans, IDE, integrated development environment, |
| Java, Java EE, open source, web technology, e-commerce"> |
| |
| <link rel="stylesheet" type="text/css" href="../../../../netbeans.css"> |
| <link rel="stylesheet" type="text/css" href="../../../../print.css" media="print"> |
| <link rel="stylesheet" type="text/css" href="../../../../lytebox.css" media="screen"> |
| <script type="text/javascript" src="../../../../images_www/js/lytebox-compressed.js"></script> |
| |
| <title>The NetBeans E-commerce Tutorial - Managing Sessions</title> |
| </head> |
| |
| <body> |
| |
| <!-- Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved. --> |
| |
| <h1>The NetBeans E-commerce Tutorial - Managing Sessions</h1> |
| |
| <div style="margin-left:-3px"> |
| <div class="feedback-box margin-around float-left" style="margin-right:15px"> |
| |
| <h4>Tutorial Contents</h4> |
| |
| <ol> |
| <li><a href="intro.html">Introduction</a></li> |
| <li><a href="design.html">Designing the Application</a></li> |
| <li><a href="setup-dev-environ.html">Setting up the Development Environment</a></li> |
| <li><a href="data-model.html">Designing the Data Model</a></li> |
| <li><a href="page-views-controller.html">Preparing the Page Views and Controller Servlet</a></li> |
| <li><a href="connect-db.html">Connecting the Application to the Database</a></li> |
| <li><a href="entity-session.html">Adding Entity Classes and Session Beans</a></li> |
| <li><strong>Managing Sessions</strong> |
| |
| <ul style="margin: 5px 0 0 -2em"> |
| <li><a href="#session-data">Handling Session Data</a></li> |
| <li><a href="#debug">Examining Session Data with the Java Debugger</a></li> |
| <li><a href="#session-track">Examining Session Tracking Options</a></li> |
| <li><a href="#time-out">Handling Session Time-Outs</a></li> |
| <li><a href="#seeAlso">See Also</a></li> |
| </ul></li> |
| |
| <li><a href="transaction.html">Integrating Transactional Business Logic</a></li> |
| <li><a href="language.html">Adding Language Support</a></li> |
| <li><a href="security.html">Securing the Application</a></li> |
| <li><a href="test-profile.html">Testing and Profiling</a></li> |
| <li><a href="conclusion.html">Conclusion</a></li> |
| </ol> |
| </div> |
| </div> |
| |
| <p><img src="../../../../images_www/articles/68/netbeans-stamp-68-69.png" class="stamp" |
| alt="Content on this page applies to NetBeans IDE, versions 6.8 and 6.9" |
| title="Content on this page applies to NetBeans IDE, versions 6.8 and 6.9"></p> |
| |
| <p>Every e-commerce application that offers some form of shopping cart functionality |
| needs to be able to remember user-specific data as users click through the website. |
| Unfortunately for you the developer, the HTTP protocol, over which communication |
| on the Internet takes place, is a <em>stateless</em> protocol. Each request received |
| by your server is an independent piece of information that has no relation to previously |
| received requests. Therefore, if a customer clicks a button to add an item to his |
| or her shopping cart, your application must take measures to ensure not only that |
| the state of the user's cart is updated, but that the action doesn't affect the |
| cart of another user who happens to be browsing the site at the same time.</p> |
| |
| <p>In order to properly handle the above-described scenario, you need to implement |
| functionality so that a <em>session</em> can be created and maintained for the |
| duration of a user's visit to the site. Servlet technology, which is the foundation |
| of all Java-based web applications, provides for this with its |
| <a href="http://java.sun.com/javaee/6/docs/api/javax/servlet/http/HttpSession.html" target="_blank"><code>HttpSession</code></a> |
| interface. You also need to define several classes, namely <code>ShoppingCart</code> |
| and <code>ShoppingCartItem</code>, that allow the application to temporarily store |
| user data while the session is being maintained.</p> |
| |
| <p>This tutorial unit takes a different approach from others in the NetBeans E-commerce |
| Tutorial. Instead of having you create project files and providing steps with code |
| snippets for you to copy and paste into your own project, you open the completed |
| project snapshot for this unit, and examine the code using the IDE's debugger and |
| other tools. In the process, you'll learn how to apply an <code>HttpSession</code> |
| object to your code so that each visit to the website results in a dedicated session. |
| You also learn about <em>scoped variables</em>, and their usage in both Java classes |
| and JSP pages. This unit also discusses <code>HttpSession</code>'s default mechanism |
| for maintaining sessions (i.e., cookies) and shows what steps need to be taken in |
| the event that cookies are deactivated in a user's browser. Finally, session time-outs |
| are covered, and the unit demonstrates how to handle them by creating a simple filter |
| that intercepts requests to check whether a session exists.</p> |
| |
| <p>You can view a live demo of the application that you build in this tutorial: |
| <a href="http://services.netbeans.org/AffableBean/" target="_blank">NetBeans E-commerce |
| Tutorial Demo Application</a>.</p> |
| |
| <br style="clear:left;"> |
| |
| <br> |
| <table> |
| <tbody> |
| <tr> |
| <th class="tblheader" scope="col">Software or Resource</th> |
| <th class="tblheader" scope="col">Version Required</th> |
| </tr> |
| <tr> |
| <td class="tbltd1"><a href="https://netbeans.org/downloads/index.html" target="_blank">NetBeans IDE</a></td> |
| <td class="tbltd1">Java bundle, 6.8 or 6.9</td> |
| </tr> |
| <tr> |
| <td class="tbltd1"><a href="http://www.oracle.com/technetwork/java/javase/downloads/index.html" target="_blank">Java Development Kit (JDK)</a></td> |
| <td class="tbltd1">version 6</td> |
| </tr> |
| <tr> |
| <td class="tbltd1"><a href="#glassFish">GlassFish server</a></td> |
| <td class="tbltd1">v3 or Open Source Edition 3.0.1</td> |
| </tr> |
| <tr> |
| <td class="tbltd1"><a href="http://dev.mysql.com/downloads/mysql/" target="_blank">MySQL database server</a></td> |
| <td class="tbltd1">version 5.1</td> |
| </tr> |
| <tr> |
| <td class="tbltd1"><a href="https://netbeans.org/projects/samples/downloads/download/Samples%252FJavaEE%252Fecommerce%252FAffableBean_snapshot5.zip">AffableBean |
| project</a></td> |
| <td class="tbltd1">snapshot 5</td> |
| </tr> |
| </tbody> |
| </table> |
| |
| <p><strong class="notes">Notes:</strong></p> |
| |
| <ul> |
| <li>The NetBeans IDE requires the Java Development Kit (JDK) to run properly. |
| If you do not have any of the resources listed above, the JDK should be |
| the first item that you download and install.</li> |
| |
| <li>The NetBeans IDE Java Bundle includes Java Web and EE technologies, which are |
| required for the application you build in this tutorial.</li> |
| |
| <li id="glassFish">The NetBeans IDE Java Bundle also includes the GlassFish server, |
| which you require for this tutorial. You could |
| <a href="http://glassfish.dev.java.net/public/downloadsindex.html" target="_blank">download |
| the GlassFish server independently</a>, but the version provided with the |
| NetBeans download has the added benefit of being automatically registered with |
| the IDE.</li> |
| |
| <li>You can follow this tutorial unit without having completed previous units. To |
| do so, see the <a href="setup.html">setup instructions</a>, which describe how |
| to prepare the database and establish connectivity between the IDE, GlassFish, |
| and MySQL.</li> |
| </ul> |
| |
| |
| <br> |
| <h2 id="session-data">Handling Session Data</h2> |
| |
| <p>Applications can manage user sessions with the <code>HttpSession</code> object. |
| You can bind user-specific data to the <code>HttpSession</code> object, then access |
| this data at a later stage. Both bind and access actions can be done from Java |
| classes, as well as from session-scoped variables in EL expressions.</p> |
| |
| <ul> |
| <li><a href="#httpSession">Working with an HttpSession Object</a></li> |
| <li><a href="#scopedVariables">Working with Scoped Variables in Web Applications</a></li> |
| </ul> |
| |
| <div class="indent"> |
| <h3 id="httpSession">Working with an HttpSession Object</h3> |
| |
| <p>The <code>AffableBean</code> application uses the <code>HttpSession</code> object |
| to identify users over multiple requests. An <code>HttpSession</code> object is |
| obtained using <code>getSession()</code> on a given request:</p> |
| |
| <pre class="examplecode" style="width:664px; margin-left:10px; margin-top:-2px"> |
| HttpSession session = request.getSession();</pre> |
| |
| <p>If a session object doesn't yet exist for the request, the method creates and returns |
| a new session object.</p> |
| |
| <p>You can use the session object as a vehicle for passing data between requests. You |
| use the <code>setAttribute</code> method to bind objects to the session. Likewise, |
| you use <code>getAttribute</code> to retrieve objects from the session. In the |
| <code>AffableBean</code> application for example, the user's shopping cart is created |
| and bound to the user session in the following manner:</p> |
| |
| <pre class="examplecode" style="width:664px; margin-left:10px; margin-top:-2px"> |
| ShoppingCart cart = new ShoppingCart(); |
| session.setAttribute("cart", cart);</pre> |
| |
| <p>In order to retrieve the cart from the session, the <code>getAttribute</code> method |
| is applied:</p> |
| |
| <pre class="examplecode" style="width:664px; margin-left:10px; margin-top:-2px"> |
| cart = (ShoppingCart) session.getAttribute("cart");</pre> |
| |
| <p>In JSP pages, you can access objects bound to the session using EL expressions. Continuing |
| with the above example, if a <code>ShoppingCart</code> object named '<code>cart</code>' |
| is bound to the session, you can access the object using the following EL expression: |
| |
| <pre class="examplecode" style="width:664px; margin-left:10px; margin-top:-2px">${cart}</pre> |
| |
| <p>Accessing the <code>ShoppingCart</code> object on its own is of little value however. |
| What you really want is a way to access values stored in the object. If you explore |
| the new <code>ShoppingCart</code> class in the project snapshot, you'll note that it |
| contains the following properties:</p> |
| |
| <ul> |
| <li><code>double total</code></li> |
| <li><code>int numberOfItems</code></li> |
| <li><code>List<String, ShoppingCartItem> items</code></li> |
| </ul> |
| |
| <p>Provided that properties have matching getter methods, you can access values for |
| singular properties using simple dot notation in an EL expression. If you examine |
| the <code>cart.jsp</code> page, you'll see that this is exactly how the value for |
| <code>numberOfItems</code> is accessed:</p> |
| |
| <pre class="examplecode" style="width:664px; margin-left:10px; margin-top:-2px"> |
| <p>Your shopping cart contains ${cart.numberOfItems} items.</p></pre> |
| |
| <p>In order to extract data from properties that contain multiple values, such as the |
| above <code>items</code> list, the <code>cart.jsp</code> page uses a <code><c:forEach></code> |
| loop:</p> |
| |
| <pre class="examplecode" style="width:664px; margin-left:10px; margin-top:-2px"> |
| <c:forEach var="cartItem" items="${cart.items}" varStatus="iter"> |
| |
| <c:set var="product" value="${cartItem.product}"/> |
| |
| <tr class="${((iter.index % 2) == 0) ? 'lightBlue' : 'white'}"> |
| <td> |
| <img src="${initParam.productImagePath}${product.name}.png" |
| alt="${product.name}"> |
| </td> |
| |
| <td>${product.name}</td> |
| |
| <td> |
| &euro; ${cartItem.total} |
| <br> |
| <span class="smallText">( &euro; ${product.price} / unit )</span> |
| </td> |
| ... |
| </tr> |
| |
| </c:forEach></pre> |
| |
| <p><code>ShoppingCartItem</code>'s <code>product</code> property identifies the product |
| type for a cart item. The above loop takes advantage of this by first setting a |
| <code>product</code> variable to the expression <code>${cartItem.product}</code>. It |
| then uses the variable to obtain information about that product (e.g., name, price).</p> |
| |
| |
| <h3 id="scopedVariables">Working with Scoped Variables in Web Applications</h3> |
| |
| <p>When working with JSP/Servlet technology, there are four scope objects available to |
| you within the realm of the application. JSP technology implements <em>implicit |
| objects</em> that allows you to access classes defined by the Servlet API.</p> |
| |
| <div class="margin-around"> |
| <table width="688px"> |
| <tr> |
| <th class="tblheader" scope="col">Scope</th> |
| <th class="tblheader" scope="col">Definition</th> |
| <th class="tblheader" scope="col">Servlet Class</th> |
| <th class="tblheader" scope="col">JSP Implicit Object</th> |
| </tr> |
| <tr> |
| <td class="tbltd1"><strong>Application</strong></td> |
| <td class="tbltd1">Global memory for a web application</td> |
| <td class="tbltd1"><code><a href="http://java.sun.com/javaee/6/docs/api/javax/servlet/ServletContext.html" target="_blank">javax.servlet.ServletContext</a></code></td> |
| <td class="tbltd1"><code>applicationScope</code></td> |
| </tr> |
| <tr> |
| <td class="tbltd1"><strong>Session</strong></td> |
| <td class="tbltd1">Data specific to a user session</td> |
| <td class="tbltd1"><code><a href="http://java.sun.com/javaee/6/docs/api/javax/servlet/http/HttpSession.html" target="_blank">javax.servlet.http.HttpSession</a></code></td> |
| <td class="tbltd1"><code>sessionScope</code></td> |
| </tr> |
| <tr> |
| <td class="tbltd1"><strong>Request</strong></td> |
| <td class="tbltd1">Data specific to an individual server request</td> |
| <td class="tbltd1"><code><a href="http://java.sun.com/javaee/6/docs/api/javax/servlet/http/HttpServletRequest.html" target="_blank">javax.servlet.HttpServletRequest</a></code></td> |
| <td class="tbltd1"><code>requestScope</code></td> |
| </tr> |
| <tr> |
| <td class="tbltd1"><strong>Page</strong></td> |
| <td class="tbltd1">Data that is only valid in the context of a single page (JSPs only)</td> |
| <td class="tbltd1"><code>[n/a]</code></td> |
| <td class="tbltd1"><code>pageScope</code></td> |
| </tr> |
| </table> |
| </div> |
| |
| <p>If you open your project's <code>category.jsp</code> file in the editor, you'll see |
| that EL expressions include various scoped variables, including <code>${categories}</code>, |
| <code>${selectedCategory}</code> and <code>${categoryProducts}</code>. The <code>${categories}</code> |
| variable is application-scoped, which is set in the <code>ControllerServlet</code>'s |
| <code>init</code> method:</p> |
| |
| <pre class="examplecode" style="width:664px; margin-left:10px; margin-top:-2px"> |
| // store category list in servlet context |
| getServletContext().setAttribute("categories", categoryFacade.findAll());</pre> |
| |
| <p>The other two, <code>${selectedCategory}</code> and <code>${categoryProducts}</code>, |
| are placed in the application's session scope from the <code>ControllerServlet</code>. |
| For example:</p> |
| |
| <pre class="examplecode" style="width:664px; margin-left:10px; margin-top:-2px"> |
| // place selected category in session scope |
| session.setAttribute("selectedCategory", selectedCategory);</pre> |
| |
| <p class="notes"><strong>Note:</strong> If you are continuing from the previous tutorial |
| units, you'll likely note that <code>${selectedCategory}</code> and <code>${categoryProducts}</code> |
| were originally placed in the request scope. In previous units this was fine, but |
| consider now what happens if a user clicks the 'add to cart' button in a category page. |
| The server responds to an <code>addToCart</code> request by returning the currently |
| viewed category page. It therefore needs to know the <code>selectedCategory</code> and |
| the <code>categoryProducts</code> pertaining to the selected category. Rather than |
| establishing this information for each request, you place it in the session scope from |
| a <code>category</code> request so that it is maintained across multiple requests, and |
| can be accessed when you need it. Also, examine the functionality provided by the cart |
| page. (A functional description is <a href="#cartPage">provided below</a>.) The 'continue |
| shopping' button returns the user to the previously viewed category. Again, the |
| <code>selectedCategory</code> and the <code>categoryProducts</code> variables are required.</p> |
| |
| <p>When referencing scoped variables in an EL expression, you do not need to specify the |
| variable's scope (provided that you do not have two variables of the same name in |
| different scopes). The JSP engine checks all four scopes and returns the first |
| variable match it finds. In <code>category.jsp</code> for example, you can use the following expression:</p> |
| |
| <pre class="examplecode" style="width:664px; margin-left:10px; margin-top:-2px"> |
| ${categoryProducts}</pre> |
| |
| <p>This expression is shorthand for the following expression:</p> |
| |
| <pre class="examplecode" style="width:664px; margin-left:10px; margin-top:-2px"> |
| ${sessionScope.categoryProducts}</pre> |
| |
| <span class="tips">For more information, see the following resources:</span> |
| |
| <ul style="margin: 5px 0 0 1em"> |
| <li><a href="http://java.sun.com/blueprints/guidelines/designing_enterprise_applications_2e/web-tier/web-tier5.html#1079198" target="_blank">Designing |
| Enterprise Applications with the J2EE Platform: State Scopes</a></li> |
| <li><a href="http://download.oracle.com/docs/cd/E17477_01/javaee/5/tutorial/doc/bnafo.html" target="_blank">Sharing Information > Using Scoped Objects</a></li> |
| <li><a href="http://download.oracle.com/docs/cd/E17477_01/javaee/5/tutorial/doc/bnahq.html#bnaij" target="_blank">Unified Expression Language > Implicit Objects</a></li> |
| </ul> |
| </div> |
| |
| |
| <br> |
| <h2 id="debug">Examining Session Data with the Java Debugger</h2> |
| |
| <p>Begin exploring how the application behaves during runtime. Use the IDE's debugger to |
| step through code and examine how the <code>HttpSession</code> is created, and how other |
| objects can be placed in the session scope to be retrieved at a later point.</p> |
| |
| <ol> |
| <li>Open the <a href="https://netbeans.org/projects/samples/downloads/download/Samples%252FJavaEE%252Fecommerce%252FAffableBean_snapshot5.zip">project |
| snapshot</a> for this tutorial unit in the IDE. Click the Open Project ( |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/common/open-project-btn.png" |
| alt="Open Project button"> ) button and use the wizard to navigate to the location |
| on your computer where you downloaded the project. If you are proceeding from the |
| <a href="entity-session.html">previous tutorial unit</a>, note that this project |
| snapshot includes a new <code>cart</code> package, containing <code>ShoppingCart</code> |
| and <code>ShoppingCartItem</code> classes. |
| |
| Also, the following files have been modified: |
| |
| <ul style="margin: 5px 0 0 -.7em"> |
| <li><code>WEB-INF/web.xml</code></li> |
| <li><code>css/affablebean.css</code></li> |
| <li><code>WEB-INF/jspf/header.jspf</code></li> |
| <li><code>WEB-INF/jspf/footer.jspf</code></li> |
| <li><code>WEB-INF/view/cart.jsp</code></li> |
| <li><code>WEB-INF/view/category.jsp</code></li> |
| <li><code>WEB-INF/view/checkout.jsp</code></li> |
| <li><code>controller/ControllerServlet</code></li> |
| </ul></li> |
| |
| <li>Run the project ( |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/common/run-project-btn.png" |
| alt="Run Project button"> ) to ensure that it is properly configured with your database and |
| application server. |
| |
| <br><br> |
| <p class="alert">If you receive an error when running the project, revisit the |
| <a href="setup.html">setup instructions</a>, which describe how to prepare the |
| database and establish connectivity between the IDE, GlassFish, and MySQL.</p></li> |
| |
| <li>Test the application's functionality in your browser. If you are continuing directly from |
| the <a href="entity-session.html">previous tutorial unit</a>, you'll note the following |
| enhancements. |
| |
| <h4>category page</h4> |
| |
| <ul style="margin: 5px 0 0 -.7em"> |
| <li>Clicking 'add to cart' for the first time enables the shopping cart and 'proceed to |
| checkout' widgets to display in the header.</li> |
| <li>Clicking 'add to cart' results in an update to the number of cart items in the header's |
| shopping cart widget.</li> |
| <li>Clicking 'view cart' results in the cart page displaying.</li> |
| <li>Clicking 'proceed to checkout' results in the checkout page displaying.</li> |
| </ul> |
| |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/manage-sessions/category-page.png" |
| class="margin-around b-all" alt="Browser image of category page" style="width:688px" |
| title="Category page includes shopping cart functionality"> |
| |
| <h4 id="cartPage">cart page</h4> |
| |
| <ul style="margin: 5px 0 0 -.7em"> |
| <li>Clicking 'clear cart' results in shopping cart being emptied of items.</li> |
| <li>Clicking 'continue shopping' results in a return to the previously viewed category.</li> |
| <li>Clicking 'proceed to checkout' results in the checkout page displaying.</li> |
| <li>Entering a number (1 - 99) in an item's quantity field then clicking 'update' |
| results in a recalculation of the total price for the item, and of the subtotal.</li> |
| <li>Entering zero in an item's quantity field then clicking 'update' results in |
| the item being removed from the displayed table.</li> |
| </ul> |
| |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/manage-sessions/cart-page.png" |
| class="margin-around b-all" alt="Browser image of cart page" style="width:688px" |
| title="Cart page includes shopping cart functionality"> |
| |
| <h4>checkout page</h4> |
| |
| <ul style="margin: 5px 0 0 -.7em"> |
| <li>Clicking 'view cart' results in the cart page displaying.</li> |
| <li>Clicking 'submit purchase' results in the confirmation page displaying (without |
| user-specific data).</li> |
| </ul> |
| |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/manage-sessions/checkout-page.png" |
| class="margin-around b-all" alt="Browser image of checkout page" style="width:688px" |
| title="Checkout page includes shopping cart functionality"></li> |
| |
| <li>Use the Go to File dialog to open the <code>ControllerServlet</code> in the editor. Press |
| Alt-Shift-O (Ctrl-Shift-O on Mac), then type '<code>Controller</code>' in the dialog and |
| click OK. |
| |
| <br> |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/connect-db/go-to-file-dialog.png" |
| class="margin-around b-all" alt="Go to File dialog" |
| title="Use the Go to File dialog to quickly open project resources in the editor"></li> |
| |
| <li>Set a breakpoint in the <code>doPost</code> method on the line that creates an <code>HttpSession</code> |
| object (line 150). To set a breakpoint, click in the left margin of the editor. |
| |
| <br> |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/manage-sessions/breakpoint.png" |
| class="margin-around b-all" alt="Breakpoint set in editor" |
| title="Click in editor's left margin to set breakpoints"> |
| |
| <p class="tips">To toggle line numbers for the editor, right-click in the left margin and |
| choose Show Line Numbers.</p></li> |
| |
| <li>Run the debugger. Click the Debug Project ( |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/common/debug-project-btn.png" |
| alt="Debug Project button"> ) button in the IDE's main toolbar. The GlassFish server starts |
| (or restarts, if it is already running) and opens a socket on its debug port number. The |
| application welcome page opens in your browser. |
| |
| <br><br> |
| <p class="tips">You can view and modify the debug port number from the Servers window (Tools |
| > Servers). Select the Java tab for the server you are using. Specify the port number |
| in the 'Address to use' field under Debug Settings.</p></li> |
| |
| <li>When the application's welcome page displays in the browser, click any category image to navigate |
| to the category page. Recall that clicking the 'add to cart' button sends an <code>addToCart</code> |
| request to the server: |
| |
| <pre class="examplecode"><form action="addToCart" method="post"></pre> |
| |
| As you may recall from <a href="page-views-controller.html#controller">Preparing the Page Views |
| and Controller Servlet</a>, the <code>ControllerServlet</code>'s <code>doPost</code> method handles |
| requests for the <code>/addToCart</code> URL pattern. You can therefore expect that when a user |
| clicks an 'add to cart' button, the <code>doPost</code> method is called.</li> |
| |
| <li>Click 'add to cart' for any product in the category page. Switch back to the IDE and note that |
| the debugger suspends on the breakpoint. |
| |
| <br> |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/manage-sessions/breakpoint-suspended.png" |
| class="margin-around b-all" alt="Debugger suspended on breakpoint in editor" |
| title="Debugger suspends on breakpoints in editor"></li> |
| |
| <li>Place your cursor on the call to <code>getSession()</code> and press Ctrl-Space to invoke the |
| Javadoc documentation. |
| |
| <br> |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/manage-sessions/javadoc-getsession.png" |
| class="margin-around b-all" alt="Javadoc documentation displayed in editor" style="width:688px" |
| title="Press Ctrl-Space to invoke Javadoc documentation"> |
| |
| <br> |
| According to the documentation, <code>getSession()</code> returns the <code>HttpSession</code> |
| currently associated with the request, and if no session exists, the method creates a new session |
| object. |
| |
| <br><br> |
| <div class="feedback-box float-left" style="width: 683px;"> |
| |
| <h3>Taking Advantage of the IDE's Javadoc Support</h3> |
| |
| <p>The IDE provides built-in Javadoc support for Java EE development. The IDE |
| bundles with the Java EE 6 API Specification, which you can open in an |
| external browser by choosing Help > Javadoc References > Java EE 6.</p> |
| |
| <p>The IDE also includes various other features that enable easy access to API |
| documentation:</p> |
| |
| <ul style="margin: 5px 0 0 -.7em"> |
| <li><strong>Javadoc window:</strong> Choose Window > Other > Javadoc. |
| The Javadoc window opens in the bottom region of the IDE, and displays |
| API documentation relevant to your cursor's location in the editor.</li> |
| |
| <li><strong>Javadoc Index Search:</strong> Choose Help > Javadoc Index |
| Search (Shift-F1; fn-Shift-F1 on Mac). Type in the name of the class |
| you are looking for, then select a class from the listed results. The |
| complete class description from the API Specification displays in the |
| bottom pane of the window.</li> |
| |
| <li><strong>Documentation popup in the editor:</strong> Javadoc documentation |
| displays in a popup window when you press Ctrl-Space on a given element |
| in the editor. You can click the External Browser ( |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/manage-sessions/external-browser-btn.png" |
| alt="External Browser button"> ) button to have the documentation open |
| in your browser. |
| |
| If you want to use Ctrl-Space for code completion only, you can deactivate |
| the documentation popup by opening the Options window (Tools > Options; |
| NetBeans > Preferences on Mac), then selecting Editor > Code Completion. |
| Deselect the 'Auto Popup Documentation Window' option.</li> |
| </ul> |
| |
| <p>When you document your own work, consider adding Javadoc comments to your |
| classes and methods. Open the <code>ShoppingCart</code> class and examine |
| the Javadoc comments added to the class methods. Javadoc comments are marked |
| by the <code>/** ... */</code> delimiters. For example, the <code>addItem</code> |
| method has the following comment before its signature:</p> |
| |
| <div class="margin-around"> |
| <pre class="examplecode" style="width:643px"> |
| /** |
| * Adds a <code>ShoppingCartItem</code> to the <code>ShoppingCart</code>'s |
| * <code>items</code> list. If item of the specified <code>product</code> |
| * already exists in shopping cart list, the quantity of that item is |
| * incremented. |
| * |
| * @param product the <code>Product</code> that defines the type of shopping cart item |
| * @see ShoppingCartItem |
| */ |
| public synchronized void addItem(Product product) {</pre> |
| </div> |
| |
| <p>This enables you (and others working on the project) to view Javadoc documentation |
| on the method. To demonstrate, open the Navigator (Ctrl-7; ⌘-7 on Mac) and |
| hover your mouse over the <code>addItem</code> method.</p> |
| |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/manage-sessions/javadoc-additem.png" |
| title="Hover over methods in Navigator to view Javadoc documentation" |
| alt="Javadoc popup" class="margin-around b-all"> |
| |
| <p>You can also use the IDE to generate a set of Javadoc HTML pages. In the Projects |
| window, right-click your project node and choose Generate Javadoc. The IDE generates |
| the Javadoc in the <code>dist/javadoc</code> folder of your project's directory |
| and opens the index page in the browser.</p> |
| |
| <br> |
| <p>For more information on Javadoc, see the following resources:</p> |
| |
| <ul style="margin: 5px 0 0 -.7em"> |
| <li><a href="http://java.sun.com/j2se/javadoc/" target="_blank">Javadoc Tool Official Home Page</a></li> |
| <li><a href="http://java.sun.com/j2se/javadoc/writingdoccomments/index.html" target="_blank">How |
| to Write Doc Comments for the Javadoc Tool</a></li> |
| </ul> |
| </div> |
| |
| <div style="clear:left"></div> |
| </li> |
| |
| <li>Hover your mouse over the <code>session</code> variable. Note that the debugger suspends |
| on the line <em>it is about to execute.</em> The value returned by <code>getSession()</code> |
| has not yet been saved into the <code>session</code> variable, and you see a popup stating |
| that "<code>session</code> is not a known variable in the current context." |
| |
| <br> |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/manage-sessions/session-variable.png" |
| class="margin-around b-all" alt="Debugger popup displayed in editor" |
| title="Hover your mouse over variables and expressions to determine their current values"></li> |
| |
| <li>Click the Step Over ( |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/manage-sessions/step-over-btn.png" |
| alt="Step Over button"> ) button in the debugger toolbar located above the editor. The line is |
| executed, and the debugger steps to the next line in the file.</li> |
| |
| <li>Hover your mouse over the <code>session</code> variable again. Now you see the value currently |
| set to the <code>session</code> variable. |
| |
| <br> |
| <a href="../../../../images_www/articles/73/javaee/ecommerce/manage-sessions/session-variable-set.png" |
| rel="lytebox" title="Hover your mouse over variables and expressions to determine their current values"> |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/manage-sessions/session-variable-set.png" |
| class="margin-around b-all" alt="Debugger popup displayed in editor" width="688px" |
| title="Click to enlarge"></a> |
| |
| <p class="tips">In NetBeans 6.9, you can click the grey pointer ( |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/manage-sessions/grey-pointer.png" |
| alt="Step Over button"> ) in the popup to expand a list of variable values contained in the |
| highlighted element.</p></li> |
| |
| <li>Click the Step Over ( |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/manage-sessions/step-over-btn.png" |
| alt="Step Over button"> ) button (F8; fn-F8 on Mac) to arrive at the <code>if</code> statement (line |
| 154). Because you just clicked the 'add to cart' button in the browser, you know that the expression |
| <code>userPath.equals("/addToCart")</code> should evaluate to <code>true</code>.</li> |
| |
| <li>Highlight the <code>userPath.equals("/addToCart")</code> expression (by control-clicking |
| with your mouse). This time you see a popup indicating the value of the expression you highlighted. |
| |
| <br> |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/manage-sessions/expression.png" |
| class="margin-around b-all" alt="Evaluated expression displayed in popup" |
| title="Highlight expressions to determine their current values"></li> |
| |
| <li>Press F8 (fn-F8 on Mac) to step to the next line (line 158). The application has been designed |
| so that the <code>ShoppingCart</code> object for the user session is only created when the user |
| adds an item to the cart for the first time. Since this is the first time the <code>addToCart</code> |
| request has been received in this debug session, you can expect the <code>cart</code> object to |
| equal <code>null</code>. |
| |
| <br> |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/manage-sessions/cart-null.png" |
| class="margin-around b-all" alt="Evaluated expression displayed in popup" |
| title="Cart object doesn't exist until user adds item to shopping cart"></li> |
| |
| <li>Press F8 (fn-F8 on Mac) to step to the next line (line 160). Then, on line 160, where the |
| <code>ShoppingCart</code> object is created, click the Step Into ( |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/manage-sessions/step-into-btn.png" |
| alt="Step Into button"> ) button. The debugger steps into the method being called. In this |
| case, you are taken directly to the <code>ShoppingCart</code>'s constructor. |
| |
| <br> |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/manage-sessions/cart-constructor.png" |
| class="margin-around b-all" alt="Evaluated expression displayed in popup" |
| title="Step into methods to follow runtime execution to other classes"></li> |
| |
| <li>Press Ctrl-Tab to switch back to the <code>ControllerServlet</code>. Note that the IDE |
| provides a Call Stack ( |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/manage-sessions/call-stack-badge.png" |
| alt="Call Stack badge"> ) badge on line 160, indicating that the debugger is currently suspended |
| somewhere on a method higher up in the call stack. |
| |
| <br><br> |
| <p class="tips">Press Alt-Shift-3 (Ctrl-Shift-3 on Mac) to open the IDE's Call Stack window.</p></li> |
| |
| <li>Press F8 (fn-F8 on Mac) to continue stepping through code. When the debugger completes the |
| <code>ShoppingCart</code> constructor, you are taken back to the <code>ControllerServlet</code>. |
| |
| <br><br> |
| Line 161 of the <code>ControllerServlet</code> binds the newly-created <code>cart</code> object |
| to the session. |
| |
| <pre class="examplecode">session.setAttribute("cart", cart);</pre> |
| |
| To witness this, open the debugger's Variables window. Choose Window > Debugging > Variables, |
| or press Alt-Shift-1 (Ctrl-Shift-1 on Mac). |
| |
| <br> |
| <a href="../../../../images_www/articles/73/javaee/ecommerce/manage-sessions/variables-win-session.png" |
| rel="lytebox" title="Open the debugger's Variables window to inspect variable values as you step through code"> |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/manage-sessions/variables-win-session.png" |
| class="margin-around b-all" alt="Variables window" width="688px" |
| title="Click to enlarge"></a> |
| |
| <br> |
| If you expand the session > session > attributes node, you are able to view the |
| objects that are bound to the session. In the above image, there are two items currently |
| bound to the session (highlighted). These are <code>selectedCategory</code> and |
| <code>categoryProducts</code>, instantiated in the <code>ControllerServlet</code> at lines |
| 83 and 89, respectively. Both of these items were bound earlier, when you clicked a category |
| image, and the <code>ControllerServlet</code> processed the category page request.</li> |
| |
| <li>Press F8 (fn-F8 on Mac) to execute line 161. The <code>cart</code> object is bound to the |
| session, and the Variables window updates to reflect changes. In the Variables window, note |
| that the session now contains three attributes, the third being the newly initialized |
| <code>ShoppingCart</code> object (highlighted below). |
| |
| <br> |
| <a href="../../../../images_www/articles/73/javaee/ecommerce/manage-sessions/variables-win-session-cart.png" |
| rel="lytebox" title="ShoppingCart object is bound to session with the setAttribute method"> |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/manage-sessions/variables-win-session-cart.png" |
| class="margin-around b-all" alt="Variables window" width="688px" |
| title="Click to enlarge"></a> |
| |
| <br> |
| <p class="tips">So far, we have not "proven" that the session, as listed in |
| the Variables window, represents an <code>HttpSession</code>. As previously mentioned, |
| <code>HttpSession</code> is actually an interface, so when we talk about an <code>HttpSession</code> |
| object, or session object, we are in fact referring to any object that implements the |
| <code>HttpSession</code> interface. In the Variables window, if you hover your cursor |
| over '<code>session</code>', a popup displays indicating that the variable represents |
| an <code>HttpSession</code> object. The <code>StandardSessionFacade</code> type, as |
| displayed, is the internal class that GlassFish uses to implement the <code>HttpSession</code> |
| interface. If you are familiar with Tomcat and are puzzled by the |
| '<code>org.apache.catalina</code>' paths that appear in the Value column, this is |
| because the GlassFish web/servlet container is in fact a derivative of the Apache Tomcat |
| container.</p> |
| |
| A new <code>ShoppingCart</code> is added to the session, and the request continues |
| to be processed. In order to complete implementation of the 'add to cart' functionality, |
| the following actions are taken: |
| |
| <ul style="margin: 5px 0 0 -.7em"> |
| <li>the ID of the selected product is retrieved from the request (line 165)</li> |
| <li>a <code>Product</code> object is created using the ID (line 169)</li> |
| <li>a new <code>ShoppingCartItem</code> is created using the <code>product</code> (line 170)</li> |
| <li>the <code>ShoppingCartItem</code> is added to <code>ShoppingCart</code>'s <code>items</code> list (line 170)</li> |
| </ul></li> |
| |
| <li>Press F8 (fn-F8 on Mac) to continue stepping through code while being mindful of the above-listed |
| four actions. Pause when the debugger suspends on line 170.</li> |
| |
| <li id="step21">Create a watch on the session. This will allow you to view values contained |
| in the session when you step into the <code>addItem</code> method in the next step. |
| Right-click the session in the Variables window and choose Create Fixed Watch. |
| |
| <br> |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/manage-sessions/create-watch.png" |
| class="margin-around b-all" alt="Right-click menu displayed in Variables window" |
| title="Create watches on variables as you step through code in a debug session"> |
| |
| <p class="tips">Alternatively, you can place your cursor on the <code>session</code> variable |
| in the editor, then right-click and choose New Watch. The New Watch dialog enables you to |
| specify variables or expressions to watch continuously when debugging an application. (In |
| the case of expressions, highlight the expression first, then right-click and choose New |
| Watch.) |
| |
| <br> |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/manage-sessions/new-watch-dialog.png" |
| class="margin-around b-all" alt="New Watch dialog" |
| title="Right-click variables and expressions in the editor and choose New Watch"></p> |
| |
| A new watch is created on the <code>session</code> variable and all variables it contains. |
| The watch is visible from the Watches window (Window > Debugging > Watches) or, if |
| you toggle the Watches ( |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/manage-sessions/watch-btn.png" |
| alt="Watches button"> ) button in the left margin of the Variables window, it displays in |
| the top row of the Variables window. |
| |
| <br><br> |
| The debugger enables you to keep an eye on variables as it steps through code. This can |
| be helpful, for example if you'd like to follow changes to specific variable values (and |
| don't want to need to sift through the full list presented in the Variables window with |
| each step), or if you temporarily step into a class that doesn't contain the variables |
| you are interested in.</li> |
| |
| <li>Click the Step Into ( |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/manage-sessions/step-into-btn.png" |
| alt="Step Into button"> ) button to step into <code>ShoppingCart</code>'s <code>addItem</code> |
| method.</li> |
| |
| <li>Step through the <code>addItem</code> method until you reach line 53. As the Javadoc states, |
| <code>addItem</code> <em>"adds a <code>ShoppingCartItem</code> to the <code>ShoppingCart</code>'s |
| <code>items</code> list. If item of the specified <code>product</code> already exists in |
| shopping cart list, the quantity of that item is incremented."</em></li> |
| |
| <li>Examine the <code>session</code> variable which you created a watch on (<a href="#step21">step |
| 21</a> above). The <code>items.add(scItem)</code> statement in line 51 added the new |
| <code>ShoppingCartItem</code> to the <code>items</code> list in the <code>ShoppingCart</code>. |
| This is evident by drilling into the third attribute (i.e., the <code>cart</code> variable) |
| contained in the session. |
| |
| <br> |
| <a href="../../../../images_www/articles/73/javaee/ecommerce/manage-sessions/variables-window-add-item.png" |
| rel="lytebox" title="Session displays the new ShoppingCartItem as listed in the ShoppingCart's 'items' list"> |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/manage-sessions/variables-window-add-item.png" |
| class="margin-around b-all" alt="Variables window" width="688px" |
| title="Click to enlarge"></a> |
| |
| <br> |
| At this stage, you can see how an <code>HttpSession</code> is created for the request, |
| how a <code>ShoppingCart</code> object is created and attached to the session, and how |
| a <code>ShoppingCartItem</code> is created based on the user's product choice, then added |
| to the <code>ShoppingCart</code>'s list of <code>items</code>. The only remaining action |
| is to forward the request to the <code>category.jsp</code> view.</li> |
| |
| <li>Open the header JSP fragment (<code>header.jspf</code>) in the editor and place a |
| breakpoint on line 86. This line contains the EL statement within the shopping cart |
| widget that displays the number of cart items. |
| |
| <br> |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/manage-sessions/breakpoint-jsp.png" |
| class="margin-around b-all" alt="Breakpoint set in JSP page" width="688px" |
| title="You can suspend the debugger in JSP pages"></li> |
| |
| <li>Click the Continue ( |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/manage-sessions/continue-btn.png" |
| alt="Continue button"> ) button in the debugger toolbar. The debugger continues until |
| execution completes, or until it reaches another breakpoint. In this case, the debugger |
| suspends on line 86 in the header JSP fragment. |
| |
| <br><br> |
| <p class="notes"><strong>Note:</strong> In order to suspend the debugger in a JSP page, |
| you need to set a breakpoint. For example, when the <code>ControllerServlet</code> |
| forwards the request to the appropriate view, the debugger will not automatically |
| suspend within the JSP page.</p></li> |
| |
| <li>Open the Variables window (Alt-Shift-1; Ctrl-Shift-1 on Mac) if it is not already open. |
| Unlike with Java classes, the debugger <em>does not</em> provide tooltips when you hover |
| your mouse over variables or expressions in a JSP page. However, the Variables window does |
| enable you to determine variable values as you step through code. So, where can you find |
| the value for <code>${cart.numberOfItems}</code>?</li> |
| |
| <li>In the Variables window, expand the Implicit Objects > pageContext > session > |
| session > attributes node. This provides access to the session object, just as you |
| saw earlier when working in the <code>ControllerServlet</code>. In fact, you may note |
| that the session which you created a watch on in step 21 above points to the very same |
| object. Here you can verify that the value of <code>${cart.numberOfItems}</code> equals |
| '<code>1</code>'. |
| |
| <br> |
| <a href="../../../../images_www/articles/73/javaee/ecommerce/manage-sessions/variables-window-number-of-items.png" |
| rel="lytebox" title="In JSP pages, view session attributes within the pageContext implicit object"> |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/manage-sessions/variables-window-number-of-items.png" |
| class="margin-around b-all" alt="Variables window" width="688px" |
| title="Click to enlarge"></a> |
| |
| <p class="tips">Maximize the Variables window, or any window in the IDE, by right-clicking |
| the window header, then choosing Maximize Window (Shift-Esc).</p> |
| |
| The debugger gives you access to the <code>pageContext</code> implicit object. |
| <code>pageContext</code> represents the context of the JSP page, and offers direct |
| access to various objects including the <code>HttpServletRequest</code>, |
| <code>HttpSession</code>, and <code>ServletContext</code> objects. For more information, |
| see the <a href="http://java.sun.com/javaee/5/docs/tutorial/doc/bnahq.html#bnaij" target="_blank">Java |
| EE 5 Tutorial: Implicit Objects</a>.</li> |
| |
| <li>Click the Finish Session ( |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/manage-sessions/finish-session-btn.png" |
| alt="Finish Session button"> ) button. The runtime finishes executing, and the debug |
| session terminates. The browser displays a fully-rendered category page, and you can |
| see that the shopping cart widget in the page header contains one item.</li> |
| </ol> |
| |
| <p>Hopefully you now feel comfortable using the IDE's debugger not only to examine your project |
| when it behaves unexpectedly, but also as a tool to become more familiar with code. |
| Other useful buttons in the debugger toolbar include:</p> |
| |
| <ul> |
| <li>( <img src="../../../../images_www/articles/73/javaee/ecommerce/manage-sessions/step-out.png" |
| alt="Step Out button"> ) <strong>Step Out:</strong> Steps you out of the current method call. |
| Executes and removes the topmost method call in your call stack.</li> |
| |
| <li>( <img src="../../../../images_www/articles/73/javaee/ecommerce/manage-sessions/run-to-cursor.png" |
| alt="Run to Cursor button"> ) <strong>Run to Cursor:</strong> Executes up to the line on |
| which your cursor is placed.</li> |
| |
| <li>( <img src="../../../../images_www/articles/73/javaee/ecommerce/manage-sessions/apply-code-changes.png" |
| alt="Apply Code Changes button"> ) <strong>Apply Code Changes:</strong> After editing a |
| file, you can press this button so that the file is recompiled and changes are taken into |
| account in the debug session.</li> |
| |
| <li>( <img src="../../../../images_www/articles/73/javaee/ecommerce/manage-sessions/step-over-expression.png" |
| alt="Step Over Expression button"> ) <strong>Step Over Expression:</strong> Enables you |
| to view the input parameters and resulting output values of each method call within an |
| expression. You can inspect the output values for the previous method and the input |
| parameters for the next method in the Local Variables window. When there are no further |
| method calls, Step Over Expression behaves like the Step Over ( |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/manage-sessions/step-over-btn.png" |
| alt="Step Over button"> ) command.</li> |
| </ul> |
| |
| |
| <br> |
| <h2 id="session-track">Examining Session Tracking Options</h2> |
| |
| <p>There are three conventional ways of tracking sessions between client and server. By |
| far the most common is with cookies. URL rewriting can be applied in the event that |
| cookies are not supported or disabled. Hidden form fields can also be used as a means |
| of "maintaining state" over multiple requests, but these are limited to |
| usage within forms.</p> |
| |
| <p>The <code>AffableBean</code> project includes an example of the hidden field method |
| in both the category and cart pages. The 'add to cart' and 'update' buttons that display |
| for product items contain a hidden field which relays the product ID to the server |
| when the button is clicked. If you open the <code>cart.jsp</code> page in the editor, |
| you'll see that the <code><form></code> tags contain a hidden field.</p> |
| |
| <pre class="examplecode" style="width:730px; margin-left:10px; margin-top:-2px"> |
| <form action="updateCart" method="post"> |
| <strong><input type="hidden" |
| name="productId" |
| value="${product.id}"></strong> |
| ... |
| </form></pre> |
| |
| <p>In this manner, the product ID is sent as a request parameter which the server uses |
| to identify the item within the user's cart whose quantity needs to be modified.</p> |
| |
| <p>The Servlet API provides a high-level mechanism for managing sessions. Essentially, |
| it creates and passes a cookie between the client and server with each request-response |
| cycle. If the client browser doesn't accept cookies, the servlet engine automatically |
| reverts to URL rewriting. The following two exercises demonstrate this functionality.</p> |
| |
| <ul> |
| <li><a href="#http-monitor">Examining Client-Server Communication with the HTTP Monitor</a></li> |
| <li><a href="#url-rewrite">Maintaining Sessions with URL Rewriting</a></li> |
| </ul> |
| |
| <div class="indent"> |
| <h3 id="http-monitor">Examining Client-Server Communication with the HTTP Monitor</h3> |
| |
| <p>By default, the servlet engine uses cookies to maintain and identify sessions between |
| requests. A random, alphanumeric number is generated for each session object, which |
| serves as a unique identifier. This identifier is passed as a '<code>JSESSIONID</code>' |
| cookie to the client. When the client makes a request, the servlet engine reads the |
| value of the <code>JSESSIONID</code> cookie to determine the session which the request |
| belongs to.</p> |
| |
| <p>To demonstrate this, we'll use the debugger in tandem with the IDE's HTTP Monitor.</p> |
| |
| <ol> |
| <li>Begin by activating the HTTP Monitor for the server you are using. Choose Tools |
| > Servers. In the left column of the Servers window, select the server you are |
| using (GlassFish). Then, in the main column, select the Enable HTTP Monitor option. |
| |
| <br> |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/manage-sessions/servers-win-http-monitor.png" |
| class="margin-around b-all" alt="Servers window" width="688px" |
| title="Select the Enable HTTP Monitor option to activate the HTTP Monitor"></li> |
| |
| <li>If your server is already running, you need to restart it. However, since we plan |
| to use the debugger, and running the debugger restarts the server to communicate |
| on a different port, just click the Debug Project ( |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/common/debug-project-btn.png" |
| alt="Debug Project button"> ) button in the IDE's main toolbar. The server restarts, |
| a debug session begins and the application's welcome page opens in your browser. The |
| HTTP Monitor displays in the bottom region of the IDE. |
| |
| <br> |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/manage-sessions/http-monitor.png" |
| class="margin-around b-all" alt="HTTP Monitor" width="688px" |
| title="HTTP Monitor displays by default in bottom region of the IDE"></li> |
| |
| <li>Click the AffableBean record in the left column (as shown in the above image). When |
| you select records in the left column, the right (i.e., main) column refreshes to |
| display corresponding data. In the above image, the Request tab displays the requested |
| URI (<code>/AffableBean/</code>), the HTTP method (<code>GET</code>), and points out |
| that there was no query string sent with the request.</li> |
| |
| <li>Select the Session tab. Note that there is a statement, "The session was created |
| as a result of this request." This is due to the fact that the server has sent a |
| <code>Set-Cookie</code> header for the <code>JSESSIONID</code> cookie in its response. |
| Also note that the new session ID is listed under 'Session properties'. As will later |
| be shown, the session ID is the value of the <code>JSESSIONID</code> cookie. |
| |
| <br> |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/manage-sessions/session-tab.png" |
| class="margin-around b-all" alt="HTTP Monitor - Session tab" |
| title="Session details are displayed under the Session tab in the HTTP Monitor"> |
| |
| <br> |
| You may wonder how a session object was created from a request for the site welcome page. |
| After all, the <code>ControllerServlet</code> does not handle the initial request for |
| <code>/AffableBean/</code>, and nowhere does this request encounter <code>getSession()</code>. |
| Or does it? Recall that JSP pages are compiled into servlets upon deployment. Once you've |
| deployed your project to the server, you can actually use the IDE to view the JSP's compiled |
| servlet on your server.</li> |
| |
| <li>In the Projects window, right-click the <code>index.jsp</code> file and choose View Servlet. |
| An <code>index_jsp.java</code> file opens in the editor. This is the servlet that was automatically |
| compiled from the <code>index.jsp</code> page.</li> |
| |
| <li>Perform a search in the file for <code>getSession</code>. Press Ctrl-F (⌘-F on Mac), |
| type '<code>getSession</code>' in the search bar, then press Enter. |
| |
| <br><br> |
| <p class="tips"> Ctrl-F (⌘-F on Mac) is a keyboard shortcut for Edit > Find.</p> |
| |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/manage-sessions/get-session.png" |
| class="margin-around b-all" alt="Editor displaying getSession method" |
| title="The getSession method exists in the JSP page's compiled servlet"> |
| |
| <p> |
| The <code>getSession</code> method is in fact called. The reason this occurs is because |
| JSP pages include the <code>pageContext.session</code> implicit object by default. If you |
| wanted to deactivate this behavior, you could add the following directive to the top of |
| a JSP file:</p> |
| |
| <pre class="examplecode"><%@page session="false" %></pre> |
| |
| <p>If you add the directive the <code>getSession</code> method will be removed in the compiled servlet.</p> |
| |
| <p class="tips">To find out the location of the compiled servlet on your server, |
| you can hover your mouse over the servlet's name tab above the editor. A popup |
| displays the path to the file on your computer.</p></li> |
| |
| <li>In the browser, select a category then add an item to your cart. Switch back to the |
| IDE. Note that the debugger suspends on the breakpoint in the <code>ControllerServlet</code> |
| you set earlier (line 150). All breakpoints are remembered between sessions. To remove |
| the breakpoint, you could click the breakpoint ( |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/common/breakpoint-badge.png" |
| alt="Breakpoint badge"> ) badge in the editor's left margin. However, since there are |
| multiple breakpoints already set in the project, open the debugger's Breakpoints |
| window (Window > Debugging > Breakpoints). |
| |
| <br> |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/manage-sessions/breakpoints-window.png" |
| class="margin-around b-all" alt="Breakpoints window" |
| title="View all breakpoints in your project from the Breakpoints window"> |
| |
| <br> |
| From the Breakpoints window, you can view and call actions on all breakpoints |
| set in projects opened in the IDE.</li> |
| |
| <li>Right-click the breakpoint set in <code>header.jspf</code> and choose Delete. |
| Then right-click the breakpoint set in the <code>ControllerServlet</code> and |
| choose Disable. (You'll re-enable it later in this exercise.)</li> |
| |
| <li>Click the Continue ( |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/manage-sessions/continue-btn.png" |
| alt="Continue button"> ) button. The request finishes executing, and the category |
| page displays in the browser with one item added to the cart.</li> |
| |
| <li>In the HTTP Monitor, search for the <code>addToCart</code> request in the left |
| column, then select it to display details in the main column. |
| |
| <br><br> |
| <p class="tips">Click the Ascending Sort ( |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/manage-sessions/ascending-sort-btn.png" |
| alt="Ascending Sort button"> ) button so that the most recent records are listed |
| at the top.</p> |
| |
| <br> |
| Under the Request tab, note the requested URI (<code>/AffableBean/addToCart</code>), |
| the HTTP method (<code>POST</code>), and the request parameters (<code>productId</code> |
| and <code>submit</code>). |
| |
| <br> |
| <a href="../../../../images_www/articles/73/javaee/ecommerce/manage-sessions/http-monitor-add-to-cart.png" |
| rel="lytebox" title="View request data, including request parameters, under the HTTP Monitor's Request tab"> |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/manage-sessions/http-monitor-add-to-cart.png" |
| class="margin-around b-all" style="width:688px" alt="HTTP Monitor - Request tab" |
| title="Click to enlarge"></a></li> |
| |
| <li>Select the Cookies tab. Here you see that a cookie named <code>JSESSIONID</code> exists, |
| and was sent from the client to the server. Note that the value for the cookie is the |
| same as the Session ID displayed under the Session tab. |
| |
| <br> |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/manage-sessions/cookies-tab.png" |
| class="margin-around b-all" alt="HTTP Monitor - Cookies tab" |
| title="Cookies are displayed under the Cookies tab in the HTTP Monitor"> |
| |
| <br> |
| Likewise, if you click the Header tab, you see the cookie listed, since '<code>Cookie</code>' |
| is a request header that was sent by the client. |
| |
| <br> |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/manage-sessions/headers-tab.png" |
| class="margin-around b-all" alt="HTTP Monitor - Cookies tab" |
| title="Cookies are displayed under the Cookies tab in the HTTP Monitor"> |
| |
| <p class="tips">See Wikipedia's <a href="http://en.wikipedia.org/wiki/List_of_HTTP_headers" target="_blank">List |
| of HTTP headers</a> for more information on request and response headers.</p></li> |
| |
| <li>Select the Session tab. There is a statement which indicates, "The session existed |
| before this request." Also note that the <code>cart</code> attribute is listed under |
| 'Session attributes after the request'. This makes sense, since we know that the |
| <code>cart</code> object is bound to the session when the <code>addToCart</code> request |
| is processed for the first time. |
| |
| <br> |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/manage-sessions/session-tab-add-to-cart.png" |
| class="margin-around b-all" alt="HTTP Monitor - Session tab" |
| title="Session attributes are displayed under the Session tab in the HTTP Monitor"> |
| |
| <br><br> |
| In the next few steps, locate the session ID and <code>JSESSIONID</code> cookie in the |
| Variables window.</li> |
| |
| <li>Re-enable the breakpoint you set earlier in the <code>ControllerServlet</code>. Press |
| Alt-Shift-5 (Ctrl-Shift-5 on Mac) to open the Breakpoints window, then click in the |
| checkbox next to the breakpoint entry to re-enable it.</li> |
| |
| <li>In the browser, click the 'add to cart' button for one of the listed products.</li> |
| |
| <li>Switch to the IDE and note that the debugger is suspended on the breakpoint set |
| in the <code>ControllerServlet</code>. Click the Step Over ( |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/manage-sessions/step-over-btn.png" |
| alt="Step Over button"> ) button so that the <code>session</code> variable is assigned |
| to the session object.</li> |
| |
| <li>Open the Variables window (Alt-Shift-1; Ctrl-Shift-1 on Mac) and expand session > |
| session. You'll find the session ID listed as the value for the <code>id</code> |
| variable.</li> |
| |
| <li>To locate the <code>JSESSIONID</code> cookie, recall that you can normally access |
| cookies from a servlet by calling the |
| <a href="http://java.sun.com/webservices/docs/1.6/api/javax/servlet/http/HttpServletRequest.html#getCookies%28%29" target="_blank"><code>getCookies</code></a> |
| method on the <code>HttpServletRequest</code>. Therefore, drill into the request object: |
| request > Inherited > request > request > Inherited > cookies. |
| Here you see the <code>cookies</code> ArrayList. If you expand the list, you'll |
| find the <code>JSESSIONID</code> cookie, the value of which is the session ID.</li> |
| |
| <li>Click the Finish Session ( |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/manage-sessions/finish-session-btn.png" |
| alt="Finish Session button"> ) button to terminate the debug session.</li> |
| </ol> |
| |
| |
| <h3 id="url-rewrite">Maintaining Sessions with URL Rewriting</h3> |
| |
| <p>As mentioned, the servlet engine detects whether cookies are supported for the client |
| browser, and if not, it switches to URL rewriting as a means of maintaining sessions. |
| This all happens transparently for the client. For you, the developer, the process |
| isn't entirely transparent.</p> |
| |
| <p>You need to ensure that the application is capable of rewriting URLs whenever cookies |
| are disabled. You do this by calling the response’s <code>encodeURL</code> method |
| on all URLs returned by servlets in your application. Doing so enables the session |
| ID to be appended to the URL in the event that the use of cookies is not an option; |
| otherwise, it returns the URL unchanged.</p> |
| |
| <p>For example, the browser sends a request for <code>AffableBean</code>'s third category |
| (bakery): <code>category?3</code>. The server responds with session ID included in the |
| URL:</p> |
| |
| <pre class="examplecode">/AffableBean/category<strong>;jsessionid=364b636d75d90a6e4d0085119990</strong>?3</pre> |
| |
| <p>As stated above, <em>all URLs returned by your application's servlets must be encoded</em>. |
| Keep in mind that JSP pages are compiled into servlets. How can you encode URLs in JSP |
| pages? JSTL's |
| <a href="http://java.sun.com/products/jsp/jstl/1.1/docs/tlddocs/c/url.html" target="_blank"><code><c:url></code></a> |
| tag serves this purpose. The following exercise demonstrates the problem and illustrates |
| a solution.</p> |
| |
| <ol> |
| <li>Temporarily disable cookies in your browser. If you are using Firefox, you can |
| choose Tools > Options (Firefox > Preferences on Mac). In the window that |
| displays, select the Privacy tab, then under History, select 'Use custom settings |
| for history' in the provided drop-down. Deselect the 'Accept cookies from sites' |
| option. |
| |
| <br> |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/manage-sessions/firefox.png" |
| class="margin-around b-all" alt="Firefox Preferences window" |
| title="Temporarily disable cookies in your browser"></li> |
| |
| <li>Run the <code>AffableBean</code> project. When the welcome page displays, click |
| into a category, then try adding an item to your cart. You'll see that the |
| application's functionality is severely compromised in its present state. |
| |
| <br> |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/manage-sessions/compromised.png" |
| class="margin-around b-all" alt="Broken categories page" width="688px" |
| title="The application's functionality is compromised when the client doesn't accept cookies"> |
| |
| <br> |
| As before, the server generates a session and binds objects to it. This is how |
| the category page is able to display the selected category and products. However, |
| the server has failed in its attempt to set a <code>JSESSIONID</code> cookie. |
| Therefore, when the client makes a second request (when user clicks 'add to cart'), |
| the server has no way of identifying the session which the request belongs to. |
| It therefore cannot locate any of the attributes previously set in the session, |
| such as <code>selectedCategory</code> and <code>categoryProducts</code>. This |
| why the rendered response lacks the information specified by these attributes.</li> |
| |
| <li>Open the project's <code>category.jsp</code> page in the editor. Locate the line |
| that implements the 'add to cart' button (line 58). The <code><form></code> |
| element's <code>action</code> attribute determines the request sent to the server. |
| |
| <pre class="examplecode"><form action="addToCart" method="post"></pre></li> |
| |
| <li>Modify the request so that it is passed through the <code><c:url></code> tag. |
| |
| <pre class="examplecode"><form action="<strong><c:url value='addToCart'/></strong>" method="post"></pre></li> |
| |
| <li>Press Ctrl-S (⌘-S on Mac) to save changes to the file. Recall that the IDE |
| provides the Deploy on Save feature, which is enabled by default. This means that |
| any saved changes are automatically deployed to your server.</li> |
| |
| <li>In the browser, select a different category so that the application renders the |
| newly modified category page.</li> |
| |
| <li>Examine the source code for the page. In Firefox, you can press Ctrl-U (⌘-U on |
| Mac). The 'add to cart' button for each product displays with the session ID appended |
| to the URL. |
| |
| <pre class="examplecode"> |
| <form action="addToCart<strong>;jsessionid=4188657e21d72f364e0782136dde</strong>" method="post"></pre></li> |
| |
| <li>Click the 'add to cart' button for any item. You see that the server is now able |
| to determine the session which the request belongs to, and renders the response |
| appropriately.</li> |
| |
| <li>Before proceeding, make sure to re-enable cookies for your browser.</li> |
| </ol> |
| |
| <p id="encodeUrl">Again, every link that a user is able to click on within the application, |
| whose response requires some form of session-related data, needs to be properly encoded. |
| Sometimes implementation is not as straight-forward as the example shown above. For |
| example, the 'clear cart' widget used in <code>cart.jsp</code> currently sets a |
| <code>clear</code> parameter to <code>true</code> when the link is clicked.</p> |
| |
| <div class="indent"> |
| <pre class="examplecode" style="width:700px"> |
| <%-- clear cart widget --%> |
| <c:if test="${!empty cart && cart.numberOfItems != 0}"> |
| <a href="viewCart<strong>?clear=true</strong>" class="bubble hMargin">clear cart</a> |
| </c:if></pre></div> |
| |
| <p>The <code><c:url></code> tag can be applied to the URL in the following manner:</p> |
| |
| <div class="indent"> |
| <pre class="examplecode" style="width:700px"> |
| <%-- clear cart widget --%> |
| <c:if test="${!empty cart && cart.numberOfItems != 0}"> |
| |
| <strong><c:url var="url" value="viewCart"> |
| <c:param name="clear" value="true"/> |
| </c:url></strong> |
| |
| <a href="<strong>${url}</strong>" class="bubble hMargin">clear cart</a> |
| </c:if></pre></div> |
| |
| <p>The <code>clear=true</code> parameter is set by adding a <code><c:param</code> tag |
| between the <code><c:url></code> tags. A variable named '<code>url</code>' is set |
| using <c:url>'s <code>var</code> attribute, and <code>var</code> is then accessed |
| in the HTML anchor tag using the <code>${url}</code> expression.</p> |
| |
| <p>You can download and examine |
| <a href="https://netbeans.org/projects/samples/downloads/download/Samples%252FJavaEE%252Fecommerce%252FAffableBean_snapshot6.zip">snapshot |
| 6</a> to see how all links in the project have been encoded.</p> |
| |
| <p class="alert">URL rewriting should only be used in the event that cookies are not an |
| available tracking method. URL rewriting is generally considered a suboptimal solution |
| because it exposes the session ID in logs, bookmarks, referer headers, and cached HTML, |
| in addition to the browser's address bar. It also requires more server-side resources, |
| as the server needs to perform additional steps for each incoming request in order |
| to extract the session ID from the URL and pair it with an existing session.</p> |
| </div> |
| |
| |
| <br> |
| <h2 id="time-out">Handling Session Time-Outs</h2> |
| |
| <ul> |
| <li><a href="#time-interval">Setting Session Time Intervals</a></li> |
| <li><a href="#programmatically">Programmatically Handling Session Time-Outs</a></li> |
| </ul> |
| |
| <div class="indent"> |
| |
| <h3 id="time-interval">Setting Session Time Intervals</h3> |
| |
| <p>You should consider the maximum time interval which your server maintains sessions for. |
| If your website receives heavy traffic, a large number of sessions could expend your |
| server's memory capacity. You might therefore shorten the interval in hopes of removing |
| unused sessions. On the other hand, you certainly wouldn't want to cut sessions too short, |
| as this could become a usability issue that might have a negative impact on the business |
| behind the website. Taking the <code>AffableBean</code> application as an example, a user |
| proceeds to checkout after filling her shopping cart with items. She then realizes she |
| needs to enter her credit card details and goes off to find her purse. After returning |
| to her computer with credit card in hand, she fills in the checkout form and clicks submit. |
| During this time however, her session has expired on the server. The user sees that her |
| shopping cart is empty and is redirected to the homepage. Will she really take the time |
| to step through the process again?</p> |
| |
| <p>The following steps demonstrate how to set the session time-out interval in the |
| <code>AffableBean</code> project to 10 minutes. Of course, the actual duration ultimately |
| depends on your server resources, the business objectives of the application, and the |
| popularity of your website.</p> |
| |
| <ol> |
| <li>Open the application's deployment descriptor in the editor. Press Alt-Shift-O |
| (Ctrl-Shift-O on Mac) to use the IDE's Go to File dialog. Type in '<code>web</code>', |
| then click OK. |
| |
| <br> |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/manage-sessions/go-to-file.png" |
| class="margin-around b-all" alt="Go to File dialog" |
| title="The Go to File dialog enables quick navigation to project files"> |
| |
| <br> |
| The editor displays the <code>web.xml</code> file in the XML view. The |
| template that NetBeans provides for the <code>web.xml</code> file includes |
| a default setting for 30 minutes. |
| |
| <pre class="examplecode"> |
| <session-config> |
| <session-timeout> |
| 30 |
| </session-timeout> |
| </session-config></pre></li> |
| |
| <li>Click the General tab, and type in '<code>10</code>' in the Session Timeout field. |
| |
| <br> |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/manage-sessions/session-timeout.png" |
| class="margin-around b-all" alt="General tab of web.xml file" style="width:688px" |
| title="Specify session time-out for the application under the web.xml's General tab"></li> |
| |
| <li>Save the file (Ctrl-S; ⌘-S on Mac). |
| |
| <br><br> |
| If you switch back to the XML view, you'll see that the <code><session-timeout></code> |
| element has been updated. |
| |
| <pre class="examplecode"> |
| <session-config> |
| <session-timeout>10</session-timeout> |
| </session-config></pre> |
| </li> |
| </ol> |
| |
| <p class="notes"><strong>Note:</strong> Alternatively, you could remove the <code><session-timeout></code> |
| element altogether, and edit the <code>session-properties</code> element in the GlassFish-specific |
| deployment descriptor (<code>sun-web.xml</code>). This would set the global time-out for all |
| applications in the server's web module. See the |
| <a href="http://docs.sun.com/app/docs/doc/821-1752/beaha" target="_blank">Oracle GlassFish Server |
| 3.0.1 Application Development Guide: Creating and Managing Sessions</a> for more details.</p> |
| |
| |
| <h3 id="programmatically">Programmatically Handling Session Time-Outs</h3> |
| |
| <p>If your application relies on sessions, you need to take measures to ensure that it can |
| gracefully handle situations in which a request is received for a session that has timed |
| out or cannot be identified. You can accomplish this in the <code>AffableBean</code> |
| application by creating a simple filter that intercepts requests heading to the <code>ControllerServlet</code>. |
| The filter checks if a session exists, and if not, it forwards the request to the site's |
| welcome page.</p> |
| |
| <ol> |
| <li>Start by examining the problem that arises when a session times out midway through |
| a user's visit to the site. Temporarily reset the session time-out interval to one |
| minute. Open the web deployment descriptor (<code>web.xml</code>) and enter '<code>1</code>' |
| between the <code><session-timeout></code> tags. |
| |
| <pre class="examplecode"> |
| <session-config> |
| <session-timeout><strong>1</strong></session-timeout> |
| </session-config></pre></li> |
| |
| <li>Run the <code>AffableBean</code> project. In the browser, click into a category page, |
| add several items to your cart, then click 'view cart'. |
| |
| <br> |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/manage-sessions/cart-page-session-intact.png" |
| class="margin-around b-all" alt="Cart page displaying items in shopping cart" style="width:688px" |
| title="The cart page relies on a session object to display items in shopping cart"></li> |
| |
| <li>Wait at least one full minute.</li> |
| |
| <li>Update the quantity for one of the items displayed in the cart page. (Any number between |
| 1 and 99 is acceptable.) Click 'update'. The server returns an HTTP Status 500 message. |
| |
| <br> |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/manage-sessions/glassfish-error-report.png" |
| class="margin-around b-all" alt="GlassFish error report displayed in browser" style="width:688px" |
| title="NullPointerException occurs when request for expired session is received"></li> |
| |
| <li>Examine the GlassFish server log in the IDE. Open the Output window (Ctrl-4; ⌘-4 on Mac) |
| and select the GlassFish Server tab. Scroll to the bottom of the log to examine the error's stack |
| trace. |
| |
| <br> |
| <a href="../../../../images_www/articles/73/javaee/ecommerce/manage-sessions/gf-server-output.png" rel="lytebox" |
| title="NullPointerException occurs when request belonging to expired session is received"> |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/manage-sessions/gf-server-output.png" |
| class="margin-around b-all" alt="GlassFish error report displayed in browser" style="width:688px" |
| title="Click to enlarge"></a> |
| |
| <br> |
| The server log indicates that a <code>NullPointerException</code> occurred at line 184 |
| in the <code>ControllerServlet</code>. The Output window forms a link to the line where |
| the exception occurred.</li> |
| |
| <li>Click the link. You navigate directly to line 184 in the <code>ControllerServlet</code>. |
| Hovering your mouse over the error badge in the editor's left margin provides a tooltip |
| describing the exception. |
| |
| <br> |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/manage-sessions/nullpointer-exception.png" |
| class="margin-around b-all" alt="Error badge and tooltip displayed in editor" |
| title="Error badge and tooltip indicate the location and cause of the problem"> |
| |
| <br> |
| Because the session had already expired before the request was received, the servlet |
| engine was unable to associate the request with its corresponding session. It was |
| therefore unable to locate the <code>cart</code> object (line 151). The exception |
| finally occurred in line 184 when the engine attempted to call a method on a variable |
| equating to <code>null</code>. |
| |
| <br><br> |
| Now that we've identified the problem, let's fix it by implementing a filter.</li> |
| |
| <li>Click the New File ( |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/common/new-file-btn.png" |
| alt="New File button"> ) button in the IDE's toolbar. (Alternatively, press Ctrl-N; |
| ⌘-N on Mac.)</li> |
| |
| <li>Select the <strong>Web</strong> category, then select <strong>Filter</strong> |
| and click Next.</li> |
| |
| <li>Name the filter <code>SessionTimeoutFilter</code>. Type <code>filter</code> into |
| the Packages field so that the filter class is placed in a new package when created.</li> |
| |
| <li>Click Next. Accept default settings and click Finish. A template for the <code>SessionTimeoutFilter</code> |
| is generated and opens in the editor. |
| |
| <br><br> |
| <p class="notes"><strong>Note:</strong> Currently, in NetBeans 6.9, it isn't possible |
| to use the wizard to set a mapping to a servlet that isn't registered in the web |
| deployment descriptor. (<code>ControllerServlet</code> was registered using the |
| <code>@WebServlet</code> annotation.) We'll therefore modify the generated code |
| in the next step.</p></li> |
| |
| <li>Modify the <code>@WebFilter</code> annotation signature so that it appears as follows. |
| |
| |
| <pre class="examplecode">@WebFilter(<strong>servletNames = {"Controller"}</strong>) |
| public class SessionTimeoutFilter implements Filter {</pre> |
| |
| This sets the filter to intercept any requests that are handled by the <code>ControllerServlet</code>. |
| (Alternatively, you could have kept the <code>urlPatterns</code> attribute, and listed all |
| patterns that the <code>ControllerServlet</code> handles.) |
| |
| <br><br> |
| Note that '<code>Controller</code>' is the name of the <code>ControllerServlet</code>, |
| as specified in the servlet's <code>@WebServlet</code> annotation signature. Also note |
| that you've removed the <code>filterName</code> attribute, since the name of the filter |
| class is used by default. |
| |
| <br><br> |
| The IDE's filter template provides a lot of interesting code which is worth inspecting |
| in its own right. However, most of it is not needed for our purposes here. Any filter |
| class must implement the <code>Filter</code> interface, which defines three methods: |
| |
| <ul style="margin: 5px 0 0 -.7em"> |
| <li><strong><code>init</code>:</strong> performs any actions after the filter is initialized |
| but before it is put into service</li> |
| <li><strong><code>destroy</code>:</strong> removes the filter from service. This method can |
| also be used to perform any cleanup operations.</li> |
| <li><strong><code>doFilter</code>:</strong> used to perform operations for each request the |
| filter intercepts</li> |
| </ul> |
| |
| <p class="tips">Use the Javadoc Index Search to pull up documentation on the |
| <code>Filter</code> interface. Press Shift-F1 (fn-Shift-F1 on Mac), then type |
| '<code>Filter</code>' into the search field and hit Enter. Select the 'Interface |
| in javax.servlet' entry. The Javadoc documentation displays in the lower pane of |
| the index search tool.</p></li> |
| |
| <li>Replace the body of the <code>SessionTimeoutFilter</code> with the following contents. |
| |
| <pre class="examplecode"> |
| @WebFilter(servletNames = {"Controller"}) |
| public class SessionTimeoutFilter implements Filter { |
| |
| <strong>public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) |
| throws IOException, ServletException { |
| |
| HttpServletRequest req = (HttpServletRequest) request; |
| |
| HttpSession session = req.getSession(false); |
| |
| // if session doesn't exist, forward user to welcome page |
| if (session == null) { |
| try { |
| req.getRequestDispatcher("/index.jsp").forward(request, response); |
| } catch (Exception ex) { |
| ex.printStackTrace(); |
| } |
| return; |
| } |
| |
| chain.doFilter(request, response); |
| } |
| |
| public void init(FilterConfig filterConfig) throws ServletException {} |
| |
| public void destroy() {}</strong> |
| |
| }</pre></li> |
| |
| <li>Press Ctrl-Shift-I (⌘-Shift-I on Mac) to fix import statements. |
| (Imports need to be added for <code>HttpServletRequest</code> and <code>HttpSession</code>.) |
| Also, use the editor hints to add the <code>@Override</code> annotation |
| to the <code>init</code>, <code>destroy</code>, and <code>doFilter</code> |
| methods. |
| |
| <br><br> |
| In the coming steps, you run the debugger on the project and step through the |
| <code>doFilter</code> method to see how it determines whether the request is bound |
| to an existing session.</li> |
| |
| <li>Open the Breakpoints window (Alt-Shift-5; Ctrl-Shift-5 on Mac) and ensure that |
| you do not have any existing breakpoints set. To delete a breakpoint, right-click |
| the breakpoint and choose Delete. (If you completed the above exercise, |
| <a href="#http-monitor">Examining Client-Server Communication with the HTTP |
| Monitor</a>, you may have an outstanding breakpoint set in the <code>ControllerServlet</code>.)</li> |
| |
| <li>Run the debugger. Click the Debug Project ( |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/common/debug-project-btn.png" |
| alt="Debug Project button"> ) button in the IDE's main toolbar.</li> |
| |
| <li>When the welcome page displays in the browser, select a category, then add several |
| items to your shopping cart.</li> |
| |
| <li>Set a breakpoint on the line in <code>SessionTimeoutFilter</code>'s |
| <code>doFilter</code> method that tries to access the session (line 32). |
| |
| <br> |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/manage-sessions/filter-breakpoint.png" |
| class="margin-around b-all" alt="Breakpoint set in editor" |
| title="Set a breakpoint on the getSession method"></li> |
| |
| <li>In the browser, click the 'view cart' button. Switch to the IDE and note that the |
| debugger has suspended on the breakpoint. |
| |
| <br><br> |
| Recall that <code>getSession()</code> creates a new session object if |
| the current one doesn't exist. Here, we use <code>getSession(false)</code>, |
| which refrains from creating a new object if none is found. In other words, |
| the method returns <code>null</code> if the session doesn't exist.</li> |
| |
| <li>Click the Step Over ( |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/manage-sessions/step-over-btn.png" |
| alt="Step Over button"> ) button, then hover your mouse over the <code>session</code> |
| variable. Provided that a minute hasn't passed since the previous request was |
| sent, you'll see that the variable has been assigned to a <code>StandardSessionFacade</code>. |
| This represents the session object for the request. |
| |
| <br> |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/manage-sessions/session-exists.png" |
| class="margin-around b-all" alt="Popup displaying 'session' variable assigned to a session object" |
| title="Hover your mouse over variables to determine their current value"></li> |
| |
| <li>Continue stepping through the method until the request is processed. Since <code>session</code> |
| doesn't equal <code>null</code>, you skip the <code>if</code> statement and <code>chain.doFilter</code> |
| then forwards the request to the <code>ControllerServlet</code> (line 44).</li> |
| |
| <li>In the browser, make sure a full minute has passed, then update a quantity for |
| one of the product items in your cart. This is the same procedure we went through |
| earlier in the exercise when the status 500 message was returned. Now that the |
| filter intercepts requests heading to the <code>ControllerServlet</code>, let's |
| see what happens when a session time-out occurs.</li> |
| |
| <li>After clicking 'update', switch to the IDE and note that the debugger is again suspended |
| on the breakpoint set in the filter.</li> |
| |
| <li>Highlight the <code>req.getSession(false)</code> expression, then hover your |
| mouse over it. Here you see the expression equates to <code>null</code>, as the |
| session has already expired. |
| |
| <br> |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/manage-sessions/session-null.png" |
| class="margin-around b-all" alt="Popup displaying 'session' variable equates to 'null'" |
| title="Highlight expressions and hover your mouse over them to determine their current value"></li> |
| |
| <li>Continue stepping through the code. Now that the <code>session</code> variable |
| equals <code>null</code>, the <code>if</code> statement on line 35 is processed, |
| and the request is forwarded to <code>/index.jsp</code>. When the debugger finishes |
| executing, you'll see that the browser displays the site's welcome page.</li> |
| |
| <li>Click the Finish Session ( |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/manage-sessions/finish-session-btn.png" |
| alt="Finish Session button"> ) button to terminate the debug session.</li> |
| |
| <li>Open the project's <code>web.xml</code> file and change the session time-out interval |
| back to 10 minutes. |
| |
| <pre class="examplecode"> |
| <session-config> |
| <session-timeout><strong>10</strong></session-timeout> |
| </session-config></pre> |
| </li> |
| |
| <li>Save (Ctrl-S; ⌘-S on Mac) the file.</li> |
| </ol> |
| </div> |
| |
| <p><a href="https://netbeans.org/projects/samples/downloads/download/Samples%252FJavaEE%252Fecommerce%252FAffableBean_snapshot6.zip">Snapshot |
| 6</a> provides you with the completed project version for this tutorial unit. One final topic |
| concerning session management should be mentioned. You can explicitly terminate a session by |
| calling the <code>invalidate</code> method on the session object. If the session is no longer |
| needed, it should be removed in order to conserve the memory available to your server. After |
| you complete the next unit, <a href="transaction.html">Integrating Transactional Business |
| Logic</a>, you will see how the <code>ControllerServlet</code>, upon successfully processing |
| a customer order, destroys the user's <code>cart</code> object and terminates the session |
| using the <code>invalidate</code> method.</p> |
| |
| <div class="indent"> |
| <pre class="examplecode" style="width:710px; margin-left:10px; margin-top:-2px"> |
| // if order processed successfully send user to confirmation page |
| if (orderId != 0) { |
| |
| // dissociate shopping cart from session |
| cart = null; |
| |
| // end session |
| session.invalidate(); |
| |
| ... |
| }</pre></div> |
| |
| <p>This is demonstrated in |
| <a href="https://netbeans.org/projects/samples/downloads/download/Samples%252FJavaEE%252Fecommerce%252FAffableBean_snapshot8.zip">project |
| snapshot 8</a> (and later snapshots).</p> |
| |
| |
| <div class="feedback-box"> |
| <a href="/about/contact_form.html?to=3&subject=Feedback: NetBeans E-commerce Tutorial - Managing Sessions">Send |
| Us Your Feedback</a></div> |
| |
| <br style="clear:both;"> |
| |
| |
| <h2 id="seeAlso">See Also</h2> |
| |
| <div class="indent"> |
| <h3>NetBeans Resources</h3> |
| |
| <ul> |
| <li><a href="../../../../features/java/debugger.html" target="_blank">NetBeans IDE Features: Debugger</a></li> |
| <li><a href="../../java/debug-multithreaded.html" target="_blank">Debugging Multithreaded Applications</a></li> |
| <li><a href="../../java/debug-multithreaded-screencast.html" target="_blank">Video of the Multithreaded Debugging with the NetBeans IDE</a></li> |
| <li><a href="../../java/debug-evaluator-screencast.html" target="_blank">Video of Using the Code Snippet Evaluator in the NetBeans Debugger</a></li> |
| <li><a href="../../../../community/media.html" target="_blank">Video Tutorials and Demos for NetBeans IDE</a></li> |
| <li><a href="https://netbeans.org/projects/www/downloads/download/shortcuts.pdf">Keyboard Shortcuts & Code Templates Card</a></li> |
| <li><a href="../javaee-gettingstarted.html" target="_blank">Getting Started with Java EE Applications</a></li> |
| <li><a href="../javaee-intro.html" target="_blank">Introduction to Java EE Technology</a></li> |
| <li><a href="../../../trails/java-ee.html" target="_blank">Java EE & Java Web Learning Trail</a></li> |
| </ul> |
| |
| <h3>GlassFish Resources</h3> |
| |
| <ul> |
| <li><a href="http://wiki.glassfish.java.net/Wiki.jsp?page=Screencasts" target="_blank">GlassFish Screencasts</a></li> |
| <li><a href="http://glassfish.dev.java.net/docs/index.html" target="_blank">GlassFish v3 Documentation</a></li> |
| <li><a href="http://www.sun.com/offers/details/GlassFish_Tomcat.html" target="_blank">Learning GlassFish for Tomcat Users</a></li> |
| <li><a href="http://docs.sun.com/app/docs/doc/821-1751" target="_blank">Oracle GlassFish Server 3.0.1 Administration Guide</a></li> |
| <li><a href="http://docs.sun.com/app/docs/doc/821-1750" target="_blank">Oracle GlassFish Server 3.0.1 Application Deployment Guide</a></li> |
| <li><a href="http://docs.sun.com/app/docs/doc/821-1752" target="_blank">Oracle GlassFish Server 3.0.1 Application Development Guide</a></li> |
| </ul> |
| |
| <h3>Technical Articles & Miscellaneous Resources</h3> |
| |
| <ul> |
| <li><a href="http://java.sun.com/javaee/reference/code/" target="_blank">Java EE Code Samples & Apps</a></li> |
| <li><a href="http://java.sun.com/j2se/javadoc/" target="_blank">Javadoc Tool</a> [product homepage]</li> |
| <li><a href="http://java.sun.com/j2se/javadoc/writingdoccomments/index.html" target="_blank">How to Write Doc Comments for the Javadoc Tool</a></li> |
| <li><a href="http://java.sun.com/products/servlet/Filters.html" target="_blank">The Essentials of Filters</a></li> |
| <li><a href="http://java.sun.com/blueprints/corej2eepatterns/Patterns/InterceptingFilter.html" target="_blank">Core J2EE Patterns - Intercepting Filter</a></li> |
| <li><a href="http://courses.coreservlets.com/Course-Materials/csajsp2.html" target="_blank">Beginning and Intermediate-Level Servlet, JSP, and JDBC Tutorials</a></li> |
| <li><a href="http://courses.coreservlets.com/Course-Materials/msajsp.html" target="_blank">Advanced Servlet and JSP Tutorials</a></li> |
| <li><a href="http://courses.coreservlets.com/Course-Materials/java5.html" target="_blank">Java 5 & Java 6 Tutorials</a></li> |
| <li><a href="http://www.ibm.com/developerworks/java/library/j-jstl0211.html" target="_blank">A JSTL primer, Part 1: The expression language</a></li> |
| <li><a href="http://www.ibm.com/developerworks/java/library/j-jstl0318/index.html" target="_blank">A JSTL primer, Part 2: Getting down to the core</a></li> |
| </ul> |
| </div> |
| |
| </body> |
| </html> |