In this article, we will look in depth at session management (90,500) in web applications. In the article, “Tutorial: Review of HTTP Methods and Servlet API for the Web Component Developer Exam” we briefly mentioned session objects and the role they have in maintaining a client conversation during which a client interacts with the web application, but now we will go in depth to look at how session objects are created, retrieved, updated and destroyed during a client session. This is part of a series of articles to help you prepare for the web component developer exam.

Session Management for Maintaining Conversations

The core architecture of the means of communicating with servlets doesn’t lend itself to remember that state of client communication with a web application. This is because HTTP is a stateless protocol providing no means for a server to recognize that a series of requests originate from the same client. Fortunately the HttpSession API provides a solution for maintaining client state across multiple client requests by using an HttpSession object to hold conversational state. This is very important for ecommerce applications where maintaining a shopping cart while the user is browsing through the site is absolutely essential.

The HttpSession object is a means to provide each client with a unique identifier that allows the server identify it and to furnish it with information that the server can be used to properly handle a request. Initially we will look at the traditional session-tracking techniques such as user authorization, hidden form fields, URL rewriting, and persistent cookies that was originally used by CGI developers. Then we will look at the built-in support for session tracking in the HttpSession API. The support is built upon traditional techniques and greatly simplifies the task of session tracking in your servlets. A figure of HttpSession is shown below:

Tutorial:In Depth Look at Session Management for Web Component Developer Exam-a16-httpsessionwithsetattribute.jpg
Figure: HttpSession with Attribute being set

One way to perform session tracking is to leverage the information that comes with user authorization. This is done when a web server restricts access to some of its resources to only those clients that have been authenticated. After the client is authenticated, the username can be accessed by a servlet through getRemoteUser().

We can use the username to track a client session. Once a user has logged in, the browser remembers her username and resends the name and password as the user views new pages on the site. A servlet can identify the user through her username and thereby track her session. This allows a user to continue to add items to a ecommerce shopping cart and for that information to be persisted. If the user ends their shopping and returns later, the shopping cart can be reactivated with all of the items the user had previously selected. An example of adding items to a shopping cart is shown below:

Java Code: Example of Adding Items to a Shopping Cart
String name = req.getRemoteUser(); 
if (name == null) {
// Explain that the server administrator should protect this page
} 
else {
   String[] items = req.getParameterValues("item"); 
   if (items != null) {
      for (int i = 0; i < items.length; i++) { 
         addItemToCart(name, items[i]);
      }
   }
}
And now the items for the user’s cart can be retrieved:

String name = req.getRemoteUser(); 
if (name == null) {
   // Explain that the server administrator should protect this page
} else {
   String[] items = getItemsFromCart(name);
}
As you can see, it is easy to use user authorization in order to perform session tracking. You only need to have the server secure the relevant set of pages, and then use getRemoteUser() method to identify each client. This approach works irrespective of where the user access the site. It can be from any laptop, tablet computer or smart phone.

There are two disadvantages of the requirement of the user authenticate to use the site. The first is that the user cannot have more than one session on the same site and the second is that the user must authenticate him or herself every time they visit the site. Most users will accept this as a small price to pay for session tracking, but it is not really necessary in order to provide session tracking. In fact session tracking can be done anonymously without requiring authentication.

Hidden Form Fields

One approach to anonymous session tracking is to use hidden form fields. In this approach hidden fields added to an HTML form that are not shown to the client. When the form is submitted, the hidden fields are sent back to the server with the normal form fields. An example of a form with hidden fields are shown below:

XML Code: Form with Hidden Fields
<FORM ACTION="/store/FootballSearch" METHOD="POST">
 ... 
<INPUT TYPE=hidden NAME="postalCode" VALUE="SE1 3JT"> 
<INPUT TYPE=hidden NAME="userType" VALUE="intermediate">
... 
</FORM>
For the servlet that handles the form, FootballSearch, there is no difference between a hidden or visible fields. They are all accessed via the same methods, getParameter or getParameter. By using hidden form fields, it is possible to refactor the shopping cart servlets so that users can shop anonymously until check-out time. The listing below shows how this can be done:

Java Code: Session Management with Hidden Fields
/**
 * Servlet implementation class ShoppingCartViewer
 */
