A recipe for cookie management

Integrate an easy-to-use library for client-side cookie handling

While developing a universal email client offering single-point access to all major Internet mail services, Web-based or otherwise, I found my application often had to act as a mini Web browser to interact with mail provider Websites. I stumbled upon the same need for Website interaction while developing XML Web service implementations to facilitate machine access to Websites. These sites often use cookies for state management—that is, to maintain user session data. In both cases, I realized that most Website interaction logic dealt with cookie handling. I also noticed that although both applications performed cookie handling, the logic was quite different and not interchangeable. In response to these limitations, I set out to develop a lightweight general-purpose library devoted to cookie handling. In this article, I share this library with you.

To illustrate the library in action, I present a console-based Hotmail email checker. Further, I explore client-side state management from the mobile device perspective using the Mobile Information Device Profile (MIDP) from the Java 2 Platform, Micro Edition (J2ME).

Cookie basics

Lets begin by answering some questions:

  • What is state management, and why do we need it?
  • What are cookies, and how do they fit into the picture?

To answer the first question, we must examine HTTP more closely. HTTP is basically a stateless protocol because, from a Web server's perspective, all HTTP requests are independent of preceding requests. That means each HTTP response depends entirely on the information contained in the corresponding request. While this behavior allows a simple and efficient Web server implementation, using it as a basis for complex Web applications proves rather difficult.

The state management mechanism overcomes this HTTP limitation and allows Web clients and servers to maintain a relationship between requests. The period during which this relationship holds is called a session. Most Web applications that require you to log in use sessions and state management. Shopping cart applications use state management to hold a list of all items marked for purchase. State management enables customization of portals and search engines to a particular user's preferences. Web applications can even use state management to tailor Website content based on user interests.

Cookies affect state management. Cookies are small pieces of text stored by the server on the local machine and sent with every request to that same server. The IETF RFC 2965 HTTP State Management Mechanism is the current cookie specification. The Web server uses HTTP headers, specified in the RFC (request for comments), to send cookies to the client. At the client end, the browser parses these cookies and stores them in a local file. It then attaches these cookies automatically to any requests to the same server. In the remainder of this article, I use the terms cookie handling and state management synonymously.

If you want to find out which sites you visit use cookies, try this simple experiment:

Warning: Perform this exercise only if you feel comfortable changing your browser's settings and generally know your way around your system.

  • Open your favorite browser. I assume you're using either Internet Explorer (IE) 5+ or Netscape Navigator 4+.
  • Disable automatic cookie handling:

    • In IE, from the Tools menu, choose Internet Options, then Security. Click Custom Level and scroll down until you see "Allow cookies that are stored on your computer." Choose the Prompt radio button. Also choose the Prompt radio button under "Allow per-session cookies (not stored)." Click OK to return to your main window.
    • In Netscape Navigator, from the Edit menu, choose Preferences, then Advanced. Check "Warn me before accepting a cookie." Now click OK to return to the main window.
  • Now, browse your favorite sites. Odds are, when you check your Webmail or shop online, dialog boxes will bombard you, asking for your permission to accept cookies.

Reverse the steps above to return to your original settings. You can also see what cookies are stored on your local machine (previous warning applies):

  • For IE: Using Windows Explorer or My Computer, browse to C:\Windows\Cookies. All the text files in this directory contain cookies
  • For Netscape Navigator:

    • On Windows, using Windows Explorer or My Computer, browse to C:\Program Files\Netscape\Users. Look for a file named "cookies.txt" or "cookies" in the subdirectories
    • On Unix(-like) systems, look for a file named "cookies" in the ".netscape" directory

Note: Depending on your system setup, the steps to disable automatic cookie handling and view stored cookies might vary.

Now that you know the basics, I next explain how this discussion relates to Java.

State management in Java

Java applications require cookie handling in the following scenarios:

  • Website interaction: To interact with Websites, Internet-based client-side applications often act as mini Web browsers. These sites use cookies for state management—that is, to maintain user session data.
  • Web services implementations: Web services promise to make the Web a friendlier place for machines. One desirable way to permit machine-Website interaction is to have a Web service front the Website. Thus, the Web service presents a machine-friendly view of the target Website. Such Web services' implementations would need cookie handling to carry out the actual Website interaction.
  • Web browsers: Java-based Web browsers would need cookie-handling modules to support state management.

