Previous     Contents     Index     Next     
iPlanet Application Server Developer's Guide



Chapter 12   Creating and Managing User Sessions


This chapter describes how to create and manage a session that allows users and transaction information to persist between interactions.

This chapter contains the following sections:



Introducing Sessions

The term user session refers to a series of user application interactions that are tracked by the server. Sessions are used for maintaining user specific state, including persistent objects (like handles to EJBs or database result sets) and authenticated user identities, among many interactions. For example, a session could be used to track a validated user login followed by a series of directed activities for a particular user.

The session itself resides in the server. For each request, the client transmits the session ID in a cookie or, if the browser does not allow cookies, the server automatically writes the session ID into the URL.

The iPlanet Application Server supports the servlet standard session interface, called HttpSession for all session activities. This interface enables you to write portable, secure servlets.

Additionally, the iPlanet Application Server provides an additional interface, called HttpSession2, which provides support for a servlet security framework, as well as, sharing sessions between servlets and older iPlanet Application Server components (that is, AppLogics).

Behind the scenes, there are two session styles, distributable and local. The main difference between them is that distributable sessions, as the name implies, can be distributed among multiple servers in a cluster, while local sessions are sticky (that is, bound to an individual server). Sticky load balancing is automatically set for application servlets configured to use the local session model. You determine which session style to use in the application configuration file. For more information about session-related elements in the application configuration file, see Chapter 11 "Packaging for Deployment."


Sessions and Cookies

A cookie is a small collection of information that can be transmitted to a calling browser, which retrieves it on each subsequent call from the browser so that the server can recognize calls from the same client. A cookie is returned with each call to the site that created it, unless it expires.

Sessions are maintained automatically by a session cookie that is sent to the client when the session is first created. The session cookie contains the session ID, which identifies the client to the browser on each successive interaction. If a client does not support or allow cookies, the server rewrites the URLs where the session ID appears in the URLs from that client.


Sessions and URL Rewriting

There are two situations in which the iPlanet Application Server plugin performs implicit URL rewriting:

  • When a response comes back from the iPlanet Application Server; if implicit URL rewriting has been chosen, the plugin rewrites the URLs in the response before passing the response on to the client.

  • When the request given by a client need not be sent to the iPlanet Application Server and can be served on the web server side. Such requests may occur in the middle of a session and the response may need to be rewritten.

This section includes the following topics:


Supported Tags and Attributes

The following tags and attributes are supported for URL rewriting. All of them are case insensitive with respect to the plugin.


Table 12-1    Supported tags and attributes for URL rewriting

Tag or Attribute

Language

Examples

A  

HTML  

<a href="http://www.sun.com"> Sun </a>

<a href="/index.html"> Index </a>  

AREA  

HTML  

<area shape=circle cords="50,50,25" href="http://www.oracle.com/technetwork/indexes/documentation/index.html">  

FORM  

HTML  

 

FRAME  

HTML  

 

GO  

WML  

<go href="/help.wml">  

IMG  

HTML  

 

ONENTERBACKWARD  

WML  

<card onenterbackward="/url"> xyz </card>  

ONENTERFORWARD  

WML  

<card onenterforward="/url"> Hello </card>  

ONPICK  

WML  

<select>

  <option onpick="/a.wml"> A </option>

  <option onpick="/b.wml"> B </option>

</select>  

ONTIMER  

WML  

<card ontimer="/next">  

The following sections provide additional detail about each of the tags.


A

  • The URL mentioned in the href attribute of this tag is rewritten with the cookies.

  • The URL can have a query string.

  • The URL must be enclosed in double or single quotes.

  • The URL must not start with a # character.

  • Cookies are rewritten just after the end of the URI. If the URL already has a query string, it is placed after the cookies.


AREA
  • The URL mentioned in the href attribute of this tag is rewritten.

  • No action is taken for nohref.

  • The URL can have a query string.

  • The URL must be enclosed within double or single quotes.


FORM
  • The cookies are encoded in the form of hidden fields.

  • Both POST and GET are handled.


FRAME
  • The URL pointed to by the SRC attribute of this tag is rewritten.

  • FRAMESET and NOFRAMES are not processed.

  • The URL can have a query string.

  • The URL must be enclosed within double or single quotes.


