JavaServer

Session Tracking


Contents / New Features / Administrator Docs / Developer Docs / Index

Session Tracking is a mechanism for building a sophisticated, stateful model on top of the web's stateless protocol. With Session Tracking, session state is maintained by the server. The server creates new sessions, invalidates old sessions, and maintains policies of session persistence.

The following topics describe sessions and the different capabilities of the Session Tracker:

As a developer, you should read all sections, especially Using Session Tracking from a Servlet where example code is given. As an administrator, refer to Customizing Session Tracking to see how Session Tracking can be tuned.

Note: When the JavaTM Web ServerTM is installed, it creates an empty sessionSwap directory. If there are too many sessions to be held in physical memory, they are swapped out to that directory to be held on disk. This is invisible to the user but may be a consideration for server performance tuning.

About Session Tracking

Session Tracking is a flexible, lightweight mechanism that enables stateful programming on the web. It has a general implementation that serves as a basis for more sophisticated state models, such as persistent user profiles or multi-user sessions.

A session is a series of requests from the same user that occur during a time-period. This transaction model for sessions has many benefits over the single-hit model. It can maintain state and user identity across multiple page requests. It can also construct a complex overview of user behavior that goes beyond reporting of user hits.

Server-side Session Objects and Users

Session Tracking gives servlets and other server-side applications the ability to keep state about a user as the user moves through the site. Server-side applications can use this facility to create more stateful user experiences and track who's doing what on the site.

Java Web Server maintains user state by creating a Session object for each user on the site. These Session objects are stored and maintained on the server. When a user first makes a request to a site, the user is assigned a new Session object and a unique session ID. The session ID matches the user with the Session object in subsequent requests. The Session object is then passed as part of the request to the servlets that handle the request. Servlets can add information to Session objects or read information from them.

Session Endurance

After the user has been idle for more than a certain period of time (30 minutes by default), the user's session becomes "invalid", and the corresponding Session object is destroyed.

A session is a set of requests originating from the same browser, going to the same server, bounded by a period of time. Loosely speaking, a session corresponds to a single sitting of a single anonymous user. Anonymous, because no explicit login or authentication is required to participate in session tracking.

Using Session Tracking from a Servlet

The following example uses the doGet method from a servlet that prints the number of times users access a particular servlet.

public void doGet (HttpServletRequest request, HttpServletResponse response)
	throws ServletException, IOException
    {

      // Obtain the Session object
        HttpSession session = request.getSession (true);

      // Get the session data value
        Integer ival = (Integer) 
            session.getValue ("sessiontest.counter");
        if (ival == null) ival = new Integer (1);
        else ival = new Integer (ival.intValue () + 1);
        session.putValue ("sessiontest.counter", ival);

     // Output the page
	response.setContentType("text/html");
	ServletOutputStream out = response.getOutputStream();
	out.println("<html>");
	out.println("<head><title>Session Tracking Test</title></head>");
	out.println("<body>");
	out.println("<h1>Session Tracking Test</h1>");
        out.println ("You have hit this page " + ival + " times");
	out.println("</body></html>");
    }

The first part of the doGet method associates the Session object with the user making the request. The second part of the method gets an integer data value from the Session object and increments it. The third part outputs the page, including the current value of the counter.

When run, this servlet should output the value of the counter that increments every time you reload the page. Note: you must obtain the session object before you actually write any data to the servlet's output stream. This will gaurentee that the session tracking headers will be sent with the response.

Storing and Retrieving Data from the Session Object

You obtain the session data value with the following:

     Integer ival = (Integer) 
         session.getValue ("sessiontest.counter");
     if (ival == null) ival = new Integer (1);
     else ival = new Integer (ival.intValue () + 1);
     session.putValue ("sessiontest.counter", ival);  

The Session object has methods similar to java.util.Dictionary for adding, retrieving, and removing arbitrary Java objects. In this example, an Integer object is read from the Session, incremented, then written back to the Session.

Any name, such as sessiontest.counter, may be used to identify values in the Session. When choosing names, remember that the Session object is shared among any servlets that the user might access. Servlets may access or overwrite each other's values from the Session. Thus, it is good practice to adopt a convention for organizing the namespace to avoid collisions between servlets, such as:

servletname.name

Session Invalidation

Sessions can be invalidated automatically or manually. Session objects that have no page requests for a period of time (30 minutes by default) are automatically invalidated by the Session Tracker sessionInvalidationTime parameter. When a Session is invalidated, the Session object and its contained data values are removed from the system.

After invalidation, if the user attempts another request, the Session Tracker detects that the user's Session was invalidated and creates a new Session. However, data from the user's previous Session will be lost.

Session objects can be invalidated manually by calling Session.invalidate(). This will cause the Session to be invalidated immediately, removing it and its data values from the system.

Note: To see how to change the default session invalidation time, refer to Customizing Session Tracking.

