Cookies and Servlets
·
HTTP
is a “sessionless” protocol, so you cannot tell from
one server hit to another if you’ve got the same person repeatedly querying
your site, or if it is a completely different person.
·
A
great deal of effort has gone into mechanisms that will allow Web developers to
track sessions. Companies could not do e-commerce without keeping track of a
client and the items they have put into their shopping cart, for example.
·
A
cookie is nothing more than a small piece of information sent by a Web server
to a browser. The browser stores the cookie on the local disk, and whenever
another call is made to the URL that the cookie is associated with, the cookie
is quietly sent along with the call, thus providing the desired information
back to that server (generally, providing some way that the server can be told
that it’s you calling).
·
Clients
can, however, turn off the browser’s ability to accept cookies. If your site
must track a client who has turned off cookies, then another method of session
tracking (URL rewriting or hidden form fields) must be incorporated by hand,
since the session tracking capabilities built into the servlet
API are designed around cookies
The Cookie class
·
The
servlet API (version 2.0 and up) provides the Cookie
class. This class incorporates all the HTTP header details and allows the
setting of various cookie attributes.
·
Using
the cookie is simply a matter of adding it to the response object. The
constructor takes a cookie name as the first argument and a value as the second.
Cookies are added to the response object before you send any content.
Cookie oreo = new Cookie("TIJava", "2000");
res.addCookie(oreocookie);
·
Cookies
are recovered by calling the getCookies( )
method of the HttpServletRequest object, which
returns an array of cookie objects
· Cookie[] cookies = req.getCookies();
·
You
can then call getValue( ) for each cookie, to produce a String
containing the cookie contents. In the above example, getValue("TIJava") will produce a String containing
“2000.”
·
A
session is one or more page requests by a client to a Web site during a defined
period of time. If you buy groceries online, for example, you want a session to
be confined to the period from when you first add an item to “my shopping cart”
to the point where you check out. Each item you add to the shopping cart will
result in a new HTTP connection, which has no knowledge of previous connections
or items in the shopping cart. To compensate for this lack of information, the
mechanics supplied by the cookie specification allow your servlet
to perform session tracking.
·
A
servlet Session object lives on the server
side of the communication channel; its goal is to capture useful data about
this client as the client moves through and interacts with your Web site. This
data may be pertinent for the present session, such as items in the shopping
cart, or it may be data such as authentication information that was entered
when the client first entered your Web site, and which should not have to be
reentered during a particular set of transactions.
·
The
Session class of the servlet API uses the Cookie
class to do its work. However, all the Session object needs is some kind
of unique identifier stored on the client and passed to the server.
·
Web
sites may also use the other types of session tracking but these mechanisms
will be more difficult to implement as they are not encapsulated into the servlet API (that is, you must write them by hand to deal
with the situation when the client has disabled cookies).
Here’s an example that
implements session tracking with the servlet API:
//: SessionPeek.java
// Using the HttpSession class.
import java.io.*;
import java.util.*;
import javax.servlet.*;
import javax.servlet.http.*;
public class SessionPeek extends HttpServlet {
public void service(HttpServletRequest req,
HttpServletResponse res)
throws ServletException, IOException {
// Retrieve Session Object before any
// output is sent to the client.
HttpSession session = req.getSession();
res.setContentType("text/html");
PrintWriter out = res.getWriter();
out.println("<HEAD><TITLE> SessionPeek ");
out.println(" </TITLE></HEAD><BODY>");
out.println("<h1> SessionPeek </h1>");
// A simple hit counter for this session.
Integer ival = (Integer)
session.getAttribute("sesspeek.cntr");
if(ival==null)
ival = new Integer(1);
else
ival = new Integer(ival.intValue() + 1);
session.setAttribute("sesspeek.cntr", ival);
out.println("You have hit this page <b>"
+ ival + "</b> times.<p>");
out.println("<h2>");
out.println("Saved Session Data </h2>");
// Loop through all data in the session:
Enumeration sesNames =
session.getAttributeNames();
while(sesNames.hasMoreElements()) {
String name =
sesNames.nextElement().toString();
Object value = session.getAttribute(name);
out.println(name + " = " + value + "<br>");
}
out.println("<h3> Session Statistics </h3>");
out.println("Session ID: "
+ session.getId() + "<br>");
out.println("New Session: " + session.isNew()
+ "<br>");
out.println("Creation Time: "
+ session.getCreationTime());
out.println("<I>(" +
new Date(session.getCreationTime())
+ ")</I><br>");
out.println("Last Accessed Time: " +
session.getLastAccessedTime());
out.println("<I>(" +
new Date(session.getLastAccessedTime())
+ ")</I><br>");
out.println("Session Inactive Interval: "
+ session.getMaxInactiveInterval());
out.println("Session ID in Request: "
+ req.getRequestedSessionId() + "<br>");
out.println("Is session id from Cookie: "
+ req.isRequestedSessionIdFromCookie()
+ "<br>");
out.println("Is session id from URL: "
+ req.isRequestedSessionIdFromURL()
+ "<br>");
out.println("Is session id valid: "
+ req.isRequestedSessionIdValid()
+ "<br>");
out.println("</BODY>");
out.close();
}
public String getServletInfo() {
return "A session tracking servlet";
}
} ///:~
·
Inside
the service( ) method, getSession( ) is called for the request
object, which returns the Session object associated with this request.
The Session object does not travel across the network, but instead it
lives on the server and is associated with a client and its requests.
·
getSession( ) comes in two versions: no
parameter, as used here, and getSession(boolean). getSession(true) is equivalent to getSession( ).
The only reason for the boolean
is to state whether you want the session object created if it is not found. getSession(true) is the most likely call, hence getSession( ).
· The Session object, if it is not new, will give us details about the client from previous visits. If the Session object is new then the program will start to gather information about this client’s activities on this visit. Capturing this client information is done through the setAttribute( ) and getAttribute( ) methods of the session object.
java.lang.Object getAttribute(java.lang.String)
void setAttribute(java.lang.String name,
java.lang.Object value)
·
The
Session object uses a simple name-value pairing for loading information.
The name is a String, and the value can be any object derived from java.lang.Object.
·
SessionPeek keeps track of how many times the
client has been back during this session. This is done with an Integer
object named sesspeek.cntr. If the name is not
found an Integer is created with value of one, otherwise an Integer
is created with the incremented value of the previously held Integer.
The new Integer is placed into the Session object.
·
If
you use same key in a setAttribute( ) call, then the new object overwrites
the old one. The incremented counter is used to display the number of times
that the client has visited during this session.
·
getAttributeNames( ) is related to getAttribute( )
and setAttribute( ); it returns an
enumeration of the names of the objects that are bound to the Session
object. A while loop in SessionPeek
shows this method in action.
·
Session
objects hang around depending on the servlet
container you are using; they usually default to 30 minutes (1800 seconds),
which is what you should see from the ServletPeek
call to getMaxInactiveInterval( ).
Tests seem to produce mixed results between servlet
containers. Sometimes the Session object can hang around overnight, but never
in less than the time specified by the inactive interval. You can try this by
setting the inactive interval with setMaxInactiveInterval( ) to 5 seconds and see if your Session object hangs around or if it is cleaned up at the appropriate time.
This may be an attribute you will want to investigate while choosing a servlet container.