@WebServlet("/ShoppingCartViewer")
public class ShoppingCartViewer extends HttpServlet {
	private static final long serialVersionUID = 1L;

	/**
	 * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse
	 *      response)
	 */
	protected void doGet(HttpServletRequest request,
			HttpServletResponse response) throws ServletException, IOException {
		response.setContentType("text/html");
		PrintWriter out = response.getWriter();
		out.println("<HEAD><TITLE>Current Shopping Cart Items</TITLE></HEAD>");
		out.println("<BODY>");
		// Cart items are passed in as the item parameter.
		String[] items = request.getParameterValues("item");
		// Print the current cart

		out.println("You currently have the following items in your cart:<BR>");
		if (items == null) {
			out.println("<B>None</B>");
		} else {
			out.println("<UL>");
			for (int i = 0; i < items.length; i++) {
				out.println("<LI>" + items[i]);
			}
			out.println("</UL>");
		}

		// Ask whether the user would like to add more items or check out.
		// Include the current items as hidden fields so they'll be passed on.
		out.println("<FORM ACTION=\"/servlet/ShoppingCart\" METHOD=POST>");
		if (items != null) {
			for (int i = 0; i < items.length; i++) {
				out.println("<INPUT TYPE=hidden NAME=item VALUE=\"" + items[i]
						+ "\">");
			}
		}
		out.println("Would you like to<BR>");
		out.println("<INPUT TYPE=submit VALUE=\" Add More Items \">");
		out.println("<INPUT TYPE=submit VALUE=\" Check Out \">");
		out.println("</FORM");
		out.println("</BODY></HTML>");
	}
}
The servlet reads all of the items already in the cart using getParameterValues (“item”). We’re assuming that all of the item parameter values were sent to the servlet using hidden fields. We then display the items to the user and asks if he wants to add more items or check out. The servlet output’s a form with hidden fields in order that the target of the form, the ShoppingCart servlet receives the current items as part of the submission. The problem with this approach is that as items are accumulated in the shopping cart, it is clunky to pass all of these items in hidden form fields. A better approach for large numbers of items is to pass on a unique session ID that identifies a particular client's session. The session ID can then be associated with complete information about the session that is stored on the server.

As hidden form fields is based on standard HTML it is quite straightforward to support anonymous session tracking since HTML (and hidden form fields) are supported in all the popular browsers. The disadvantage of this approach is that it only works for sequences of dynamically generated forms. If you are working with static documents, emailed documents bookmarked documents or browser shutdowns, this approach is ineffective.

URL Rewriting

Another means of supporting anonymous session tracking is URL rewriting. It is based on including extra information in every local URL. The extra information could be extra path information, additional parameters, or possibly custom, server-specific URL changes. Changes in the latest specification for HTTP have eliminated the space restriction that used to exist for URL rewriting. So it is possible to include all the information that you require as part of the URL. Below are examples of URL that have been rewritten to pass a session ID 1X59Y:

Tutorial:In Depth Look at Session Management for Web Component Developer Exam-a16-rewrittenurl.jpg
Table: Example of Original and Rewritten URLs

Basically when you’re using URL-rewriting for session tracking and you send a URL that references your site to the client, you explicitly add on the session data. Since the servlet will automatically switch to URL rewriting when if cookies aren’t supported by the client, you should encode all URLs that reference your site. The two possible places that you might use URLs referring to your own site is when:
*the URLs are embedded in the Web page that the servlet generates via use of the HttpServletResponse’s encodeURL method - The method will determine if URL-rewriting is currently in use and append the session information only if necessary. The URL is returned unchanged otherwise. An example is shown below:

Java Code: URL Rewriting with encodeURL
String baseURL = manufactureURL; 
String encodeURL = response.encodeURL(baseURL); 
out.println("<A HREF=\"" + encodeURL + "\">...</A>");
*you decide to use a URL that refers to your own site as part of a sendRedirect call (i.e., placed into the Location response header) - In this situation, as there are different rules for determining if session information needs to be attached, you need to use the HttpServletResponse’s encodeRedirectURL method rather than encodeURL method. An example is given below:

