|
Introduction | Servlets & HTTP | Life-Cycle | Sessions | Summary | Examples Sessions: HTTP Session Tracking | Cookies | Servlet Sessions | Sessions At Work | ||
Servlet SessionWe have seen the most common and well-used techniques for maintaining HTTP sessions over the web, namely, persistent cookies, URL rewriting, hidden form fields and user authorisation. There are also proprietary session tracking strategies that are vendor dependent that persist state to disk and/or a database. There are no clear winners, with pros and cons to each approach. The servlet developer does not want to deal with each and every one of these session tracking techniques in their web applications. Instead, there should be one API that chooses the most approipriate HTTP session technique based upon its client's and server's capabilities. The API should shield developers, where possible, from details such as whether the browser has cookies enabled or if the server supports URL rewriting. This is the aim of the Servlet Session Tracking API. Maintaining HTTP sessions is made easy with the Servlet Session Tracking which has one API with many possible implementations (cookies, URL rewriting). What is a Session?A session is a collection of HTTP requests, over a period of time, between a client and a web server. When a session is created, its lifetime is also set, the default being three minutes. Upon expiration, the session is destroyed and its resources returned back to the servlet engine. Sessions can be prematurely destroyed by the developer. In this section we look into the life-cycle of a session, focusing on how sessions are created and destroyed. In the next section we delve deeper into how sessions are used during their lifetime. Creating a Session
Creating a session couldn't be simpler. Off the HTTPServletRequest object, req, call: HttpSession theSession = req.getSession(true); That will get the current HTTPSession for the client, or create one if it doesn't already exist. If the argument value to getSession() was false, no session will be created if one doesn't already exist. The following CreateSession servlet illustrates how to create a session and glean some important session statistics such as creation time, last access time, the maximum lifetime of a session in seconds and most importantly, the session id that is used to uniquely identify a client's session. package com.ack.servlets; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpSession; import java.io.IOException; import java.io.PrintWriter; import java.util.Date; public class CreateSession extends HttpServlet { private int fCounter; public void doGet(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException { res.setContentType("text/html"); PrintWriter pw = res.getWriter(); pw.println("<BODY><HTML>"); // get session, can create it if one doesn't already exist HttpSession theSession = req.getSession(true); // check if session is newly created if( theSession.isNew() ) pw.println("</pre><p>Session: isNew</p>"); else pw.println("<p>Session: Already Exists</p>"); // get session id and it's max lifetime in seconds pw.println("<br>Session Id: " + theSession.getId() ); pw.println("<br>Session Max Inactive Time (seconds): " + theSession.getMaxInactiveInterval() ); // get creation time long dateTimes = theSession.getCreationTime(); pw.println("<br>Session Creation Time: " + new Date(dateTimes)); // get last access time, negative if never been accessed dateTimes = theSession.getLastAccessedTime(); if( dateTimes < 0 ) pw.println("<br>Session Last Access Time: Never Been Access Befored"); else pw.println("<br>Session Last Access Time: " + new Date(dateTimes)); synchronized(this) { pw.println("<p><p><p> Number of accesses: " + (++fCounter) ); } pw.println("</BODY></HTML>"); } } This servlet is available in the examples section. When you run it, try disabling cookie support in your browser and accessing the servlet again. You will notice that the session is always New. This is because a new session is created by the server that the client has not handshaked on. A cookie-based session will not be established unless the client handshakes with the server. If cookie support is disabled, the client will never handshake with the server, and the session will always be new. There are also a few other methods that prove useful to find out whether a session was created using a cookie or is based on URL rewriting. For example, the HTTPRequestServlet object req, can be used to find out: if( req.isRequestSessionIdFromCookie() ) pw.println("<P>Session created from cookie..."); else( req.isRequestSessionIdFromURL() ) pw.println("<P>Session cames as part of the URL..."); if( req.isRequestSessionIdValid() ) pw.println("<P>Session id in request is okay, get it with getSession()"); else pw.println("<P>Session id is invalid, getSession() will create a new session"); Note that session implementations supported by the Session Tracking API are cookies and URL rewriting. If you want to implement sessions using hidden fields or user authorization, then this is something you going to have to do outside of the Session Tracking API. Destroying a sessionA session is destroyed automatically by reaching its expiration time, or manually, by the invaliation() method on the session. When a session is created it has an associated expiration time, after which the session will be put into an invalid state by the servlet engine. Once a session becomes invalid, its resources cannot be accessed by the developer. The resources in an invalid session are first released and then the session object becomes eligible for garbage collection. It is the responsibility of the servlet engine to monitor sessions and to invalidate them when their time comes. However, a web application can force a session into the invalid state. It does this by calling the invalidate() method on the HttpSession object. In the following code example, we display the session id for the current session on each client access. After every five accesses, the servlet invalidates (destroys) the session and displays how long the session was active for. It also displays the time remaning before it would have been invalidated by the servlet engine. package com.ack.servlets; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpSession; import java.io.IOException; import java.io.PrintWriter; public class DestroySession extends HttpServlet { private int fCounter; public void doGet(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException { res.setContentType("text/html"); PrintWriter pw = res.getWriter(); pw.println("<HTML><BODY>"); synchronized(this) { // get or create current session HttpSession theSession = req.getSession(true); // print out the session id pw.println("<BR>Session Id: " + theSession.getId()); pw.println("<BR>Page Accessed: " + (++fCounter) ); pw.println( (fCounter == 1) ? " time " : " times " ); // and destroy the session every five accessed if( (fCounter % 5) == 0 ) { // calculate how long session was active and how much // time it had left before it automatically expired long startTime = theSession.getCreationTime(); long endTime = theSession.getLastAccessedTime(); long maxActiveTime = theSession.getMaxInactiveInterval(); double timeActive = (endTime - startTime)/1000.0; // display times pw.println("<BR>Session was active for (secs): " + timeActive/1000.0); pw.println("<BR> Session Time remaining (secs): " + (maxActiveTime - timeActive) ); theSession.invalidate(); } } pw.println("</BODY></HTML>"); pw.close(); } } Note that all methods off the HttpSession can throw an IllegalStateException. This exception is used to report attempts to access session resources after a session has been invalidated. All servlet web applications should defensively code for situations where they have handles to invalid sessions. Getting hold of all sessionsIn the 2.0 version of the Servlet API, you could get hold of a HttpSessionContext object by calling getSessionContext() off an HttpSession. For example: HttpSessionContext sessionContext = theSession.getSessionContext(); HttpSessionContext holds the collection of active sessions. Using the sessionContext, the servlet developer can get an Enumeration of all session ids in the servlet engine and use this to get a handle on a specific session object. Hence to display the creation times for all sessions within the servlet engine, we could do the following: Enumeration allSessionIds = sessionContext.getIds(); while( allSessionIds.hasMoreElements() ) { String sessionId = (String)allSessionIds.nextElement(); HttpSession aSession = sessionContext.getSession(sessionId); out.println("<P>Session Id: " + sessionId ); out.println("<BR>Creation Time: " + aSession.getCreationTime() ); } Although HttpSessionContext seems like a useful class for getting easy access to all client sessions, it appears Sun thought access to such private data was too easy. In version 2.1 of the Servlet API the HttpSessionContext class was deprecated for security reasons by Sun, with no plans for a replacement. In short, steer clear of HttpSessionContext! | |||
(c) Zameer's Online Education 2006 |