To carry out client-side cookie handling, browsers follow these steps:

  • For retrieving cookies:

    1. Extract the cookies from the incoming HTTP headers
    2. Parse the cookies for individual components (name, value, path, and so on)
    3. Determine if the host is permitted to set those cookies
  • For sending cookies:

    1. Determine which cookies can be sent to host
    2. For multiple cookies, determine the order in which cookies must be sent
    3. Format and send the cookies with outgoing HTTP headers

A client-side Java application should follow all the above steps. But implementing all those steps using the rules specified in RFC 2965 eats up considerable time and distracts the developer from the core application. As a result, the developer often chooses to compromise the specification and ends up with slipshod custom cookie-handling code that could break easily.

For example, suppose you want to write a Java client application that interacts with a servlet-based shopping Web application. On the server side, when the servlet first asks the servlet container for a session by calling request.getSession(), the container creates a new session and the server uses a session ID to retrieve the session object on subsequent requests. The server automatically sends this session ID to the client as an HTTP cookie. In subsequent requests, the client sends back the same session ID along with its request. The server uses the ID to locate the right session object for the servlet processing the request. Typically, the code on the client would look like this:

      /* To get cookie. */
      ...
      HttpURLConnection huc= (HttpURLConnection) url.openConnection();
      ...
      InputStream is = huc.getInputStream();
      // Retrieve session ID from response.
      String cookieVal = hc.getHeaderField("Set-Cookie");
      String sessionId;
      if(cookieVal != null)
      {
            sessionId = cookieVal.substring(0, cookieVal.indexOf(";"));
      }
      ...
      /* To send cookie. */
      HttpURLConnection huc= (HttpURLConnection) url.openConnection();
      if(sessionId != null)
      {
            huc.setRequestProperty("Cookie", sessionId);
      }
      
      InputStream is = huc.getInputStream();
      ...

The cookie specification RFC 2965 defines a new header, Set-Cookie2, for version 1 cookies. If we upgraded the server to use the new header, the above code would break. The above code could also not handle multiple cookies. In addition, a version 1 cookie's value can be a quoted string. If the session cookie's value were a quoted string containing a semicolon, that would also cause the above code to break. In short, the code snippet above is not insulated from the cookie version used and is unnecessarily coupled to it.

The above code might be acceptable for a simple application that interacts with only one particular host and path map. But for a more ambitious application, cookie management grows complex when multiple hosts and paths are involved. It would prove painful and unproductive for a developer to implement all the algorithms, security checks, and balances outlined in the cookie specification.

Enter jCookie

To ease some of this heartache, I've developed a general-purpose cookie library christened, predictably, jCookie, which implements the cookie specification. The library minimizes the extra coding and effort required for client-side cookie handling and lets the developer focus on the core application. Other APIs/libraries do exist (for example, HTTPClient from Apache), but they use architectures far removed from the built-in native java.net APIs, thus introducing a new learning curve. My API can be as simple as a method call on existing java.net objects.

You could also use a stripped-down version of jCookie currently under development, called jCookieMicro, on J2ME-enabled mobile devices to create an exciting suite of fat clients that can interact with Web server-based applications.

I now introduce the jCookie API's major actors. I'll start with the two main data structures:

  1. Class Cookie: An instance of this class represents a single cookie. It encapsulates all the cookie properties defined by RFC 2965 and provides access to those properties using getters and setters.
  2. Class CookieJar: An instance of this class acts as a container for a collection of Cookie objects. It conforms to the Collections Framework and provides operations to manipulate the cookie collection.

The API presents two views to simultaneously satisfy the developer requiring transparent cookie handling and the developer requiring advanced features. The following figure illustrates these views, or layers.

jCookie library's layered views

The jCookie architecture

Below, I describe the layers and the various classes they use.

Layer 1

Those developers wanting (almost) transparent cookie handling, which is usually the case, use Layer 1. At this level, you use the Client class to handle cookies. It has two primary methods:

  • public CookieJar getCookies(URLConnection urlConn): This method extracts the cookies from the given URLConnection, parses them into Cookie objects, and returns them as a CookieJar
  • public CookieJar setCookies(URLConnection urlConn, CookieJar cj): This method picks out the appropriate Cookie objects from the CookieJar and sets URLConnection's headers

Layer 0

Those developers who cannot breathe without being neck-deep in code (myself included) use Layer 0. At this level, you can change the parsing logic and the security rules used by the cookie-handling code. To do this, first implement the CookieParser interface. It has the following four methods:

  • public Header getCookieHeaders(CookieJar cj): Converts the Cookies in the CookieJar to a header set suitable for sending with an HTTP request
  • public boolean allowedCookie(Cookie c, URL url): Checks whether a request to the given URL can return the specified Cookie
  • public CookieJar parseCookies(Header h, URL url): Converts the headers in an HTTP response into a CookieJar of Cookie objects
  • public boolean sendCookieWithURL(Cookie c, URL url, boolean bRespectExpires): Checks whether the given Cookie can be sent with a request for the given URL