Java Code: URL Rewriting with encodeRedirectURL
String baseURL = homeURL; 
// Relative URL OK in version 2.2 S
String encodedURL = response.encodeRedirectURL(baseURL); 
response.sendRedirect(encodedURL);
There are advantages and disadvantages with each rewriting technique. Extra path information works on all servers as well as a target for forms that use both the GET and POST methods. It is problematic if the servlet needs to use the extra path information. Added parameter also works on all servers, but it fails as a target for forms using a POST method and it can create parameter naming collisions. Custom, server-specific change works only under all conditions for servers that support this type of change. Below is a revised version of the shopping cart viewer using the extra path information type of URL rewriting to anonymously track a shopping cart:

Java Code: Servlet using URL Rewriting for Session Management
/**
 * Servlet implementation class ShoppingCartViewerRewrite
 */
@WebServlet("/ShoppingCartViewerRewrite")
public class ShoppingCartViewerRewrite extends HttpServlet {
	private static final long serialVersionUID = 1L;
       
	/**
	 * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
	 */
	protected void doGet(HttpServletRequest request,
			HttpServletResponse response) throws ServletException, IOException {

		response.setContentType("text/html");
		PrintWriter out = response.getWriter();
		out.println("<HEAD><TITLE>Current Shopping Cart Items</TITLE></HEAD>");
		out.println("<BODY>");
		// Get the current session ID, or generate one if necessary
		String sessionid = request.getPathInfo(); 

		// Cart items are associated with the session ID
		String[] items = getItemsFromCart(sessionid);
		// Print the current cart items.
		out.println("You currently have the following items in your cart:<BR>");
		if (items == null) {
			out.println("<B>None</B>");
		} else {
			out.println("<UL>");
			for (int i = 0; i < items.length; i++) {
				out.println("<LI>" + items[i]);
				out.println("</UL>");
			}
		}
		// Ask if the user wants to add more items or check out.
		// Include the session ID in the action URL.
		String url = request.getContextPath() + "/servlet/ShoppingCart/";
		out.println("<FORM ACTION=\"" + response.encodeRedirectURL(url)
				+ "\" METHOD=POST>");
		out.println("Would you like to<BR>");
		out.println("<INPUT TYPE=submit VALUE=\" Add More Items \">");
		out.println("<INPUT TYPE=submit VALUE=\" Check Out \">");
		out.println("</FORM>");
		// Offer a help page. Include the session ID in the URL.
		url = request.getContextPath()
				+ "/servlet/Help/?topic=ShoppingCartViewerRewrite\"";
		out.println("For help, click <A HREF=\""
				+ response.encodeRedirectURL(url) + ">here</A>");
		out.println("</BODY></HTML>");
	}

	private static String[] getItemsFromCart(String sessionid) {
		// Not implemented
		return null;
	}
}

Here the servlet attempts to retrieve the current session ID using getSession(). If there is no session, then a new session will be automatically generated. The session is then used to fetch and display the current items in the cart. We then use the encodeRedirectURL in order to rewrite the URL for the form's ACTION attribute, so it can be retrieved by the ShoppingCart servlet. We also do the same for the help URL that invokes the Help servlet. This was impossible using hidden form fields since the Help servlet isn't the target of a form submission.

The advantages of URL rewriting is that URL rewriting works for all dynamically created documents, such as the Help servlet, not just forms. Also depending on your server, you can use custom URL rewriting for static documents. Before custom URL rewriting used to be somewhat tedious but now with the encodeRedirectURL function it is very simple to do URL rewriting. In the listing above, we use it to rewrite both the form action as well as for the help page.

Persistent Cookies

Another approach that can be used for session tracking is via persistent cookies. A cookie is a set of information created by a web container and then sent to a browser. The set of information contained in a cookie is a name, a single value, and some optional attributes such as a comment, path and domain qualifiers, a maximum age, and the version number. It is one of the primary means to exchange information between the browser and web container. When a browser receives a cookie, it saves the cookie and thereafter sends the cookie back to the server each time it accesses a page on that server, subject to certain rules. Because a cookie's value can uniquely identify a client, cookies are often used for session tracking.

Tutorial:In Depth Look at Session Management for Web Component Developer Exam-a16-cookiesenttobrowser.jpg
Figure: Cookie being sent to a browser