Handling Non-cookie Browsers (URL Rewriting)

The Session Tracker uses a session ID to match users with Session objects on the server side. The session ID is a String that is sent as a cookie to the browser when the user first accesses the server. On subsequent requests, the browser sends the session ID back as a cookie, and the server uses this cookie to find the Session associated with that request.

There are situations, however, where cookies will not work. Some browsers, for example, do not support cookies. Other browsers allow the user to disable cookie support. In such cases, the Session Tracker must resort to a second method, URL rewriting, to track the user's session.

URL rewriting involves finding all links that will be written back to the browser, and rewriting them to include the session ID. For example, a link that looks like this:

   <a href="/store/catalog"> 

might be rewritten to look like this:

   <a href="/store/catalog;$sessionid$DA32242SSGE2"> 

If the user clicks on the link, the rewritten form of the URL will be sent to the server. The server's Session Tracker will be able to recognize the ;$sessionid$DA32242SSGE2 and extract it as the session ID. This is then used to obtain the proper Session object.

Implementing this requires some reworking by the servlet developer. Instead of writing URLs straight to the output stream, the servlet should run the URLs through a special method before sending them to the output stream. For example, a servlet that used to do this:

    out.println("<a href=\"/store/catalog\">catalog</a>");  

should now do this:

    out.print ("<a href=\"");
    out.print (response.encodeUrl ("/store/catalog"));
    out.println ("\">catalog</a>");  

The encodeUrl method performs two functions:

  1. Determine URL Rewriting: The encodeUrl method determines if the URL needs to be rewritten. Rules for URL Rewriting are somewhat complex, but in general if the server detects that the browser supports cookies, then the URL is not rewritten. The server tracks information indicating whether a particular user's browser supports cookies.
  2. Return URL (modified or the same): If the encodeUrl method determined that the URL needs to be rewritten, then the session ID is inserted into the URL and returned. Otherwise, the URL is returned unmodified.

In addition to URLs sent to the browser, the servlet must also encode URLs that would be used in sendRedirect() calls. For example, a servlet that used to do this:

    response.sendRedirect ("http://myhost/store/catalog");  

should now do this:

    response.sendRedirect 
       (response.encodeRedirectUrl ("http://myhost/store/catalog")); 

The methods encodeUrl and encodeRedirectUrl are distinct because they follow different rules for determining if a URL should be rewritten.

Multiple Servlets
URL conversions are only required if the servlet supports session tracking for browsers that do not support cookies or browsers that reject cookies. The consequences of not doing these conversions is that the user's session will be lost if the user's browser does not support cookies and the user clicks on an un-rewritten URL. Note that this can have consequences on other servlets. If one servlet does not follow these conventions, then a user's session could potentially be lost for all servlets.

Using Session Tracking with the Page Compiler

Page Compilation is a feature of the Java Web Server that allows HTML pages containing Java code to be compiled and run as servlets. Page Compilation also simplifies the task of supporting session tracking. To that end, if URL rewriting is enabled, Page Compilation automatically adds the encodeUrl call around links in the HTML page.

For example, the Access Count Example could be rewritten as a .jhtml file like this:

    <html>
    <head><title>Session Tracking Test</title></head>
    <body>
    <h1>Session Tracking Test</h1>

    <java type=import>javax.servlet.http.*</java>
    
    <java>
          HttpSession session = request.getSession (true);
    
          // Get the session data value
            Integer ival = (Integer) 
                session.getValue ("sessiontest.counter");
            if (ival == null) ival = new Integer (1);
            else ival = new Integer (ival.intValue () + 1);
            session.putValue ("sessiontest.counter", ival);
    </java>
    
    You have hit this page <java type=print>ival</java> times.

    <p>Click here to go to the <a href="/store/catalog">catalog</a>
    
    </body></html>             

This example is similar to the servlet code in the previous example, except that the Java code has been inserted directly into the HTML source. In this example, the /store/catalog link will be detected by the Page Compiler and will automatically call encodeUrl.

Note: The Page Compiler will not detect URLs in the Java code. If the Java code outputs URLs, then the Java code must still run those URLs through encodeUrl.

Additional APIs

In addition to the Session object, there are a few more classes that may interest the servlet developer.

Description Class
HttpSessionContext The HttpSessionContext is the object that contains all existing and valid Sessions. The HttpSessionContext can be obtained by getSessionContext() on the Session object. The HttpSessionContext lets you find other Session objects by their IDs and list the IDs of all valid Sessions.
HttpSessionBindingListener HttpSessionBindingListener is an interface that can be implemented by objects placed into a Session. When the Session is invalidated, its contained values are also removed from the system. Some of these values may be active objects that require cleanup operations to occur when their Session is invalidated. If a value in Session implements HttpSessionBindingListener, then the value is notified when the Session is invalidated, thereby giving the object a chance to perform any necessary cleanup operations.