You can use the Client class's setCookieParser(CookieParser cp) method to set the CookieParser implementation. The default CookieParser used by the library is an implementation of the RFC 2965 cookie specification.

At Layer 1, jCookie acts as a library; at Layer 0, it incorporates elements of an API.

jCookie usage

The Client class invokes the cookie-handling logic at both layers. It provides the application developer's library view. To use the jCookie library, follow these steps:

  • To retrieve cookies from responses to requests:

    1. Create a URLConnection object and set it up
    2. Connect the URLConnection
    3. Create a Client object and set a custom CookieParser if desired
    4. Obtain a CookieJar of Cookies by calling the Client instance's getCookies() method, passing in URLConnection as an argument
    5. Do something with the HTTP response
  • To send cookies with a request (assuming a CookieJar was retrieved earlier):

    1. Create a URLConnection object and set it up
    2. Create a Client object and set a custom CookieParser if desired
    3. Set cookie headers by calling the Client instance's setCookies() method, passing in URLConnection and CookieJar as arguments
    4. Connect the URLConnection
    5. Do something with the HTTP response

The following snippet shows common jCookie usage. The jCookie code is highlighted:

import com.sonalb.net.http.cookie.*;
import java.net.*;
import java.io.*;
...
public class Example
{
   ...
   
   public void someMethod()
   {
      ...
      URL url   = new URL("http://www.site.com/");
      HttpURLConnection huc =   (HttpURLConnection) url.openConnection();
      
      // Set up the HttpURLConnection here.
      ...
      huc.connect();
      InputStream is = huc.getInputStream();
      Client client =   new Client();
      CookieJar cj = client.getCookies(huc);
      // Do some processing.
      ...
      huc.disconnect();
      // Make another request.
      url = new URL("http://www.site.com/");
      huc = (HttpURLConnection) url.openConnection();
      client.setCookies(huc, cj);
      huc.connect();
      ...
      // Do some processing.
   }
}

The above code illustrates two facets of the jCookie API:

  • The use of native java.net objects (HttpURLConnection)
  • The ease of retrieving and sending cookies (single method calls)

In practice, real code following the above pattern would have successfully maintained a session between the two requests. Now that we have covered the library's basic structure, let's put jCookie through its paces with some real code.

Hotmail new mail checker

To illustrate the jCookie library's ease of use, I'll use it in an application that displays the From, Subject, and Date fields of the new messages in a Hotmail account. For simplicity, the application displays this information on the console. To receive the new messages in a Hotmail inbox, the application needs to complete the following steps:

  • Log in to Hotmail by performing an HTTP POST operation on the login form
  • To reach the main page, handle redirects and cookies
  • Retrieve the inbox HTML page
  • Extract the relevant fields for the new messages

Most sites requiring user logins complete the login process by first performing an HTTP POST operation through a form. For successful authentication, the POST's response is usually an HTTP redirect with some cookie headers. The cookies return to the server when the redirected page is requested.

The jCookie library includes a convenience class called HTTPRedirectHandler, which manages the common task of handling redirects while completing client-side cookie handling. To use the class, first create an HTTPRedirectHandler instance, passing in an unconnected HttpURLConnection. Then call the HTTPRedirectHandler instance's connect() method to handle the redirect and cookie. The handler ascertains a successful run from the HTTP response code. Once processing completes, the calling class retrieves the HttpURLConnection object representing the last request. The CookieJar containing all the cookies received during the course of the redirects can also be retrieved. The cookie-handling logic lies in HTTPRedirectHandler's connect() method. Let's take a look at this method's code. The cookie-handling parts are commented:

