http://www.developer.com/java/using-the-httpsession-object-of-the-servlet-api.html

Back to article

Using the HttpSession object of the Servlet API


May 18, 2000

written by Matthew E. Ferris

javax.servlet.http.HttpSession is an interface that provides a way to identify a user across more than one page request or visit to a web site. While this is possible to implement using cookies, or rewriting URLs, we will save the discussion on Cookies for a future article. The way in which you as a develop use the HttpSession object can be broken down into two categories: state data and application data.

 

State data

State data has to do with the details of the connection of the user to the Web server. A brief discussion of some of these methods follows:

 

isNew()

Allows you to do determine whether the session is new. Note that a session is considered new if the server used only cookie-based sessions, and the client had disabled the use of cookies. Otherwise, a session is considered not new when the client joins the session.

 

getID ()

Every HttpSession is assigned a unique identifier by the servlet engine. This will vary from one to another. The session Ids created using Gefion Software's LiteWebServer look very different from those created when running Live Software's JRun. However, this is of no consequence, as whatever convention is used, the ID will be unique. The ID is extremely useful, as it can be used to put and get application layer data without fear of stepping on another user's data.

 

setMaxinactiveInterval(int interval) and int getMaxInactiveInterval()

This will allow you to set (and get) the maximum number of seconds that a session can remain inactive without being disposed of. This is a nice improvement over the JSDK 2.0, where you needed to manage this yourself. Now, the servlet engine will take care of this for you. If the time has expired, the session itself will be expired.

 

getCreationTime()