Session Swapping and Persistence

An internet site must be prepared to support many valid Sessions. A large site, for example, might have hundreds, or even thousands of simultaneously valid Sessions. Because each Session can contain arbitrary data objects placed there by the application servlets, the memory requirements for the entire system can grow prohibitively large.

To alleviate some of these problems, the session tracking system places a limit on the number of Sessions that can exist in memory. This limit is set in the session.maxresidents property. When the number of simultaneous Sessions exceeds this number, the Session Tracker swaps the least recently-used Sessions out to files on disk. Those Sessions are not lost: they will be reloaded into memory if further requests come in for those Sessions. This system allows for more Sessions to remain valid than could exist in memory.

Session invalidation is not affected by session swapping. If a Session goes unused for longer than the normal invalidation time, then the Session is invalidated, whether it is in memory or on disk. Session invalidation is set in the session.invalidationinterval property. See Customizing Session Tracking for more information.

Sessions are written to and read from disk using Java serialization. For this reason, only serializable objects put into the Session will be written to disk. Any objects put into the Session that are not serializable will remain in memory, even if the rest of the Session has been written to disk. This does not affect session tracking operation, but does reduce the memory savings that the Session Tracker gets from swapping a Session to disk. For this reason, the servlet developer should try as hard as possible to put only serializable objects into the Session. Serializable objects are those that implement either java.io.Serializable or java.io.Externalizable.

The session swapping mechanism is also used to implement session persistence, if the session persistence feature is enabled. When the server is shut down, Sessions still in memory are written to the disk as specified in the session.swapdirectory property. When the server starts again, Sessions that were written to disk will once again become valid. This allows the server to be restarted without losing existing Sessions. Only serializable data elements in the Session will survive this shutdown/restart operation.

Note: Session persistence is intended to be used as a means for preserving Sessions across server restarts. It is not meant to be used as a general long-term session persistence mechanism.

Customizing Session Tracking

Session tracking interfaces are in the javax.servlet.http package.

Properties

You can customize properties in the Session Tracker. The properties are kept in in the server.properties files at:
  <server_root>/properties/server/javawebserver/server.properties

where <server_root> is the directory into which you installed the Java Web Server product.

Note: These property settings are applied to all sessions, and cannot be tuned for individual sessions.

Parameter Description Default
session.invalidationinterval Time interval when Java Web Server checks for sessions that have gone unused long enough to be invalidated. Value is an integer, specifying the interval in milliseconds. 10000
(10 seconds)
session.swapinterval Time interval when Java Web Server checks if too many sessions are in memory, causing the overflow of sessions to be swapped to disk. Value is an integer, specifying the interval in milliseconds. 10000
(10 seconds)
session.persistence Boolean value specifying if Java Web Server keeps session data persistent. If true, sessions are swapped to disk when Java Web Server shuts down and are revalidated from disk when it restarts. If false, Java Web Server removes session swap files every time it starts. true
session.swapdirectory Name of directory that the Java Web Server uses to swap out session data. No other data should be kept in this directory. "sessionSwap"
session.maxresidents Number of sessions allowed to remain in memory at once. If the number of sessions exceeds this number, then sessions will be swapped out to disk on a least-recently-used basis to reduce the number of resident sessions. 1024
session.invalidationtime Amount of time a session is allowed to go unused before it is invalidated. Value is specified in milliseconds. 1800000
(30 minutes)
enable.sessions Boolean value specifying whether Session Tracking is active. If false, then the Java Web Server performs no function for extracting or inserting session IDs into requests. true
enable.cookies Boolean value indicating whether Java Web Server uses cookies as a vehicle for carrying session ID. If true, session IDs arriving as cookies are recognized and the Java Web Server tries to use cookies as a means for sending the session ID. true
enable.urlrewriting Boolean value indicating whether Java Web Server uses rewritten URLs as a vehicle to carry the session ID. If true, then session IDs arriving in the URL are recognized, and the Java Web Server rewrites URLs if necessary to send the session ID. false
enable.protocolswitchrewriting Boolean value indicating whether the session ID is added to URLs when the URL dictates a switch from "http" to "https" or vice-versa. false
session.cookie.name Name of the cookie used to carry the session ID, if cookies are in use. "jwssessionid"
session.cookie.comment Comment of the cookie used to carry the session ID, if cookies are in use. "Java Web Server Session Tracking Cookie"
session.cookie.domain If present, this defines the value of the domain field that is sent for session cookies. null
session.cookie.maxage If present, this defines the value of the maximum age of the cookie. -1
session.cookie.path If present, this defines the value of the path field that will be sent for session cookies. "/"
session.cookie.secure If true, then session cookies will include the secure field. false


Top
java-server-feedback@java.sun.com
Copyright © 1998 Sun Microsystems, Inc.
All Rights Reserved.