package com.sonalb.net.http;
import com.sonalb.net.http.cookie.*;
import java.net.*;
import java.io.*;
public class HTTPRedirectHandler
{
   ...
   public HTTPRedirectHandler(HttpURLConnection huc)
   {
      ...
   }
   public void connect() throws IOException
   {
      if(bConnected)
      {
         throw new IllegalStateException("No can do. Already connected.");
      }
      int code;
      URL url;
      huc.setFollowRedirects(false);
      // Set any passed-in Cookies.
      if(!cj.isEmpty())
      {
         client.setCookies(huc,cj);
      }
      is = huc.getInputStream();
      // Extract Cookies from HttpURLConnection and add to CookieJar.
      cj.addAll(Client.getCookies(huc));
      while((code = huc.getResponseCode()) != successCode && maxRedirects > 0)
      {
         if(code != 302)
         {
            throw new IOException("Can't deal with this code (" + code + ").");
         }
         is.close();
         is = null;
         url = new URL(huc.getHeaderField("location"));
         huc.disconnect();
         huc = null;
         huc = (HttpURLConnection) url.openConnection();
         // Send Cookies with the HTTP request.
         Client.setCookies(huc, cj);
         huc.setFollowRedirects(false);
         huc.connect();
         is = huc.getInputStream();
         // Extract Cookies from the response, and add to jar.
         cj.addAll(Client.getCookies(huc));
         maxRedirects--;
      }
      if(maxRedirects <= 0 && code != successCode)
      {
         throw new IOException("Max redirects exhausted.");
      }
      bConnected = true;
   }
   // Other methods come here.
   public void handleCookies(boolean b)
   {
      ...
   }
   public void setSuccessCode(int i)
   {
      ...
   }
   public void setCookieJar(CookieJar cj)
   {
      ...
   }
   public void addCookies(CookieJar cj)
   {
      ...
   }
   public CookieJar getCookieJar()
   {
      ...
   }
   public HttpURLConnection getConnection()
   {
      ...
   }
   public void setMaxRedirects(int i)
   {
      ...
   } 
}

The HotmailChecker application uses the HTTPRedirectHandler for the login process. The application retrieves the CookieJar from the HTTPRedirectHandler for use with subsequent requests. The relevant portion of the HotmailChecker is shown below. Hotmail-specific and jCookie-related commentary is highlighted:

public boolean doLogin() throws Exception
{
   // Set up JSSE for HTTPS.
   System.getProperties().put("java.protocol.handler.pkgs","com.sun.net.ssl.internal.www.protocol");
   java.security.Security.addProvider(new com.sun.net.ssl.internal.ssl.Provider());
   // Create HttpURLConnection and set it up.
   URL url = new URL("https://lc2.law13.hotmail.passport.com/cgi-bin/dologin");
   HttpURLConnection huc = (HttpURLConnection) url.openConnection();
   huc.setDoOutput(true);
   huc.setRequestMethod("POST");
   huc.setRequestProperty("User-Agent","Mozilla/4.7 [en] (Win98; I)");
   // Send the login form fields.
   StringBuffer sb = new StringBuffer();
   sb.append("login="); sb.append(URLEncoder.encode(user));
   ...
   OutputStream os = huc.getOutputStream();
   os.write(sb.toString().getBytes("US-ASCII"));
   os.close();
   // Create handler and do processing.
   HTTPRedirectHandler hrh = new HTTPRedirectHandler(huc);
   hrh.connect();
   huc = hrh.getConnection();
   // Microsoft has an interim page that uses a Refresh Meta tag for transition between
   // HTTPS and HTTP, this prevents the security warning popup.
   // We need to manually do this URL fetch by reading response and parsing for URL.
   BufferedReader br = new BufferedReader(new InputStreamReader(huc.getInputStream()));
   ...
   // Once we have the URL for the Main page, we again use HTTPRedirectHandler to retrieve 
   // it and then process response to verify proper login.
   url = new URL(homeUrl);
   huc = (HttpURLConnection) url.openConnection();
   huc.setRequestProperty("User-Agent","Mozilla/4.7 [en] (Win98; I)");
   hrh = new HTTPRedirectHandler(huc);
   hrh.setCookieJar(cj);
   hrh.connect();
   ...
   // Save Cookies for future requests.
   cj.addAll(hrh.getCookieJar());
   ...
   return(bLoggedIn);
}

Now that we have logged in to Hotmail, we request the inbox page, passing in the Cookies retrieved during the login process. Once we have the inbox page, we must parse this HTML for the information pertaining to the new messages. Instead of using a brute-force StringTokenizer to retrieve this information, we'll use a slightly more elegant (i.e., complicated) approach, leveraging XML. This approach involves:

  • Converting the poorly formed HTML into well-formed HTML
  • Traversing the well-formed HTML using DOM (Document Object Model) to obtain new message information

If DOM, XML, and well-formed are Greek to you, suffice it to say that we convert the inbox HTML into a tree-like structure of objects and then get to the desired information.