GO
  • The URL pointed to by the href attribute of this tag is rewritten with the cookies.

  • The URL can have a query string.

  • The URL must be enclosed in double or single quotes.

  • The URL must not start with a # character.

  • Cookies are rewritten just after the end of the URI. If the URL already has a query string, it is placed after the cookies.


IMG
  • The URL pointed to by the SRC attribute of this tag is rewritten.

  • The URL can have a query string.

  • The URL must be enclosed within double or single quotes.


ONENTERBACKWARD
This is not a tag, but an attribute of WML tags such as CARD and ONEVENT.

  • The URL pointed to by ONENTERBACKWARD is rewritten.

  • The URL can have a query string.

  • The URL must be enclosed within double or single quotes.


ONENTERFORWARD
This is not a tag, but an attribute of WML tags such as CARD and ONEVENT.

  • The URL pointed to by ONENTERFORWARD is rewritten.

  • The URL can have a query string.

  • The URL must be enclosed within double or single quotes.


ONPICK
This is not a tag, but an attribute of the WML tag OPTION.

  • The URL pointed to by ONPICK is rewritten.

  • The URL can have a query string.

  • The URL must be enclosed within double or single quotes.


ONTIMER
This is not a tag, but an attribute of WML tags such as CARD and ONEVENT.

  • The URL pointed to by ONTIMER is rewritten.

  • The URL can have a query string.

  • The URL must be enclosed within double or single quotes.


The URL Rewriting Process

The URL rewriting process of the plugin happens in two stages:

For requests that are not sent to the iPlanet Application Server, only response body processing is done.

When the plugin receives a request, it checks if there is a query string. If there is one, the plugin extracts the iPlanet Application Server cookies that were encoded in a previous response. These cookies start with the prefix GXHC_. These cookies are stored in two data structures, referred to here as QueryCookies and FormCookies. In the former, the cookies are stored in a query string form. In the latter, they are stored in a format that is suitable for the HTML FORM tag. Currently, the cookies in QueryCookies are used to rewrite all the tags except FORM.

Here is an example of the cookies in QueryCookies:

GXHC_GX_jst=d1f1943e55096164&amp;gx_session_id_=74cd83f757b5c8f6;

Here is an example of the cookies in FormCookies:

<INPUT NAME=" GXHC_GX_jst" TYPE=HIDDEN VALUE="d1f1943e55096164" </INPUT><INPUT NAME=" GXHC_ gx_session_id_" TYPE=HIDDEN VALUE="74cd83f757b5c8f6" </INPUT>

These cookies are extracted and stored, to be used in the rewriting of the subsequent responses.


Response Header Processing
The response from the iPlanet Application Server comes to the plugin in the HTTP response format. The plugin first processes the headers of this response using the following algorithm.

  1. The plugin counts the number of Set-Cookie headers in the response and uses this number to allocate space for a data structure referred to as ResponseCookies. For each Set-Cookie header in the response, the remaining steps are performed.

  2. If there is a domain attribute, its value is extracted.

  3. If the cookie is already present in QueryCookies or FormCookies, one of the following occurs:

    • If the incoming cookie has a domain, the cookie in QueryCookies or FormCookies may have come with its own domain, which was lost when it was used for URL rewriting. Since it has come (again) with a domain, it is treated as a new cookie. The flag treatAsNew is set to TRUE and the cookie is removed from QueryCookies or FormCookies.

    • If the incoming cookie does not have a domain associated with it, its value is checked against the value of the same cookie in QueryCookies or FormCookies.

      • If they are same, the new cookie is dropped and treatAsNew is set to FALSE.

      • If they are different, the cookie is removed from QueryCookies or FormCookies and treatAsNew is set to TRUE.

  4. If the cookie is not present in QueryCookies or FormCookies, the cookie is brand new, and treatAsNew is set to TRUE.

  5. If the incoming cookie has a domain, one of the following occurs:

    • It is validated using the following rules (from RFC 2109):

      • It must start with a dot.

      • It must have at least one embedded dot.

      If the domain satisfies these rules, the cookie will be used for URL rewriting, and the domainOK flag is set to TRUE. Otherwise, domainOK is set to FALSE.

    • The incoming cookie does not have a domain. The cookie will be used for URL rewriting, and domainOK is set to TRUE.

  6. If domainOK is TRUE and treatAsNew is TRUE, the incoming cookie is either brand new or an old cookie with a new value. Its name, value, and domain are added to the data structure ResponseCookies.

