Sun Java Solaris Communities My SDN Account
 
Article

Session Handling in MIDP

 

A typical multitier application stores its data, including user information or preferences, in a database. Client devices send requests to a Web tier, which processes them and sends responses back. The Web tier retrieves user information from the database to customize its behavior for a particular user.

Applications use a technique called session handling to avoid looking up user information each time the client communicates with the server. This article describes session handling, starting at the server side and continuing through to the client. It includes servlet and MIDlet code examples.

HTTP and Java Servlets

Let's assume you want to make your application available over HTTP using Java servlets, and you want server-side processing to reflect user preferences known to the client application. HTTP is based on a client request and a server response. It is a stateless protocol, which means that each request and response pair is a complete interaction. There's no immediate provisioning for preserving user preferences on the server side fromr one interaction to the next. One way to implement user preferences would be to have the client send a user name or ID with each request. The servlet would use the ID to look up the user information and process the request appropriately.

A simple implementation would look something like this:

import javax.servlet.http.*;
import javax.servlet.*;
import java.io.*;

public class SessionServlet extends HttpServlet { public void doGet(HttpServletRequest request,
HttpServletResponse response)
throws ServletException, IOException { // Retrieve the user ID which is passed to us as a parameter. String id = request.getParameter("user");

// Now look up the corresponding user information. Object user = lookupUser(id);

// Now process the request, using the user information we // just looked up to customize our behavior. Write the // response back to the client. } private Object lookupUser(String id) { // Most likely we would use JDBC to connect to a database, // perform a query, package the results up as an object, // and return that object. Most likely it would be a // specific type, perhaps User, UserInformation, // or UserPreferences. return null;
} }

This code is probably setting off alarm bells in your head. We're going to look up the user information in the database every time the client makes a request? That's not very efficient, because database lookups are generally slow. We could speed things up by using a connection pool, but we'd still be paying the price of a database query for every client request.

HTTP Session Handling

What you really want is for the servlet to look up the user information once, save it somewhere, and use it each time a client request comes in from that user. HTTP's statelessness is working against you here, but there are two clever workarounds that let a client and a server maintain an interaction that is longer than just one request and response. This interaction is called a session.

You will read about the underlying details for handling session objects later. For the moment, assume that the servlet can obtain the user information from the session. If it is not there, the servlet does the costly database lookup and stores the user information in the session. Next time the same user makes a request, the user information is there in the session.

The Servlet API provides a clean way of handling HTTP sessions. The servlet code doesn't need much revision:

import javax.servlet.http.*;
import javax.servlet.*;
import java.io.*;

public class SessionServlet extends HttpServlet {
  public void doGet(HttpServletRequest request,
      HttpServletResponse response)
      throws ServletException, IOException {
    // Retrieve the session object corresponding to this request.
    HttpSession session = request.getSession();
    
    // Try to retrieve the user object from the session.
    Object user = session.getAttribute("User-Information");
    
    if (user == null) {
      // Retrieve the user ID which is passed to us as a parameter.
      String id = request.getParameter("user");
      
      // Now look up the corresponding user information.
      user = lookupUser(id);
      
      // Put the user information into the session.
      session.setAttribute("User-Information", user);
    }
    
    // Now process the request, using the user information we
    // just looked up to customize our behavior. Write the
    // response back to the client.

    // For now, just compose a suitable reply message.
    String message;
    if (session.isNew())
      message = "New session created: " + session.getId();
    else
      message = "Used existing session: " + session.getId();

    // Send the message to the client.
    response.setContentType("text/plain");
    response.setContentLength(message.length());
    PrintWriter out = response.getWriter();
    out.println(message);
  }
  
  private Object lookupUser(String id) {
    // Most likely we would use JDBC to connect to a database,
    // perform a query, package the results up as an object,
    // and return that object. Most likely it would be a
    // specific type, perhaps User, UserInformation,
    // or UserPreferences.
    
    return null;
  }
}

The servlet container uses a session ID to keep track of the session. When a client request contains a session ID, the servlet container uses that ID to locate the corresponding session. If the request doesn't include an ID, the container creates a new session object.

Keep in mind that the user ID and session ID are not directly related. The client passes the user ID to the servlet. The servlet uses it to find user information in a database. The servlet then places this information into a session object identified by a session ID.

The servlet container sends the session ID back to its client by embedding it in the HTTP response. It is the client's responsibility to save the session ID and send it with subsequent requests. Browsers handle this chore automatically, so you may not even know it's happening. When you're programming your own clients, however, for example in MIDP, you have to handle session IDs yourself, using either URL rewriting or cookies.

Under the Covers with URL Rewriting

Web servers often use URL rewriting to track sessions with browsers that don't support cookies: the server embeds the session ID inside an optional part of every HTML link that it sends to the browser. Each time the user clicks on a link in the page, the session ID is sent up to the server as part of the URL.

For example, suppose the server is going to deliver the following HTML content to the browser:

<html>
  <head><title>Simple page</title></head>
  <body>
    <a href="http://wireless.java.sun.com/">
      Wireless Developer
    </a>
  </body>
</html>

The server can rewrite the URL to embed the session ID in the link, this way:

<html>
  <head><title>Simple page</title></head>
  <body>
    <a href="http://wireless.java.sun.com/
        ;jsessionid=2317F5F557729157F5A695157835E552">
      Wireless Developer
    </a>
  </body>
</html>

When the user clicks on the link in a browser, the entire URL, including the session ID, is sent to the server.