To convert poorly formed HTML to well-formed HTML, we use a combination of the freely downloadable JTidy tool and a custom processor. The ConvertBadHTMLToGood helper class converts the poorly formed Hotmail HTML into well-formed HTML. The relevant code appears below:

import java.io.*;
import org.w3c.tidy.*;
public class ConvertBadHTMLToGood
{
   ...
   public ConvertBadHTMLToGood(Reader r)
   {
      if(r == null)
      {
         throw new IllegalArgumentException();
      }
      inReader = r;
   }
   public Reader doConvert() throws IOException
   {
      // Setup JTidy objects.
      Tidy tidy = new Tidy();
      tidy.setXmlOut(true);
      tidy.setErrout(new PrintWriter(new StringWriter()));
      // The JTidy parser requires an InputStream. There is no direct way, 
      // to the best of my knowledge, to convert a Reader into an InputStream.
      // This workaround code is not character-encoding safe, but gets by.
      BufferedReader br = new BufferedReader(inReader);
      StringBuffer sb = new StringBuffer();
      String line;
      while((line = br.readLine()) != null)
      {
         sb.append(line);
         sb.append("\n");
      }
      ByteArrayInputStream bais = new ByteArrayInputStream(sb.toString().getBytes("US-ASCII"));
      ByteArrayOutputStream baos = new ByteArrayOutputStream();
      // Do the preliminary conversion of HTML to well-formed HTML.
      tidy.parse(bais, baos);
      // Fix some stuff JTidy missed to get output that can be 
      // parsed by "true-blue" XML parsers.
      FixEntities fe = new FixEntities(baos.toString());
      return(fe.getFixedReader());
   }

Once we have well-formed HTML, we use the Java API for XML Parsing (JAXP) to convert the well-formed HTML into a DOM tree and traverse the tree to obtain new messages' From, Subject, and Date fields. I'll omit the traversal code to save you from code deluge; instead, I'll show you how to use the HotmailChecker:

import com.sonalb.net.http.cookie.*;
...
public class HotmailChecker
{
   public static void main(String args[]) throws Exception
   {
      if(args.length != 2)
      {
         usage();
         System.exit(0);
      }
      String uname = args[0];
      String pass = args[1];
      HotmailChecker hmc = new HotmailChecker(uname,pass);
      
      if(!hmc.doLogin())
      {
         System.out.println("Could not login to Hotmail.");
         System.exit(0);
      }
      Vector newMessages = hmc.getNewMessages();
      if(newMessages == null)
      {
         System.out.println("No NEW Messages.");
         return;
      }
      System.out.println("You have " + newMessages.size() + " NEW Messages");
      System.out.println("---------------------------------------------");
      Iterator iter = newMessages.iterator();
      // HMMessage encapsulates a Hotmail message.
      HMMessage hm;
      while(iter.hasNext())
      {
         hm = (HMMessage) iter.next();
         System.out.println("     From: " + hm.getFrom());
         System.out.println("  Subject: " + hm.getSubject());
         System.out.println("Sent Date: " + hm.getSentDate());
         System.out.println("---------------------------------------------");
      }
   }
   static void usage()
   {
      System.out.println("\nUsage: java HotmailChecker <Hotmail Username> <Password>");
   }
   // Instance variables and methods start here.
   ...
   public HotmailChecker(String username, String password)
   {
      ...
   }
   public boolean doLogin() throws Exception
   {
      ...
   }
   public Vector getNewMessages() throws Exception
   {
      ...
   }
   ...
}

You can download the complete, functional HotmailChecker and associated classes from Resources.

jCookieMicro meets J2ME

Note: This section assumes at least casual familiarity with J2ME.

Earlier, I mentioned the possibility of using the jCookieMicro library on J2ME-enabled mobile devices to build fat clients that interact with Web applications. I'm still developing the jCookieMicro library. Its structure and usage will resemble the jCookie library, except that in place of URLConnection, the jCookieMicro library will use the MIDP HttpConnection object. This section describes the benefits of using full-fledged cookie handling on mobile applications—in our case, MIDlets.

Let's first examine the current approaches to state management in J2ME applications. The Forum Nokia paper entitled "A Brief Introduction to Networked MIDlets" (March 2002) describes one approach. The paper's proposed mechanism works as a variation on the URL-rewriting mechanism: A servlet sits on a Web server holding all business logic and uses custom HTTP headers, rather than cookies, to carry state information. The MIDlet simply acts as a user interface, passing user input to the servlet and displaying the result. (For more on URL rewriting and other approaches to state management in J2ME applications, read "Track Wireless Sessions with J2ME/MIDP," by Michael Juntao Yuan and Ju Long (JavaWorld, April 2002).)

Using the above approach, here is the solution for the application relevant to this discussion, one that interacts with Web-based services/applications like a mini Web browser:

