The Java TM Tutorial

| Start of Tutorial > Start of Trail > Start of Lesson | Search

Trail: Servlets
Lesson: Saving Client State

## Using Cookies

> Cookies are a way for a server (or a servlet, as part of a server) to send some information to a client to store, and for the server to later retrieve its data from that client. Servlets send cookies to clients by adding fields to HTTP response headers. Clients automatically return cookies by adding fields to HTTP request headers.

> Each HTTP request and response header is named and has a single value. For example, a cookie could be a header named `BookToBuy` with a value `304qty1`, indicating to the calling application that the user wants to buy one copy of the book with stock number 304. (Cookies and their values are application-specific.)

> Multiple cookies can have the same name. For example, a servlet could send two cookies with headers named `BookToBuy`; one could have the value shown previously, `304qty1`, while the other could have a value `301qty3`. These cookies would indicate that the user wants to buy one copy of the book with stock number 304, and three copies of the book with stock number 301.

> In addition to a name and a value, you can also provide optional attributes such as comments. Current web browsers do not always treat the optional attributes correctly, so you should not rely on them.

> A server can provide one or more cookies to a client. Client software, such as a web browser, is expected to support twenty cookies per host, of at least four kilobytes each

> When you send a cookie to a client, standard HTTP/1.0 caches will not cache the page. Currently, the `javax.servlet.http.Cookie` does not support HTTP/1.1 cache control models.

> Cookies that a client stores for a server are returned by the client to that server and only that server. A server can contain multiple servlets; the Duke's Bookstore example is made up of multiple servlets running within a single server. Because cookies are returned to a server, servlets running within a server share cookies. The examples in this section illustrate this by showing the `CatalogServlet` and `ShowCart` servlet working with the same cookies.

> > Note: This section shows code that is not a part of the Duke's Bookstore example. Duke's Bookstore could use code like that shown in this lesson if it used cookies instead of session tracking to keep track of the client's book order. Because cookies are not a part of Duke's Bookstore, think of the examples in this section as pseudo-code.

> To send a cookie,

> 1. Instantiate a `Cookie` object
> 2. Set any attributes
> 3. Send the cookie

> To get information from a cookie,

> 1. Retrieve all the cookies from the user's request
> 2. Find the cookie or cookies with the name that you are interested in, using standard programming techniques
> 3. Get the values of the cookies that you found

### Creating a Cookie

The constructor for the`javax.servlet.http.Cookie` class creates a cookie with an initial name and value. You can change the value of the cookie later with its `setValue` method.

The name of the cookie must be an HTTP/1.1 token. Tokens are strings that contain none of the special characters listed in RFC 2068. (Alphanumeric strings qualify as tokens.) In addition, names that start with the dollar-sign character ("`$`") are reserved by RFC 2109.

The value of the cookie can be any string, though null values are not guaranteed to work the same way on all browsers. In addition, if you are sending a cookie that complies with Netscape's original cookie specification, do not use whitespace or any of these characters:

> `[ ] ( ) = , " / ? @ : ;`

If your servlet returns a response to the user with a `Writer`, create the cookie before accessing the `Writer`. (Because cookies are sent to the client as a header, and headers must be written before accessing the `Writer`.)

If the `CatalogServlet` used cookies to keep track of a client's book order, the servlet could create cookies like this:

        public void doGet (HttpServletRequest request,
                           HttpServletResponse response)
    	throws ServletException, IOException
        {
            // Check for pending adds to the shopping cart
            String bookId = request.getParameter("Buy");

            //If the user wants to add a book, remember it by adding a cookie
            if (bookId != null) {
                Cookie getBook = new Cookie("Buy", bookId);
                ...
            }

    	// set content-type header before accessing the Writer
            response.setContentType("text/html");

            // now get the writer and write the data of the response
    	PrintWriter out = response.getWriter();
            out.println("<html>" +
                        "<head><title> Book Catalog </title></head>" + ...);
            ...
        }

### Setting Cookie Attributes

The `Cookie` class provides a number of methods for setting a cookie's values and attributes. Using these methods is straightforward; they are explained in the javadoc for `Cookie` class.

