Cookie Handling in Java SE 6

by John Zukowski

Back in September 2005, the Cookie Management with CookieHandler tip described the J2SE 5.0 support for managing cookies over network connections. The 5.0 release provided the framework for dealing with these little nuggets of information, but the task of doing all the work was left to you, the developer. You only had to follow the defined API, but there was much work that needed to be done to actually get cookie management going well for your programs.

A quick look back to the J2SE 5.0 API brings you right to the abstract CookieHandler class but with no real implementation, no storage mechanism, no storage policy, and nothing to store. Jump ahead to Java SE 6, and the CookieManager class offers just such an implementation of CookieHandler. CookieStore is the storage mechanism, and CookiePolicy offers a policy for accepting or rejecting cookies. Lastly, HttpCookie is the object to store.

What used to be a difficult though doable task in J2SE 5.0, becomes simple construction of existing classes in Java SE 6.

Here's the working J2SE 5.0 program for working with cookies:

import java.io.\*;
import java.net.\*;
import java.util.\*;

public class Fetch {
  public static void main(String args[]) throws Exception {
    if (args.length == 0) {
      System.err.println("URL missing");
      System.exit(-1);
    }
    String urlString = args[0];
    CookieHandler.setDefault(new ListCookieHandler());
    URL url = new URL(urlString);
    URLConnection connection = url.openConnection();
    Object obj = connection.getContent();
    url = new URL(urlString);
    connection = url.openConnection();
    obj = connection.getContent();
  }
}

Notice the setDefault method call to CookieHandler in the middle. The ListCookieHandler class was the tip's implementation of a basic CookieHandler.

The Java SE 6 version of the same program is nearly identical but has just one change to the following line:

CookieHandler.setDefault(new CookieManager());

You don't need to provide any additional code. It is really that simple to go between the different APIs. There are some other differences, but changing the one line in the Fetch program has the second network connection use the cookies returned from the first.

Now for the differences. Java SE 6 has a CookiePolicy which offers the CookieManager the ability to accept all cookies, accept no cookies, or only accept cookies from the original host. To setup the CookieManager with a different policy, you use one of the constants in the CookiePolicy interface: ACCEPT_ALL, ACCEPT_NONE, or ACCEPT_ORIGINAL_SERVER. The last option is the default when none is set. To configure the cookie manager, just call its setCookiePolicy method with the appropriate constant as shown here:

CookieManager manager = new CookieManager();
manager.setCookiePolicy(CookiePolicy.ACCEPT_NONE);
CookieHandler.setDefault(manager);

In addition, you can call the second constructor for CookieManager that accepts both a CookieStore and CookiePolicy argument:

CookieManager(CookieStore store, CookiePolicy cookiePolicy)

Passing in a null store will have the system use the predefined in-memory version. You can also define your own implementation of the interface if you wish to offer longer term storage of cookies.

Before showing the corrected version of the Fetch program, there is one more API difference to mention: how to get the list of cookies from the cookie jar, err..., manager. The CookieManager class has a getCookieStore method to get the CookieStore. You then ask the store for its List of cookies with the getCookies method, and can loop through the list.

Here's a modified version of the earlier program that utilizes the Java SE 6 version of the cookie handling API. While the basic program hasn't changed much, the need for all the supporting custom classes is now no longer necessary.

import java.io.\*;
import java.net.\*;
import java.util.\*;

public class Fetch {
  public static void main(String args[]) throws Exception {
    Console console = System.console();
    if (args.length == 0) {
      System.err.println("URL missing");
      System.exit(-1);
    }
    String urlString = args[0];
    CookieManager manager = new CookieManager();
    manager.setCookiePolicy(CookiePolicy.ACCEPT_ALL);
    CookieHandler.setDefault(manager);
    URL url = new URL(urlString);
    URLConnection connection = url.openConnection();
    Object obj = connection.getContent();
    url = new URL(urlString);
    connection = url.openConnection();
    obj = connection.getContent();
    CookieStore cookieJar = manager.getCookieStore();
    List cookies = cookieJar.getCookies();
    for (HttpCookie cookie: cookies) {
      console.printf("Cookie: %s%n", cookie);
    }
  }
}

Just compile and run the program to see if visiting a particular URL will leave a cookie on your system. If you don't enable ACCEPT_ALL, visiting http://www.sun.com will not show any cookies, but enabling all will show three. Your run will produce different results.

> java Fetch http://www.sun.com
Cookie: JROUTE=9999
Cookie: JSESSIONID=999999995d3f13ffffffffc68433979b7f5b0
Cookie: Starload=star-fep7

Yes, going from the J2SE 5.0 cookie handling mechanism to Java SE 6 is that easy. You don't have to implement even one additional interface if the default functionality is sufficient. For a refresher on the difficulties involved in creating the J2SE 5.0 version of the handler, be sure to revisit the earlier tip.

Be sure to try out the Tech Tips Quiz, found later in that same issue.

Comments:

Post a Comment:
Comments are closed for this entry.
About

John O'Conner

Search

Categories
Archives
« April 2014
SunMonTueWedThuFriSat
  
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
   
       
Today