Cookies were not part of the official HTTP specification, but have quickly became a de facto standard supported in all the popular browsers. RFC 2109 was then superseded by RFC 2965 in October 2000 which was superseded by what is considered the definitive specification for cookies, known as RFC 6265 in April 2011.

How to use Cookies

As of Servlet API 2.0, there is now the javax.servlet.http.Cookie class for using cookies. The HTTP header details for the cookies are handled by the Servlet API. You don’t need to do create a cookie yourself, this will happen automatically as well as the cookie being set in the header when the getSession method is called on the request object. Depending on the configuration of the browser, some will be setup to not accept cookies. This means that the client will ignore the “Set-Cookie” part of the response header and you will not get any exception. Instead if you are not using URL rewriting, any call to the getSession method will always return a new session and the client will never send back a request with a session ID cookie header.If you need to create a cookie yourself, you can use the following constructor:

Java Code: Syntax for Cookie Constructor
public Cookie(String name, String value)
This creates a new cookie with an initial name and value. Check Netscape’s Cookie Specification and RFC 2109 for valid names and values. The list of characters that are not supported including white spaces is shown below:

XML Code: Non supported characters for Cookies
[] ( ) = ," / ? @ :;
You can then send a cookie to a client by calling the addCookie method of the HttpServletResponse. This method will add the specified cookie provided in the argument to the response. You can also add more cookies in subsequent calls to addCookie(). Since cookies are sent in HTTP headers, you need to add them to the response before you send any content. Browsers are setup to accept a maximum of 20 cookies per site and 300 per user. The size limit of a cookie is 4096 bytes. You can set a cookie by doing the following:

Java Code: Example of Cookie being set
Cookie cookie = new Cookie("ID", "4872"); 
res.addCookie(cookie);
If you need to retrieve all the cookies sent by a browser you can use the HttpServletRequest’s getCookies() method. This method will return an array of Cookie objects sent by the browser as part of the request. If there were no cookies sent, the response will be null. The following listing shows how this can be done:
Java Code: Example of looping through an array of cookies
Cookie[] cookies = request.getCookies(); 
if (cookies ! = null) {
   for (int i = 0; i < cookies.length; i++) { 
      String name = cookies[i].getName(); 
      String value = cookies[i].getValue();
   }
}
You can also setup attributes for a cookie. The are a number of methods that can be used to set these attributes. For each attribute, there is a corresponding get and set methods. You will rarely use the get methods since when a cookie is sent to the server, it has only its name, value, and version. Let’s step through some of the methods of some of the attributes that can be set on a cookie:
  • public void Cookie.setVersion(int v) - this method sets the version of a cookie. Servlets can send and receive cookies formatted to match either both version 0 or the RFC 2109 (version 1) compatible version of cookies. The default for the construction of cookies is version 0 in order to maximize interoperability.
  • public void Cookie.setDomain(String pattern) - this method specifies the domain restriction pattern for the servers that should see a cookie. The default is for cookies to be returned only to the host that saved them. If you specify the domain name pattern, you override this. The pattern must always begin with a dot and contain at least two dots. A pattern will match only one entry beyond the initial dot. For example, “.acme.com:”$ecs is valid and matches ACME Laboratories and shopping.acme.com but not www.shopping.acme.com. See Netscape's Cookie Specification and RFC 2109 for more information about domain patterns.
  • public void Cookie.setMaxAge(int expiry) - this method specifies the maximum age of the cookie in seconds before it expires. The default is a negative value indicating that the cookie should expire when the browser exits. Zero tells the browser to delete the cookie immediately.
  • public void Cookie.setPath(String uri) - this method sets a path for the cookie. This path is the subset of URIs to which a cookie should be sent. The default is for cookies to be sent to the page that set the cookie as well as all the pages in that directory or under that directory. If for example, the servlet under /servlet/MyServlet sets a cookie, the default path is “/servlet”. That path indicates the cookie should be sent to /servlet/YourServlet and to /servlet/subdir/TheirServlet—but not to the /FooPage.html servlet alias. A path set to “/” causes a cookie to be sent to all the pages on a server. A cookie's path must be such that it includes the servlet that set the cookie.
  • public void Cookie.setSecure(boolean flag) - this indicates whether to only send the cookie over a secure channel, such as SSL. The default is false.
  • public void Cookie.setComment(String comment) - this sets the comment field of the cookie. Use this to describe the purpose of a cookie. Many web browsers will display this text to the user. This is only supported in version 1 cookies.
  • public void Cookie.setValue(String newValue) - this assigns a new value to a cookie. In version 0 cookies, values cannot contain the following: whitespace, brackets, parentheses, equals signs, commas, double quotes, slashes, question marks, at signs, colons, and semicolons. Please note that empty values may not behave identically in all browsers.

