SCWCD : Session Management
Write servlet code to store objects into a session object and retrieve objects from
a session object.
Sessions are represented by an HttpSession object. You access a
session by calling the HttpServletRequest.getSession() or
HttpServletRequest.getSession(boolean) method of a request object.
This method returns the current session associated with this request, or, if the
request does not have a session, it creates one (unless boolean argument is
false).
You can associate object-valued attributes with a session by name. Such attributes are
accessible by any Web component that belongs to the same Web context and is handling a
request that is part of the same session.
For example, you can save shopping cart as a session attribute. This allows the
shopping cart to be saved between requests and also allows cooperating servlets to
access the cart. Some servlet adds items to the cart; another servlet displays, deletes
items from, and clears the cart; and next servlet retrieves the total cost of the items
in the cart.
public class CashierServlet extends HttpServlet {
public void doGet (HttpServletRequest req, HttpServletResponse res)
throws ServletException, IOException {
// Get the user's session and shopping cart
HttpSession session = request.getSession();
ShoppingCart cart = (ShoppingCart) session.getAttribute("cart");
...
// Determine the total price of the user's books
double total = cart.getTotal();
...
}
}
package javax.servlet.http;
public interface HttpSession {
public java.lang.Object getAttribute(java.lang.String name);
public java.util.Enumeration getAttributeNames();
public void removeAttribute(java.lang.String name);
public void setAttribute(java.lang.String name, java.lang.Object value);
}
Given a scenario describe the APIs used to access the session object, explain when the
session object was created, and describe the mechanisms used to destroy the session
object, and when it was destroyed.
A session is considered 'new' when it is only a prospective session and has not been
established. Because HTTP is a request-response based protocol, an HTTP session
is considered to be new until a client 'joins' it. A client joins a session when session
tracking information has been returned to the server indicating that a session has
been established. Until the client joins a session, it cannot be assumed that the next
request from the client will be recognized as part of a session.
The session is considered to be 'new' if either of the following is true:
These conditions define the situation where the servlet container has no
mechanism by which to associate a request with a previous request.
To obtain a session, use the getSession() or
getSession(boolean) method of the
javax.servlet.http.HttpServletRequest object. When you first obtain
the HttpSession object, the one of three ways used to establish tracking
of the session: cookies, URL rewriting, or Secure Sockets Layer (SSL) information. Assume
the servlet container uses cookies. In such a case the servlet container creates a unique
session ID and typically
sends it back to the browser as a cookie. Each subsequent request from this user (at the
same browser) passes the cookie containing the session ID, and the servlet container
uses this ID to find the user's existing HttpSession object.
If argument in getSession(boolean) method is set to
true, the HttpSession object is created if it
does not already exist (the same as call of getSession() method).
If argument in getSession(boolean) method is set to
false, the HttpSession object is NOT created if it
does not already exist and method returns null.
You can end a session:
Automatically by servlet container if a session is inactive for a specified
time. The administrators provide a way to specify the amount of time after which
to invalidate a session.
By coding the servlet to call the HttpSession.invalidate()
method on the session object.
In the HTTP protocol, there is no explicit termination signal when a client is no
longer active. This means that the only mechanism that can be used to indicate when
a client is no longer active is a timeout period.
The default timeout period for sessions is defined by the servlet container and
can be obtained via the int HttpSession.getMaxInactiveInterval() (sec.)
method of the
HttpSession interface. This timeout can be changed by the Developer
using the HttpSession.setMaxInactiveInterval(int) (sec.) method of the
HttpSession interface. The timeout periods used by these methods are
defined in SECONDS. By definition, if the timeout period for a session is set to -1
(or ANY NEGATIVE), the session will never expire. The session invalidation will not
take effect until all servlets
using that session have exited the service method. Once the session invalidation is
initiated, a new request must not be able to see that session.
package javax.servlet.http;
public interface HttpSession {
public int getMaxInactiveInterval();
public void setMaxInactiveInterval(int interval);
public void invalidate();
public boolean isNew();
}
Another way to configure session timeout (for all sessions within one web-application) is to use
deployment descriptor (web.xml). The session-timeout
element defines the default
session timeout interval for all sessions created in this web application. The specified timeout
must be expressed in a whole number of MINUTES. If the timeout is 0 or less, the container
ensures the default behaviour of sessions is NEVER to time out. If this element is not
specified, the container must set its default timeout period.
<web-app>
...
<session-config>
<session-timeout>30</session-timeout> <!-- 30 minutes -->
</session-config>
</web-app>
Using session listeners, write code to respond to an event when an object is added to a
session, and write code to respond to an event when a session object migrates from one VM
to another.
Object is added to session. Listener notification.
package listeners;
import javax.servlet.http.HttpSessionAttributeListener;
import javax.servlet.http.HttpSessionBindingEvent;
public final class SessionListener implements HttpSessionAttributeListener {
public void attributeAdded(HttpSessionBindingEvent event) {
System.out.println("attributeAdded");
System.out.println(event.getSession().getId());
System.out.println(event.getName() + "', '" + event.getValue());
}
public void attributeRemoved(HttpSessionBindingEvent event) {
System.out.println("attributeRemoved");
System.out.println(event.getSession().getId());
System.out.println(event.getName() + "', '" + event.getValue());
}
public void attributeReplaced(HttpSessionBindingEvent event) {
System.out.println("attributeReplaced");
System.out.println(event.getSession().getId());
System.out.println(event.getName() + "', '" + event.getValue());
}
}
<web-app>
...
<listener>
<listener-class>listeners.SessionListener</listener-class>
</listener>
</web-app>
Object is added to session. Object notification.
package beans;
import javax.servlet.http.HttpSessionBindingListener;
import javax.servlet.http.HttpSessionBindingEvent;
public class CounterBean implements HttpSessionBindingListener {
private int count = 1;
public int getValue() {
return count;
}
public void increment() {
count++;
}
public void valueBound(HttpSessionBindingEvent event) {
System.out.println("attributeBounded");
System.out.println(event.getSession().getId());
System.out.println(event.getName() + "', '" + event.getValue());
}
public void valueUnbound(HttpSessionBindingEvent event) {
System.out.println("attributeUnbounded");
System.out.println(event.getSession().getId());
System.out.println(event.getName() + "', '" + event.getValue());
}
}
Note, you don't need to (and must not) configure HttpSessionBindingListener
in the deployment descriptor, just make a class implementing this interface.
Object migrates from one VM to another. Object notification.
package beans;
import javax.servlet.http.HttpSessionActivationListener;
import javax.servlet.http.HttpSessionEvent;
public class CounterBean implements HttpSessionActivationListener {
private int count = 1;
public int getValue() {
return count;
}
public void increment() {
count++;
}
public void sessionWillPassivate(HttpSessionEvent se) {
System.out.println("session is about to be passivated");
// save counter's value to persistent storage
....
}
public void sessionDidActivate(HttpSessionEvent se) {
System.out.println("session has just been activated");
// retrieve counter's value from persistent storage
....
}
}
Note, you don't need to (and must not) configure
HttpSessionActivationListener
in the deployment descriptor, just make a class implementing this interface.
Given a scenario, describe which session management mechanism the Web container could employ,
how cookies might be used to manage sessions, how URL rewriting might be used to manage
sessions, and write servlet code to perform URL rewriting.
The following approaches are using for tracking a user's sessions:
Cookies
Session tracking through HTTP cookies is the most used session tracking
mechanism and is required to be supported by all servlet containers.
The container sends a cookie to the client. The client will then return the
cookie on each subsequent request to the server, unambiguously associating the
request with a session. The name of the session tracking cookie must be
'JSESSIONID' (uppercase !).
Set-Cookie: JSESSIONID=49EBBB19A1B2F8D10EE075F6F14CB8C9; Path=/
SSL Sessions
Secure Sockets Layer, the encryption technology used in the HTTPS protocol, has a
built-in mechanism allowing multiple requests from a client to be unambiguously
identified as being part of a session. A servlet container can easily use this data
to define a session.
URL Rewriting
URL rewriting is the lowest common denominator of session tracking. When a
client will not accept a cookie, URL rewriting may be used by the server as the basis
for session tracking. URL rewriting involves adding data, a session ID, to the URL
path that is interpreted by the container to associate the request with a session.
The session ID must be encoded as a path parameter in the URL string. The
name of the parameter must be 'jsessionid' (lowercase !).
Here is an example of a URL containing encoded path information:
http://www.myserver.com/catalog/index.html;jsessionid=1234
package javax.servlet.http;
public interface HttpServletRequest extends javax.servlet.ServletRequest {
...
public boolean isRequestedSessionIdFromCookie();
public boolean isRequestedSessionIdFromURL();
public boolean isRequestedSessionIdValid();
}
There are 2 methods in the HttpServletResponse for URL rewriting:
encodeURL(String)
Encodes the specified URL by including the session ID in it, or, if encoding is
not needed, returns the URL unchanged. The implementation of this method
includes the logic to determine whether the session ID needs to be encoded in
the URL. For example, if the browser supports cookies, or session tracking is
turned off, URL encoding is unnecessary.
For robust session tracking, all URLs emitted by a servlet should be run
through this method. Otherwise, URL rewriting cannot be used with browsers
which do not support cookies.
encodeRedirectURL(String)
Encodes the specified URL for use in the sendRedirect
method or, if encoding is not needed, returns the URL unchanged. The
implementation of this method includes the logic to determine whether the
session ID needs to be encoded in the URL. Because the rules for making this
determination can differ from those used to decide whether to encode a normal
link, this method is separated from the encodeURL method.
All URLs sent to the HttpServletResponse.sendRedirect
method should be run through this method. Otherwise, URL rewriting cannot be
used with browsers which do not support cookies.
package javax.servlet.http;
public interface HttpServletResponse extends javax.servlet.ServletResponse {
public java.lang.String encodeURL(java.lang.String url);
public java.lang.String encodeRedirectURL(java.lang.String url)
}
public void doGet(HttpServletRequest req, HttpServletResponse res)
throws IOException, ServletException {
response.setContentType("text/html");
PrintWriter out = response.getWriter();
...
out.print("<form action='");
out.print(response.encodeURL("SessionExample"));
out.print("' ");
out.println("method='post'>");
}
|