The following example sets the comment field of the `CatalogServlet`'s cookie. The comment field describes the purpose of the cookie.

        public void doGet (HttpServletRequest request,
                           HttpServletResponse response)
    	throws ServletException, IOException
        {
            ...
            //If the user wants to add a book, remember it by adding a cookie
            if (values != null) {
                bookId = values[0];
                Cookie getBook = new Cookie("Buy", bookId);
                getBook.setComment("User wants to buy this book " +
                                   "from the bookstore.");
            }
            ...
        }

You can also set the maximum age of the cookie. This attribute is useful, for example, for deleting a cookie. Once again, if Duke's Bookstore kept track of a user's order with cookies, the example would use this attribute to delete a book from the user's order. The user removes a book from the shopping cart in the `ShowCartServlet`; its code would look something like this:

        public void doGet (HttpServletRequest request,
                           HttpServletResponse response)
    	throws ServletException, IOException
        {
    	...
            /* Handle any pending deletes from the shopping cart */
            String bookId = request.getParameter("Remove");
            ...
            if (bookId != null) {
                // Find the cookie that pertains to the book to remove
                ...
                        // Delete the cookie by setting its maximum age to zero
                        thisCookie.setMaxAge(0);
                ...
            }

    	// also set content type header before accessing the Writer
            response.setContentType("text/html");
            PrintWriter out = response.getWriter();

            //Print out the response
            out.println("<html> <head>" +
                        "<title>Your Shopping Cart</title>" + ...);

### Sending the Cookie

Cookies are sent as headers of the response to the client; they are added with the `addCookie` method of the `HttpServletResponse` class. If you are using a `Writer` to return text data to the client, you must call the `addCookie` method before calling the `HttpServletResponse`'s `getWriter` method.

Continuing the example of the `CatalogServlet`, the following is code for sending the cookie:

        public void doGet (HttpServletRequest request,
                           HttpServletResponse response)
    	throws ServletException, IOException
        {
            ...
            //If the user wants to add a book, remember it by adding a cookie
            if (values != null) {
                bookId = values[0];
                Cookie getBook = new Cookie("Buy", bookId);
                getBook.setComment("User has indicated a desire " +
                                   "to buy this book from the bookstore.");
                response.addCookie(getBook);
            }
            ...
        }

### Retrieving Cookies

Clients return cookies as fields added to HTTP request headers. To retrieve any cookie, you must retrieve all the cookies using the `getCookies` method of the `HttpServletRequest` class.

The `getCookies` method returns an array of `Cookie` objects, which you can search to find the cookie or cookies that you want. (Remember that multiple cookies can have the same name. To get the name of a cookie, use its `getName` method.)

To continue the `ShowCartServlet` example:

        public void doGet (HttpServletRequest request,
                           HttpServletResponse response)
    	throws ServletException, IOException
        {
    	...

            /* Handle any pending deletes from the shopping cart */
            String bookId = request.getParameter("Remove");
            ...
            if (bookId != null) {

                // Find the cookie that pertains to the book to remove
                Cookie[] cookies = request.getCookies();
                ...

                // Delete the book's cookie by setting its maximum age to zero
                thisCookie.setMaxAge(0);
            }

    	// also set content type header before accessing the Writer
            response.setContentType("text/html");
            PrintWriter out = response.getWriter();

            //Print out the response
            out.println("<html> <head>" +
                        "<title>Your Shopping Cart</title>" + ...);

### Getting the Value of a Cookie

To find the value of a cookie, use its `getValue` method. To continue the `ShowCartServlet` example:

        public void doGet (HttpServletRequest request,
                           HttpServletResponse response)
    	throws ServletException, IOException
        {
            ...
            /* Handle any pending deletes from the shopping cart */
            String bookId = request.getParameter("Remove");
            ...
            if (bookId != null) {
                // Find the cookie that pertains to that book
                Cookie[] cookies = request.getCookies();
                for(i=0; i < cookies.length; i++) {
                    Cookie thisCookie = cookie[i];
                    if (thisCookie.getName().equals("Buy") &&
                        thisCookie.getValue().equals(bookId)) {

                        // Delete the cookie by setting its maximum age to zero
                        thisCookie.setMaxAge(0);
                    }
                }
            }

    	// also set content type header before accessing the Writer
            response.setContentType("text/html");
            PrintWriter out = response.getWriter();

            //Print out the response
            out.println("<html> <head>" +
                        "<title>Your Shopping Cart</title>" + ...);

| Start of Tutorial > Start of Trail > Start of Lesson | Search