Allows you to get the time that the session was created, but it returns the time in milliseconds since midnight January 1, 1970 GMT (!) This is of dubious use, so you will have to do a little creative math to make it meaningful (It's one of my peeves with Java, along with a zero-based array to represent months!).

 

getLastAccessedTime()

Allows you to find out the last time the session was accessed. This is also measured from the beginning of time as we know it: Jan. 1, 1970.

 

invalidate()

Finally, if you detect some rogue user on your site that tries to hack or enter your site and has no business being there, you can show them the door by calling invalidate. This will immediately invalidate the HttpSession, and unbind any data in it.

 

Application Data

The real power of the session object is found in the application data. Though the documentation doesn't say so, somewhere up the inheritance hierarchy there must be a hashtable, because the session object supports the methods to push and pop objects on and off the session. These methods, putValue(String name, Object value) and getValue(java.lang.String name) allow you to get and set data in the session that you can use for any variety of things.

Let's say that you are building a site to allow users to buy books online (what a concept!). One thing you will need is a shopping basket, which will track the items a user purchases.

You can create a class such as this:

import java.util.*;
import java.io.Serializable;

public class ShoppingCart implements Serializable
{

private int accountNum;	
private Vector Items;


	public ShoppingCart()
	{
		Items = new Vector();
	}
	
	public int getAccountNum()
	{
		return this.accountNum;
	}

	public void setAccountNum(int accountNum)
	{
		this.accountNum = accountNum;
	}
	
	public Iterator getItems()
	{
		return this.Items.iterator();
	}

	public boolean addItem(int item)		
	{
		return Items.add(new Integer(item));
		
	}
	
	public String toString()
	{
		return "ShoppingCart for " + accountNum;
	}	
}

This is a simple example of a shopping cart that will allow you to set an account number, and then add items to the cart. Our purpose here is not to learn how to build a shopping cart, but how to manage sessions, so we will leave this design alone for now.

Your servlet might look something like this, then:
(Note: the penultimate line of code has been split so it fits across the page you're currently viewing.)

import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
import java.util.*;


public class BookStoreServlet extends HttpServlet 
{

/** This method is the first method executed when the servlet loads.
 * @param HttpServletRequest
 * @param HttpServletResponse
 * @return void
 */
 
public synchronized void init (ServletConfig config)

{ 
        super.init();

}               		
	
/** doGet method
 */
		 
public void doGet (HttpServletRequest req, HttpServletResponse res)
	throws ServletException, IOException 	
{
	// Send out first page:	
	res.setContentType("text/html");
	PrintWriter out = res.getWriter();	

	out.println("<HTML<");
	out.println("<BODY>");
	out.println("<CENTER>");
	out.println("<H1>Welcome to WholeLottaBooks.com!</H1>");
	out.println("Would you like to begin shopping?");
	out.println("<FORM ACTION='/servlet/BookStoreServlet' METHOD='POST'>");
	out.println("<INPUT TYPE='submit' VALUE='You bet!'>");
	out.println("</FORM>");
	out.println("</CENTER>");
	out.println("</BODY>");
	out.println("</HTML>");
	
}

/**
 * doPost method
 */

public void doPost (HttpServletRequest req, HttpServletResponse res)
	throws ServletException, IOException 	
{

	StringBuffer HTML = new StringBuffer();
	res.setContentType("text/html");
	PrintWriter out = res.getWriter();
	ShoppingCart sc;
	HttpSession session = req.getSession(true);
	
	if (session.getValue("Cart") == null)
		// User has no shopping cart, create one.
	{
		sc= new ShoppingCart();
		session.putValue("Cart",sc);
		int acct = new Random().nextInt();
		if (acct < 0)
			acct = acct * -1;
		// Cast to type of ShoppingCart, since HttpSession only deals in Object.
		((ShoppingCart)session.getValue("Cart")).setAccountNum(acct);
	}
		out.println("Your account number is " + ((ShoppingCart)se
                                      ssion.getValue("Cart")).getAccountNum());		
	}	
	
	}	//end of servlet		

This will put out a welcome page that asks the user whether they want to begin shopping. If they click the "You bet" button, the doPost method executes. The doPost will check to see if they have a shopping cart. If not, one is created, and their account number is assigned to it. Again, the details of assigning account numbers, making sure that concurrency is taken care of - all of that is necessary to implementing such a system, but is outside the scope of this discussion.

After we have a shopping cart, the user will begin adding items to the cart. How this is handled is up to you as a developer. Whatever method you choose, however, you will probably be passing these to your servlet through the HttpRequest object.

We expand the above code to process these parameters as follows:

 

if (session.getValue("Cart") == null)
		// User has no shopping cart, create one.
	{
		sc= new ShoppingCart();
		session.putValue("Cart",sc);
		int acct = new Random().nextInt();
		if (acct < 0)
			acct = acct * -1;
		// Cast to type of ShoppingCart, since HttpSession only deals in Object.
		((ShoppingCart)session.getValue("Cart")).setAccountNum(acct);
	}
	else  // Shopping cart exists, see if user wants to add itesms
	{
	
		Enumeration enum = req.getParameterNames();
		while (enum.hasMoreElements())
		{
			
			String parmName = (String)enum.nextElement();
			if (parmName.equals("stockNum"))
			{
			String parmValue = req.getParameter(parmName);
			((ShoppingCart)session.getValue("Cart")).addItem(parmValue);
			}
		}						
	}

We have added an else branch to the if statement to handle the case where the user already has a shopping cart, and wants to add items to the cart. GetParameterNames will return an Enumeration of the paramter names coming in the the HttpRequest object. If the parameter name is "stockNum" we know the user wants to add an item to their cart. We are not concerned with book titles or publishers, as everything will be keyed off the stock number. We then extract the parameter value, and add it to the Shopping Cart by calling the addItem method. Note that to do this we first need to get a reference to the ShoppingCart object by calling getValue on the session object, and casting it to the appropriate type (ShoppingCart).

Using this mechanism, you can add any kind of object to your session object. This provides you as a developer with a lot of flexibility to implement your servlet in any way you choose.

A word about the safety of the doPost method of your servlet. Servlets are capable of handling more than one request at a time. However, there could be ramifications for the user based on the threading model that you choose to implement. The default model is to allow multiple threads to access the servlet. There is only one instance of the servlet running in the Web server, which serves all users. However, each user has his own copy of the doPost method, and everything goes swimmingly. The caveat to this is if you are accessing shared resources from the doPost method, you will need to account for the safety of that. For example, if you have declared a variable that is a class level or static variable, and the access to it needs to be atomic, you will need to synchronize the code that accesses the resource. The best way around this is to simply avoid using class-level or static variables that need to have atomic access. The other threading model the servlet API supports is the SingleThreadModel. Under this model, the Web server maintains a pool of servlet instances, rather than just one servlet. Each user gets a different instance of the servlet. The only thing needed for implementing this model is to have the servlet implement the interface javax.servlet.SingleThreadModel.

All this interface does is act as a marker - there is nothing for you as a developer to implement. The servlet engine will maintain a pool of servlet instances, and serve up a free instance to a user of your site. This method will still not guarantee that shared resources such as static class variables or classes outside the scope of the servlet will be safely accessed. Again, you will need to synchronize access to these resources to ensure thread safety.

My preference is for the default threading model. You simply need to be careful about how you implement your servlet. This is not too difficult however. Just stay away from class variables and synchronize access to shared resources and you will be fine.

Let's return to our WholeLottaBooks.com servlet. Another feature of the HttpSession object which can work in your favor is that the session relates to the server, not the servlet. For example, if WholeLottaBooks becomes wildly successful, and they decide to branch out into selling music, a separate servlet to handle music purchases could access the same shopping cart as the books servlet! This is very convenient to your users. Regardless of what they are purchasing, it all goes into the same cart.

This brief discussion of the HttpSession object gives you an idea of the flexibility and power available to you as a servlet developer. Like most coding exercises however, if you don't use it, you lose it. So experiment with a small servlet of your own and see for yourself what the session can do for you.

 

This article originally appeared on WebDevelopersJournal.com.

Sitemap | Contact Us