In the example below, we show the shopping cart viewer that maintains the shopping cart using persistent cookies:

Java Code: Servlet using Cookie for Session Management
/**
 * Servlet implementation class ShoppingCartViewerCookie
 */
@WebServlet("/ShoppingCartViewerCookie")
public class ShoppingCartViewerCookie extends HttpServlet {
	protected void doGet(HttpServletRequest request,
			HttpServletResponse response) throws ServletException, IOException {
		response.setContentType("text/html");
		PrintWriter out = response.getWriter();
		// Get the current session ID by searching the received cookies.
		String sessionid = null;
		Cookie[] cookies = request.getCookies();
		if (cookies != null) {
			for (int i = 0; i < cookies.length; i++) {
				if (cookies[i].getName().equals("sessionid")) {
					sessionid = cookies[i].getValue();
					break;
				}
			}
		}

		// If the session ID wasn't sent, generate one.
		// Then be sure to send it to the client with the response.
		if (sessionid == null) {
			session = generateSessionId();
			Cookie c = new Cookie("sessionid", sessionid);
			response.addCookie(c);
		}
		out.println("<HEAD><TITLE>Current Shopping Cart Items</TITLE></HEAD>");
		out.println("<BODY>");
		// Cart items are associated with the session ID
		String[] items = getItemsFromCart(sessionid);
		// Print the current cart items.
		out.println("You currently have the following items in your cart:<BR>");
		if (items == null) {
			out.println("<B>None</B>");
		} else {
			out.println("<UL>");
			for (int i = 0; i < items.length; i++) {
				out.println("<LI>" + items[i]);
			}
			out.println("</UL>");
		}

		// Ask if they want to add more items or check
		out.println("<FORM ACTION=\"/servlet/ShoppingCart\" METHOD=POST>");
		out.println("Would you like to<BR>");
		out.println("<INPUT TYPE=submit VALUE=\" Add More Items \">");
		out.println("<INPUT TYPE=submit VALUE=\" Check Out \">");
		out.println("</FORM>");
		// Offer a help page.
		out.println("For help, click <A HREF=\"/servlet/Help"
				+ "?topic=ShoppingCartViewerCookie\">here</A>");
		out.println("</BODY></HTML>");
	}
...

}
In the listing, first the servlet tries to fetch the client's session ID by iterating through the cookies that are part of the request. If there is no cookie containing a session ID, the servlet generates a new one using the generateSessionId() method that has been added to the servlet and then adds a cookie containing the new session ID to the response.

Using cookies offer an efficient and easy way to implement session tracking. In each request, the cookie automatically provides either a client's session ID or a list of the client's preferences. Also, there is the possibility to customize cookies and give them more versatility and power. The only problem is that some browsers are configured to not accept cookies. In this case, you will need to use either URL rewriting or hidden fields in a form.

Session Management using the Session Tracking API

Although there are a number of approaches available for a servlet to manage its own sessions, fortunately the Servlet API has provided several methods and classes specifically designed specifically to handle session tracking on behalf of servlets. In fact, the servlets have built in session tracking.

The session tracking aspect of the Servlet API is supported in all of the main web and application servers in the Java web and application market. Although initially the level of support was not uniform across all vendors in version 2.0 of the Servlet API, by version 2.4 this situation has improved a great deal because of the importance of ecommerce in the growth of the market. The minimal implementation provided by the servlet classes in JSDK 2.4 manages sessions through the use of persistent cookies. Many servers build on top of this base and provide additional features and capabilities. For example, some of the major web servers also have the ability to revert to using URL rewriting when cookies fail as well as allowing session objects to be persisted to the server's disk when memory is full or on a server shutdown. In this situation, you would need to ensure that all of the items that you place in the session would need to be serializable (i.e. implement the Serializable interface )