URL rewriting is a solution specific to HTML, and thus unlikely to be appropriate for a MIDP client. Due to bandwidth and processing constraints in MIDP devices, your server and client will probably exchange information in very efficient forms, not verbose markup languages like HTML.

Under the Covers with Cookies

Session tracking is a common use for cookies, which are part of the HTTP specification. A cookie is a little piece of information, usually an identifier of some kind, exchanged between cooperating programs. A server can include a cookie in its response to an HTTP request from a client. Clients are expected (though not required) to store the cookie and send it back, as appropriate, in HTTP requests. A cookie is a good place to store a session ID.

When servlet first asks its container for a session by calling request.getSession(), the container creates a new session and sends the ID back to the client as an HTTP cookie. In subsequent requests, the client sends the session ID in its HTTP request and the server uses this session ID to locate the right session object.

The following example illustrates how the session ID cookie looks inside the server's HTTP response.

HTTP/1.1 200 OK
Content-Type: text/plain
Content-Length: 53
Date: Tue, 18 Dec 2001 17:19:22 GMT
Server: Apache Tomcat/4.0.1 (HTTP/1.1 Connector)
Set-Cookie: JSESSIONID=35E2621570C3B1D052E86285D1A002D6;Path=/midp

If the client is a MIDlet, it is responsible for recognizing the session ID cookie in the server's response. The MIDlet is also obliged to send this session ID to the server, inside an HTTP request. To understand exactly how this process works, let's examine a simple piece of code that a MIDlet could use to retrieve data from a server.

String url = getAppProperty("SessionMIDlet.URL");

// Query the server and retrieve the response.
HttpConnection hc = (HttpConnection)Connector.open(url);
InputStream in = hc.openInputStream();

// Read the response from the server. // Clean up. in.close(); hc.close();

Now suppose the server sends the client a session ID as a cookie. The server response will have a Set-cookie header line. For simplicity's sake, we'll assume the server is sending us only one cookie. The cookie itself consists of several attributes, like the cookie's name, its expiration date, and the server path to which it applies. Only the name of the cookie is required; other attributes are optional. Again for simplicity, we'll retrieve only the cookie's name and ignore everything else. Because attributes are separated by semicolons, we can simply save the session ID in a String member variable, mSession:

String url = getAppProperty("SessionMIDlet.URL");

// Query the server and retrieve the response.
HttpConnection hc= (HttpConnection)Connector.open(url);
InputStream in = hc.openInputStream();

// Read the session ID from a cookie in the response headers.
String cookie = hc.getHeaderField("Set-cookie");
if (cookie != null) {
  int semicolon = cookie.indexOf(';');
  mSession = cookie.substring(0, semicolon);
}

// Read the response from the server.

// Clean up.
in.close();
hc.close()
;

Saving the cookie sent by the server is only part of the solution. We need to send it back in the request, as well:

String url = getAppProperty("SessionMIDlet.URL");

// Query the server and retrieve the response.
HttpConnection hc = (HttpConnection)Connector.open(url);
if (mSession != null)
hc.setRequestProperty("Cookie", mSession);
InputStream in = hc.openInputStream();

// Read the session ID from a cookie in the response headers. String cookie = hc.getHeaderField("Set-cookie");
if (cookie != null) { int semicolon = cookie.indexOf(';');
mSession = cookie.substring(0, semicolon);
} // Read the response from the server. // Clean up. in.close();
hc.close();

That's all there is to it. We've made some simplifying assumptions, but the essential code is in place. To make this code more robust or more generalized, you could program the following enhancements:

  • Allow for the possibility that the server is sending multiple cookies to the client. You would need to search through each header using the HttpConnection's getHeaderFieldKey(int) and getHeaderField(int) methods. You could save all the cookies, or discard all but the session ID cookie, whose name is JSESSIONID, as appropriate.
  • Generalize the client cookie-sending behavior. Cookies may include information about the server for which they're destined, the specific path on that server, and even an expiration date. You could add code to the MIDlet that examines and uses this additional information. In the simple case, when your MIDlet is connecting to only one server over the course of its life, it's a pretty safe bet just to catch the session ID cookie and send it right back.

Summary

You now understand the fundamentals of session handling on both the server and client ends of an application. You've learned about HTTP cookies and how to handle a session ID cookie from a client MIDlet.

If you'd like to try this out for yourself, you can download two complete source files to get started:

  • SessionServlet.java is a simple servlet that retrieves the session for a client request and sends back a message indicating whether the session is newly created or reused.
  • SessionMIDlet.java is a MIDlet that implements the cookie handling described above.

Alternately, you can download a MIDlet suite that contains SessionServlet.

  • SessionSuite.jad is the MIDlet suite descriptor. Note that you will need to supply a value for the SessionMIDlet.URL application property in this file. Point it to wherever you have installed SessionServlet.
  • SessionSuite.jar is the MIDlet suite itself.



Reader Feedback
Excellent   Good   Fair   Poor  

If you have other comments or ideas for future technical tips, please type them here:

Comments:
If you would like a reply to your comment, please submit your email address:
Note: We may not respond to all submitted comments.

Have a question about Java programming? Use Java Online Support.



Back To Top

Oracle is reviewing the Sun product roadmap and will provide guidance to customers in accordance with Oracle's standard product communication policies. Any resulting features and timing of release of such features as determined by Oracle's review of roadmaps, are at the sole discretion of Oracle. All product roadmap information, whether communicated by Sun Microsystems or by Oracle, does not represent a commitment to deliver any material, code, or functionality, and should not be relied upon in making purchasing decisions. It is intended for information purposes only, and may not be incorporated into any contract.