  • The MIDlet collects relevant input from the user (e.g., a Hotmail username and password)
  • The MIDlet transmits input to the servlet
  • The servlet uses input to interact with the Web-based service/application (e.g., the Hotmail Website)
  • The servlet transmits the result(s) to the MIDlet (e.g., a list of new messages)
  • The MIDlet displays the result(s) to user

In the above solution, custom HTTP headers maintain a session between the MIDlet and the servlet. Consequently, both the servlet and the MIDlet contain logic for explicitly carrying out session management. This proves undesirable for the same reason described earlier: the custom code can break easily, even as a result of routine administrative changes, such as a server upgrade. Another drawback to this approach: it requires an intermediary mobile application-aware servlet to sit between the target Web application (e.g., Hotmail) and the mobile application.

You can substitute jCookieMicro for the above approach in two ways:

  1. Move all business logic to the mobile application and eliminate the intermediary servlet altogether. Use jCookieMicro in the mobile fat client for session management.
  2. Keep business logic in the intermediary servlet, but eliminate the custom headers, and use jCookieMicro for transparent and robust session management.

The second method proves suitable for modifying existing applications. The first method leads to reduced cost and greater ease of mobile application development because it eliminates expensive server-side resources. The application flow using the first method would look like this:

  • The MIDlet collects relevant input from the user
  • The MIDlet directly connects to the target Web service and interacts with it
  • The MIDlet displays the result(s) to the user

The first method also eliminates the following drawbacks of keeping business logic in the servlet:

  • A servlet container outage takes the entire application offline, even if the target Web service is operational
  • Applications are limited to only those deployed as servlets

Another approach to state management in mobile applications, described in the Sun Wireless Java Developer article "Session Handling in MIDP," (January 2002) does not rely on custom headers, but involves writing custom code in the mobile application to handle cookies. The earlier discussion on the disadvantages of writing custom code and the advantages of using jCookie(Micro), is relevant here also (see the section above entitled "State Management in Java").

Even though jCookieMicro is in the works, you can use the jCookie library today in applications for the PersonalJava Application Environment (PJAE), since PJAE offers the complete JDK 1.1.8 platform along with some Java 2 classes.

jCookie limitations

The jCookie library in its present form has some limitations:

  • While the cookie parsing logic and security rules can plug in to the existing API (using CookieParser), no such mechanism is available for the core data structure, the Cookie class
  • No performance testing has been done

You can obtain the latest jCookie release, as well as the project's source code, from http://jcookie.sourceforge.net/. Some items planned for future versions include:

  • Use of the Jakarta Project's log4J logging API to provide user-configurable logging and debugging
  • A facility to modify jCookie behavior using a user-defined controller; this could determine whether failure to parse a single cookie would result in a fatal error, for example

Implementation of these and other features depends largely on your feedback. Please use the mailing lists, bug trackers, feature requests, and so on at the jCookie project site on SourceForge.net.

Get cooking

The jCookie library presented here facilitates less painful development of stateful client-side applications. As mentioned earlier, other libraries perform similar functions (see Resources), but these architectures are far removed from the existing native java.net API. In addition, no API/library addresses cookie handling alone. Other libraries incorporate cookie handling as a part of a complete Java Web client architecture; as a result, using these libraries involves a whole new learning curve.

The jCookie library lies close to the existing java.net objects. State management is as simple as two method calls on the ubiquitous URLConnection or HttpConnection. You can further simplify state management by using the HTTPRedirectHandler convenience class. jCookie strives to put browser-like cookie management at the disposal of client-side application developers. How far it succeeds can be determined only by your response. I'd appreciate any comments or suggestions you'd care to share.

I would like to acknowledge the help given to me by Gaurav Pal, a consultant with RDA, in conceptualizing and documenting this API, which otherwise might have remained stuck in some hard drive as meaningless 0s and 1s.

Sonal Bansal is an independent software developer and technical writer. He has more than six years of programming experience, having completed work for organizations like Tata Consultancy Services, IRIEEN (Indian Railway Institute of Electrical Engineering), and Southern Railway. He spends his free time tinkering in Java and usually gets away with posing as a Java guru. You can read more about his work at http://www.javapal.com.

Learn more about this topic

Join the discussion
Be the first to comment on this article. Our Commenting Policies
See more