Java Sessions
— print (last updated: Sep 30, 2009) print

Select font size:
Download the Sessions.zip archive and install this as a Web Application from Existing Sources.

This project illustrates the use of session management within servlets and JSP scripts. The motivation for session objects addresses two issues: maintaining a persistent state between activations, and sharing that state throughout the web application.

Regarding persistence, a Java servlet itself is a persistent object and can maintain other persistent objects as its data members, whereas, in contrast, a JSP script has no obvious access to its data members. Regarding the second issue, there is no obvious solution to sharing a state throughout the web application.

Session Management

Session management is a mechanism for maintaining and sharing the state of variables (called session variables) for every participating program in a web project. These variables are not lost when you go offsite and return. This is one of the key ingredients of a web-based shopping cart used in e-commerce.

The server can maintain a relationship with a browser session by sending and receiving information packets called cookies. A cookie is simply a name/value pair of data which contains other attributes such as the target URL (server name and path) and expiration timestamp.

In session management using cookies, when a browser first contacts a web server, the server sends a cookie called the session id which is then stored in the browser. Normally the session id is some fixed-length "random" sequence of hex digits which the server uses to identify the browser connection and associate some persistent information. When the browser makes a subsequent contact to the server so that the cookie's URL matches the server URL, the cookie is sent to the server.

For servlet and JSP sessions, the cookie's name is JSESSIONID. As mentioned above, it is originally sent from the server to the browser and then subsequently sent back back to the server for all future contacts to that site the current browser session. The default lifetime for a JSESSIONID cookie is the browser session, i.e., as long as the browser remains open.

Servlet Sessions Management

In order to participate in a session, a servlet accesses the session via the call:
HttpSession session = request.getSession();
An object is registered in a session by assigning it a string which is referred to as the object's attribute. The initial operation which takes place is:
<some class> object = /* create it */