Session Tracking Basics

Using sessions in servlets is very simple and basically involves the following options:
Looking Up the HttpSession Object Associated with the Current Request - generally you get the HttpSession object by using the HttpServletRequest’s getSession method. The web container extracts the unique session ID from a cookie or attached URL data, then uses that as a key to lookup the HttpSession object in a table. If there is no valid HttpSession in the table, the getSession method returns null. From the client perspective this means that the user is not presently participating in a session, so then the container will create a new session. So there is no need to ever use the overloaded version of getSession which takes a boolean as its argument. That version is only used when you want to discover is there already a pre-existing session. Either it returns the existing session or null if there is no session associated with the client. An example of the no argument version of the getSession is shown below:

Java Code: Example of getSession Method
HttpSession session = request.getSession();
Looking Up Information Associated with a Session - The HttpSession objects in which you obtain a reference with are live on the server and are automatically associated with the client by either cookies or URL-rewriting. Session objects have their own built-in data structure that allows you store any number of keys and associated values. You can use session.getAttribute(“myAttribute”) to look up previously stored attribute values in the system. As the return type is Object, you will need to do a type- cast to the specific type of data that was associated with the attribute name in the session. The return value is null if there is no such attribute, so you’ll need to check for null before calling methods on objects associated with sessions. Below is an example of using getAttribute and setAttribute involving a shopping cart:

Java Code: Use of getAttribute and setAttribute
HttpSession session = request.getSession(true); 
ShoppingCart cart = (ShoppingCart)session.getAttribute("shoppingCart"); 
if (cart == null) { 
   // No cart already in session
   cart = new ShoppingCart(); 
   session.setAttribute("shoppingCart", cart); 
   doSomethingWith(cart);
}
Although in most cases, you will know the name of the attribute for which you are looking, there are times when you are only looking to discover what attributes exists in a session. In that case, you can use getAttributeNames. This method will return an Enumeration, similar to the getHeaderNames and getParameterNames methods in HttpServletRequest.

Although the data that was explicitly associated with a session is the part you care most about, there are some other pieces of information that are sometimes useful as well. Below is a summary of the key methods available in the HttpSession class:
  • public Object getAttribute(String name) - this method extracts a previously stored value from a session object. It will return null if there is no value associated with the given name.
  • public void setAttribute(String name, Object value) - this method associates a value with a name. If the object supplied to setAttribute implements the HttpSessionAttributeListener interface, (which we discussed in the previous article, “Tutorial:Web Container Architecture and Services for Component Developer Exam”), the object’s attribute added or replaced event is triggered after it is stored in the session. Conversely, if the previous value implements HttpSessionBindingListener, its object added method is called.
  • public void removeAttribute(String name) - this method removes any value associated with the designated name. If the value being removed implements HttpSessionAttributeListener or HttpSessionBindingListener the attribute or object removed event is triggered.
  • public Enumeration getAttributeNames() - this method return the names of all attributes in the session.
  • public String getId() - this method returns the unique identifier generated for each session. It is often used as the key name when only a single value is associated with a session, or when logging information about sessions.
  • public boolean isNew() - this method returns true if the client (browser) has not yet responded with the session ID. It returns false for preexisting sessions.
  • public long getCreationTime() - this method returns the time in milliseconds since midnight, January 1, 1970 (GMT) at which the session was first built. To transform into a useful value you need to pass this to either a Date constructor or the setTimeInMillis method of GregorianCalendar.
  • public long getLastAccessedTime() - this method returns the time in milliseconds since midnight, January 1, 1970 (GMT) at which the session was last sent from the client.
  • public void setMaxInactiveInterval(int seconds) - this method specifies the time, in seconds, between client requests before the servlet container will invalidate this session. A negative value indicates that the session should never time out. This time out is held on the server and is different from the cookie expiration date sent to the client.
  • public void invalidate() - this method invalidates the session and unbinds all objects associated with it.