When the processing of headers finishes, all the old cookies are in QueryCookies or FormCookies and all the new ones are in ResponseCookies. The former are ready to be encoded in the response URLs, but the latter must be converted to such a format.


Response Body Processing
This stage is reached after the response headers are sent to the client. The body of the response is parsed. The plugin looks for the tags described in the section "Supported Tags and Attributes." It performs the following checks for these tags.

  1. The URL is checked to see if it is absolute or relative. Absolute URLs start with a protocol and look something like this: http://machine.website.com. If the URL is absolute, the host (machine.website.com) is extracted.

  2. The plugin must select cookies from ResponseCookies and convert them to a form that can be used for URL rewriting, referred to as NewCookies. The format used for all the tags except FORM is identical to the QueryCookies format. For FORM, the FormCookies format is used.

  3. Each cookie in ResponseCookies is added or not added to NewCookies according to this decision tree:

    • If the response URL to be rewritten is absolute, one of the following occurs:

      • If the cookie has a domain and it is part of the host name in the response URL, it is added to NewCookies.

      • If the cookie does not have a domain, the host name in the response URL is compared to the one in the request. If they are the same, the cookie is added to NewCookies.

    • If the response URL to be rewritten is relative, one of the following occurs:

      • If the cookie does not have a domain, it is added to NewCookies.

      • If the cookie has a domain that is part of the host name in the request, the cookie is added to NewCookies.

  4. The cookies in NewCookies are always encoded in the response URL. The cookies in QueryCookies and FormCookies are also encoded in the response URL under these conditions:

    • If the response URL to be rewritten is absolute and the host name in the response URL matches the host in the request.

    • If the response URL to be rewritten is relative.


The Location Header

Sometimes a request may be redirected to a different URL by sending back the HTTP header Location in the response. The URL associated with this header is also rewritten. The technique used to encode the URL is the same as the one used in response body processing. However, this rewriting is done as part of response header processing. By the time the Location header is encountered, all the valid cookies have been collected in ResponseCookies. If there is a query string in the URL, it is extracted and saved. The cookies in QueryCookies are added first, if necessary. Then the cookies selected from ResponseCookies are appended. Finally, the original query string is appended.


Order of the Cookies

All encoded cookies precede the query string.

The order in which the cookies are encoded in the response URL is dependent on the order in which they arrive as part of the response. Any new cookie in a subsequent request is appended to the cookies list. However, if a cookie is redefined in a subsequent response, it is deleted from its position and added to the end of the cookies list.

For example, suppose the response for a request comes with these cookies:

Set-Cookie c1=v1
Set-Cookie c2=v2
Set-Cookie c3=v3

The cookies are encoded as follows:

c1=v1&amp;c2=v2&amp;c3=v3

This order is used for all subsequent responses. All new cookies are appended.

However, suppose c2 is redefined in a subsequent request as follows:

Set-Cookie c2=v22

In this case, the format is changed as follows:

c1=v1&amp;c3=v3&amp;c2=v22


Sessions and Security

The iPlanet Application Server security model is based on an authenticated user session. Once a session has been created the application user is authenticated (if used) and logged in to the session. Each interaction step from the servlet that receives an EJB request, generates content to a JSP to format the output and is aware the user is properly authenticated.

Additionally, you can specify that a session cookie is only passed on a secured connection (that is, HTTPS), so the session can only remain active on a secure channel.

For more information about security, see Chapter 13 "Writing Secure Applications."



How to Use Sessions



To use a session, first create a session using the HttpServletRequest method getSession(). Once the session is established, examine and set its properties using the provided methods. If desired, set the session to time out after being inactive for a defined time period or invalidate it manually. You can also bind objects to the session which store them for use by other components.