session.setAttribute( "attr_name", object );  
This object then becomes available to other servlets which can retrieve it as follows:
<some class> obj = (<some class>) session.getAttribute( "attr_name" );  
In many cases there may be several servlets which use this session object but only the first one to access it (we don't know which it is) must initiate it. In this case, you would use a code segment something like this:
<some class> obj = (<some class>) session.getAttribute( "attr_name" );  

if (obj == null) {  // I'm the first to access the session object
  obj = /* create it */
  session.setAttribute( "attr_name", obj );  
}

Removing session attributes

Another common usage is to force a "logout" of the session by unsetting one or more variables. The most drastic operation is this one in which we must re-establish the session:
session.invalidate();
Often we want to do a less drastic operation, such as
session.removeAttribute("attr_name");   // clear specific session object
Even less drastic operations are possible. For example if the session object is a Map (e.g., a HashMap), then we may simply want to unset one or more of the keys in this map, e.g.:
Map map = (Map) session.getAttribute("attr_name");
map.remove("somekey");

JSP Session Beans

The variable session of type HttpSession is one of the pre-defined "servlet" variables available to JSP scripts, like out, request, response. Nevertheless, the so-called bean objects in JSP scripts helps us simplify the usage of session objects.

Java Beans

A true bean class is one in which the public member functions express the access to some exposed property; they usually follow the typical Java design patterns for member functions:
public <type> get<Property> (); // use "is" instead of "get" for boolean
and/or
public void set<Property> ( <type> x );
By convention, the property is a name beginning with a lower case letter, like "background" and the access functions use a style like this: getBackground, setBackground. The bean objects in JSP use this property-access method, but also allow all other member functions typical of a Java class.

JSP Session Bean

A session bean object is declared in a JSP file with the following entry:
<jsp:useBean id="mb" scope="session" class="mypkg.MyBean"/>
which, the first time executed, has this effect:
mypkg.MyBean mb = new mypkg.MyBean();
session.setAttribute("mb", mb);
A bean object is a session object where the bean's variable name is the same as attribute name. There seem to be a few restrictions on the Java class indicated by "mypkg.MyBean": A bean's get<MyProperty> function can be invoked and dumped into the HTML content by using the tag:
<jsp:getProperty name="mb"  property="myProperty" />
This is equivalent to the following code:
<%= mb.getMyProperty() %>

Sharing bean objects between JSP and servlets

A bean has been created with the jsp:useBean tag can be used in the referenced in a servlet as a session object like this:
mypkg.MyBean mb = (mypkg.MyBean) request.getSession().getAttribute("mb");
Unlike JSP scripts, the variable name mb is optional, so long as you use the attribute name "mb". Likewise we can create the bean object from the servlet:
request.getSession().setAttribute( "mb", <a mypkg.MyBean object> );

Project Files

This simple web project illustrates different possible behaviors for a selection list trying to remember the selected values between invocations. The scripts all include the following navigational JSP file:

nav.jsp
<table class="nav"> <tr> <td><a href=".">home</a></td> <td><a href="form-1.jsp">form 1</a></td> <td><a href="form-2.jsp">form 2</a></td> <td><a href="form-3.jsp">form 3</a></td> </tr> </table>

Data Bean

The selection list uses the following bean Data to deliver the selection choices to example scripts:

util/Data.java
package util; import java.util.*; public class Data { private Map<String,String> choices; public Data() { choices = new LinkedHashMap<String,String>(); String[] choices_data = {"AA", "BB", "CC", "DD", "EE", "FF", "GG" }; for (int i=1; i <= choices_data.length; ++i) { choices.put(Integer.toString(i), choices_data[i-1]); } } public Map<String,String> getChoices() { return choices; } }
This Bean is invoked in each of the JSP scripts by:
<jsp:useBean id="data" scope="session" class="util.Data" />

form-1.jsp

This script holds a stable reentrant form with a textfield and selection list made up of the above choices. The script has two drawbacks:

form-1.jsp
<%@page contentType="text/html" pageEncoding="UTF-8"%> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <%@page import="java.util.*" %> <%@page import="util.Data" %> <jsp:useBean id="data" scope="session" class="util.Data" /> <% String sel1 = request.getParameter("sel1"); String tf1 = request.getParameter("tf1"); tf1 = (tf1==null) ? "" : tf1; Map<String, String> choices = data.getChoices(); %> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>Form 1</title> <link rel="stylesheet" type="text/css" href="css/my.css" /> </head> <body> <%@ include file="nav.jsp" %> <h2>Form 1: stable reentrant</h2> <blockquote class="feedback"> <%= "query parameters:" + "<br />&nbsp;" + " tf1: " + tf1 + "<br />&nbsp;" + " sel1: " + sel1 %> </blockquote> <form action=""> tf1: <input type="text" name="tf1" value="<%=tf1 %>" /><br /><br /> name <b>sel1</b>: <select name="sel1"> <option value="">--- choose one ---</option> <% for (Map.Entry<String, String> entry : choices.entrySet()) { String label = entry.getValue(); String value = entry.getKey(); String isSelected = value.equals(sel1) ? "selected" : ""; %> <option value="<%=value%>" <%=isSelected%> ><%=label%></option> <% } %> </select> <br /><br /> <input type="submit" /> </form> </body> </html>

form-2.jsp

This variation (and the other remaining ones) uses the JSP bean param defined by
<jsp:useBean id="param" scope="session" class="java.util.HashMap" />
as a Map to store parameter values when the parameter is set through invocation of the script. The code to set the session value from the parameter sel1 is expressed like this:
if (request.getParameter("sel2") != null) {
  param.put("sel2", request.getParameter("sel2"));
}
In particular, we want to reset the session value only when there is a new parameter value. Once we've done that, then always take from the session value:
String sel2 = (String) param.get("sel2");
and use this to re-select the selected value in the activation.

form-2.jsp
<%@page contentType="text/html" pageEncoding="UTF-8"%> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <%@page import="java.util.*" %> <%@page import="util.Data" %> <jsp:useBean id="data" scope="session" class="util.Data" /> <jsp:useBean id="param" scope="session" class="java.util.HashMap" /> <% if (request.getParameter("sel2") != null) { param.put("sel2", request.getParameter("sel2")); } String sel2 = (String) param.get("sel2"); if (request.getParameter("tf2") != null) { param.put("tf2", request.getParameter("tf2")); } String tf2 = (String) param.get("tf2"); tf2 = (tf2==null) ? "" : tf2; Map<String, String> choices = data.getChoices(); %> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>Form 2</title> <link rel="stylesheet" type="text/css" href="css/my.css" /> </head> <body> <%@ include file="nav.jsp" %> <h2>Form 2: session saving, stacking</h2> <blockquote class="feedback"> <%= "session values:" + "<br />&nbsp;" + " tf2: " + tf2 + "<br />&nbsp;" + " sel2: " + sel2 %> </blockquote> <form action=""> tf2: <input type="text" name="tf2" value="<%=tf2%>" /><br /><br /> name <b>sel2</b>: <select name="sel2"> <option value="">--- choose one ---</option> <% for (Map.Entry<String, String> entry : choices.entrySet()) { String label = entry.getValue(); String value = entry.getKey(); String isSelected = value.equals(sel2) ? "selected" : ""; %> <option value="<%=value%>" <%=isSelected%> ><%=label%></option> <% } %> </select> <br /><br /> <input type="submit" /> </form> </body> </html>

form-3.jsp

This variation avoids stacking by storing the parameter values as session values and then making a second reentrant activation without parameters. The form calls the servlet

servlet/SessionFromQuery.java
package servlet; import java.io.*; import java.net.*; import javax.servlet.*; import javax.servlet.http.*; import java.util.*; public class SessionFromQuery extends HttpServlet { protected void processRequest( HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType("text/html;charset=UTF-8"); PrintWriter out = response.getWriter(); try { HttpSession session = request.getSession(); // we're assuming that the param session bean has been created Map<String,String> param = (Map<String,String>) session.getAttribute("param"); java.util.Enumeration names = request.getParameterNames(); while (names.hasMoreElements()) { String p = (String) names.nextElement(); param.put(p, request.getParameter(p)); } // go back to from where we came URL referer = new URL(request.getHeader("referer")); response.sendRedirect(referer.getPath()); } finally { out.close(); } } // ... }
which also expresses
response.sendRedirect( SOME-URL );
with the Java way to do redirection. In this case the redirection is back to the calling script computed as the referer (without its query parameters):
URL referer = new URL(request.getHeader("referer"));
response.sendRedirect(referer.getPath());
The final script is essentially the same as the previous one, except that the action is external and the script need not capture the session from the query parameters.

form-3.jsp
<%@page contentType="text/html" pageEncoding="UTF-8"%> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <%@page import="java.util.*" %> <%@page import="util.Data" %> <jsp:useBean id="data" scope="session" class="util.Data" /> <jsp:useBean id="param" scope="session" class="java.util.HashMap" /> <% String sel3 = (String) param.get("sel3"); String tf3 = (String) param.get("tf3"); tf3 = (tf3==null) ? "" : tf3; Map<String, String> choices = data.getChoices(); %> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>Form 3</title> <link rel="stylesheet" type="text/css" href="css/my.css" /> </head> <body> <%@ include file="nav.jsp" %> <h2>Form 3: session saving, no stacking</h2> <blockquote class="feedback"> <%= "session values:" + "<br />&nbsp;" + " tf3: " + tf3 + "<br />&nbsp;" + " sel3: " + sel3 %> </blockquote> <form action="SessionFromQuery"> tf3: <input type="text" name="tf3" value="<%=tf3%>" /><br /><br /> name <b>sel2</b>: <select name="sel3"> <option value="">--- choose one ---</option> <% for (Map.Entry<String, String> entry : choices.entrySet()) { String label = entry.getValue(); String value = entry.getKey(); String isSelected = value.equals(sel3) ? "selected" : ""; %> <option value="<%=value%>" <%=isSelected%> ><%=label%></option> <% } %> </select> <br /><br /> <input type="submit" /> </form> </body> </html>


© Robert M. Kline