Associating Information with a Session - We can read and write information associated with a session by using getAttribute and the setAttribute methods. You can have your values trigger events when they are stored in a session by having the object that you are associating with the session implement the HttpSessionAttributeListener or HttpSessionBindingListener interfaces. Then every time setAttribute is called on one of these objects, its attribute added or object added events will be triggered.

If you replace previous values, then only if you have implemented the HttpSessionAttributeListener interface will you get an attribute replaced event. Below is an example using a ShoppingCart class to demonstrate the use of attributes in a session.

Java Code: Use of setAttribute in Shopping Cart Example
HttpSession session = request.getSession(true);
session.setAttribute("referringPage", 
request.getHeader("Referer"));
ShoppingCart cart = (ShoppingCart)session.getValue("previousItems");
if (cart == null) { 
   // No cart already in 
   session cart = new ShoppingCart(); 
   session. setAttribute("previousItems", cart);
} 
String itemID = request.getParameter("itemID"); 
if (itemID != null) {
   cart.addItem(Catalog.getItem(itemID));
}
Terminating Sessions - Sessions will timeout when the client access to the session has exceeded the interval specified by getMaxInactiveInterval. When this occurs, any objects bound to the HttpSession object will be automatically unbound (and trigger an object removed event if the HttpSessionBindingListener interface has been implemented).
If you want to explicitly deactivate a session, you can use the session’s invalidate method.
This is shown below:

Java Code: Example of invalidate method
session.invalidate();
The Session Life Cycle

Sessions have a lifecycle similar to servlets. A session will either expires automatically, after a period of inactivity or it can be manually invalidated in a servlet by calling session.invalidate(). When a session expires (or is invalidated), the HttpSession object and the data values it contains are removed from the system and any events related to listeners for the HttpSession are triggered. A figure is shown below:

Tutorial:In Depth Look at Session Management for Web Component Developer Exam-a16-httpsessionlifecycle.jpg
Figure: HttpSession Lifecycle

Any information saved in a user's session object is lost once the session is invalidated. If you want to persist information beyond that time, you need to store it in an external location like a database or use a persistent cookie. There are several methods involved in managing the session life cycle:
  • public boolean HttpSession.isNew() - this method returns whether the session is new. New sessions have been created by the server but not yet acknowledged by the client. In the case of a client having cookies disabled, all calls to getSession return new sessions.
  • public void HttpSession.invalidate() - this method causes the session to be immediately invalidated. All objects stored in the session are immediately unbound.
  • public long HttpSession.getCreationTime() - this method returns a long value representing the time when this session was created, measured in milliseconds since midnight January 1, 1970 GMT..
  • public long HttpSession.getLastAccessedTime() - this method returns a long value representing the last time the client sent a request associated with this session, as the number of milliseconds since midnight January 1, 1970 GMT, and marked by the time the container received the request.

All the methods associated with the session lifecycle throw an IllegalStateException if the session being accessed is invalid. An example of a servlet manually invalidating a session is shown below:

Java Code: Example of Servlet manually invalidating a session
/**
 * Servlet implementation class ManualInvalidate
 */
@WebServlet("/ManualInvalidate")
public class ManualInvalidate extends HttpServlet {
	private static final long serialVersionUID = 1L;

	/**
	 * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse
	 *      response)
	 */
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		response. setContentType ("text/html"); 
		PrintWriter out = response.getWriter();
		// Get the current session object, create one if necessary 
		HttpSession session = request.getSession(true);
		// Invalidate the session if it's more than a day old or has been 
		// inactive for more than an hour. 
		if (!session.isNew()) { 
			// skip new sessions
			Date dayAgo = new Date(System.currentTimeMillis() - 24*60*60*1000); 
			Date hourAgo = new Date(System. currentTimeMillis() - 60*60*1000); 
			Date created = new Date(session.getCreationTime()); 
			Date accessed = new Date(session.getLastAccessedTime());
			if (created.before(dayAgo) ¦¦ accessed.before(hourAgo)) { 
				session.invalidate(); 
				session = request.getSession(true); // get a new session
			}
		}
		// Continue processing
		}
}
OK. That is it for session management. You should be fully prepared for any question on the web component developer exam for this section. Next we move on to security.