This section describes the following topics:


Creating or Accessing a Session

To create a new session or to gain access to an existing session, use the HttpServletRequest method getSession(), as shown in the following example:

HttpSession mySession = request.getSession();

getSession() returns the valid session object associated with the request, identified in the session cookie which is encapsulated in the request object. Calling the method with no arguments, creates a session if one does not already exist which is associated with the request. Additionally, calling the method with a Boolean argument creates a session only if the argument is true.

The following example shows the doPost() method from a servlet which only performs the servlet's main functions, if the session is present. Note that, the false parameter to getSession() prevents the servlet from creating a new session if one does not already exist:

public void doPost (HttpServletRequest req,
                  HttpServletResponse res)
            throws ServletException, IOException
{
   if ( HttpSession session = req.getSession(false) )
   {
      // session retrieved, continue with servlet operations
   }
   else
      // no session, return an error page

   }
}



Note The getSession() method should be called before anything is written to the response stream. Otherwise the SetCookie string is placed in the HTTP response body instead of the HTTP header.



For more information about getSession(), see the Java Servlet Specification v2.2.


Examining Session Properties

Once a session ID has been established, use the methods in the HttpSession interface to examine session properties, and methods in the HttpServletRequest interface to examine request properties that relate to the session.

Table 12-2 shows the methods to examine session properties.


Table 12-2    HttpSession Methods

HttpSession method

Description

getCreationTime()  

Returns the session time in milliseconds since January 1, 1970, 00:00:00 GMT.  

getId()  

Returns the assigned session identifier. An HTTP session's identifier is a unique string which is created and maintained by the server.  

getLastAccessedTime()  

Returns the last time the client sent a request carrying the assigned session identifier (or -1 if its a new session) in milliseconds since January 1, 1970, 00:00:00 GMT.  

isNew()  

Returns a Boolean value indicating if the session is new. Its a new session, if the server has created it and the client has not sent a request to it. This means, the client has not acknowledged or joined the session and may not return the correct session identification information when making its next request.  

For example:

String mySessionID = mySession.getId();
if ( mySession.isNew() ) {
   log.println(currentDate);
   log.println("client has not yet joined session " + mySessionID);
}

Table 12-3 shows the methods to inspect request object properties that relate to the session:


Table 12-3    HttpServletRequest Methods  

HttpServletRequest Methods

Description

getRemoteUser()  

Gets the requesting user name (HTTP authentication can provide the information). Returns null if the request has no user name information.  

getRequestedSessionId()  

Returns the session ID specified with the request. This may differ from the session ID in the current session if the session ID given by the client is invalid and a new session was created. Returns null if the request does not have a session associated with it.  

isRequestedSessionIdValid()  

Checks if the request is associated to a currently valid session. If the session requested is not valid, it is not returned through the getSession() method.  

isRequestedSessionIdFromCookie()  

Returns true if the request's session ID provided by the client is a cookie, or false otherwise.  

isRequestedSessionIdFromURL()  

Returns true if the request's session ID provided by the client is a part of a URL, or false otherwise.  

For example:

if ( request.isRequestedSessionIdValid() ) {
   if ( request.isRequestedSessionIdFromCookie() ) {
      // this session is maintained in a session cookie
   }
   // any other tasks that require a valid session
} else {
   // log an application error
}


Binding Data to a Session

You can bind objects to sessions in order to make them available across multiple user interactions. The following HttpSession methods provide support for binding objects to the session object:


Table 12-4    HttpSession Methods  

HttpSession Methods

Description

getValue()  

Returns the object bound to a given name in the session or null if there is no such binding.  

getValueNames()  

Returns an array of names of all values bound to the session.  

putValue()  

Binds the specified object into the session with the given name. Any existing binding with the same name is overwritten. For an object bound into the session to be distributed it must implement the serializable interface. Note that the iPlanet Application Server RowSets and JDBC ResultSets are not serializable and cannot be distributed.  

removeValue()  

Unbinds an object in the session with the given name. If there is no object bound to the given name this method does nothing.  


Binding Notification with HttpSessionBindingListener
Some objects require you to know when they are placed in or removed from, a session. To obtain this information, implement the HttpSessionBindingListener interface in those objects. When your application stores or removes data with the session, the servlet engine checks whether the object being bound or unbound implements HttpSessionBindingListener. If it does, the iPlanet Application Server notifies the object under consideration, through the HttpSessionBindingListener interface, that it is being bound into or unbound from the session.


Invalidating a Session

Specify the session to invalidate itself automatically after being inactive for a defined time period. Alternatively, invalidate the session manually with the HttpSession method invalidate().



Tip The session API does not provide an explicit session logout API, so any logout implementation must call the session.invalidate() API.



 


Invalidating a Session Manually
To invalidate a session manually, simply call the following method:

session.invalidate();

All objects bound to the session are removed.


Setting a Session Timeout
Session timeout is set using the ias-specific Deployment Descriptor. For more information, see the session-info element in Chapter 11 "Packaging for Deployment."


Controlling the Session Type

iPlanet Application Server provides for types of sessions, lite and distributed:

  • The lite session is a fast, single process implementation of HttpSession. It should be used in all situations where speed is of utmost importance, and where no distribution of session data is required. This is the simplest form of HttpSession.

  • The distributed session is a robust and scalable implementation of the HttpSession API. It uses the Application Server's distribution facilities, thus enabling failover and load-balancing capabilities. It is somewhat slower than the lite session because of the overhead of network backup.

To control the session type, set the appropriate elements in the iPlanet Application Server specific XML file. For more information, see the session-info element in Chapter 11 "Packaging for Deployment."


Sharing Sessions in a Distributed Environment

iPlanet Application Server 6.5 allows the sharing of the same session object with concurrent requests in the same JVM. The following list describes the processes followed by iPlanet Application Server:

  1. Whenever there is a request accessing a session, it will increment a counter.

  2. Whenever there is a first mutable access to the session, the Dsync lock will be triggered, and the locking thread's reference is stored in the session.

  3. The session's state is refreshed from Dsync just after the lock.

  4. Every request while going out will decrement the counter, as well as saving the session.

  5. If the request going out was the one that had originally locked the session, then it waits for all the others requests to go out before the completion of servletrunner.execute().

    This request has been streamed out by the time it reaches this wait. The locking thread needs to wait as it is the only one with the authority to unlock.

  6. When all the requests for the session go out, the locking thread will unlock the session and leave.

  7. In case the session gets invalidated in between, the locking thread is asked to release the lock immediately, as there is not going to be any requirement for backend consistency from that point onwards.



    Note
    • For concurrent requests, there is a small overhead as the locking thread stays in a wait state till all the requests accessing the session are done with their work.

      If you are going to use plenty of concurrent accesses, this overhead must be taken into account when tuning for performance improvements.

    • When cross referencing objects as attributes, the objects will no longer hold the cross references when come out of the distributed session.

      This happens because every attribute gets individually serialized, and stored as a blob. Therefore, all the referenced objects also go into this blob. While retrieving, the whole object graph is unserialized independently for each attribute.




Sharing Sessions with AppLogics

Servlet programmers can use the iPlanet Application Server interface, HttpSession2 to share distributable sessions between AppLogics and servlets. Sharing sessions is useful when you want to migrate an application from NAS 2.x to iPlanet Application Server 6.5. HttpSession2 interface adds security and direct distributable sessions manipulation.

Additionally, if you establish a session in an AppLogic using loginSession() and you want to access the session from a servlet, you must call the setSessionVisibility() method in the AppLogic class to instruct the session cookie to transmit to servlets as well as AppLogics. Additionally, this must be completed before calling saveSession().

For example, in an AppLogic:

domain=".mydomain.com";
path="/"; //make entire domain visible
isSecure=true;
if ( setSessionVisibility(domain, path, isSecure) == GXE.SUCCESS )
   { // session is now visible to entire domain }

For more information about setSessionVisibility(), refer to the AppLogic class in the Foundation Class Reference (Java). For more information about sharing sessions between AppLogics and servlets, see the Migration Guide.


Previous     Contents     Index     Next     
Copyright © 2002 Sun Microsystems, Inc. All rights reserved.

Last Updated March 06, 2002