Servlet - Handling Cookies

[Updated: Apr 4, 2017, Created: Apr 1, 2017]

This example demonstrates the usage of following cookies handling Servlet API:

  • HttpServletRequest#getCookies(), which returns an array containing the Cookie objects sent from a web browser.
  • HttpServletResponse#addCookie(Cookie cookie), which adds the specified cookie to the response so that the web browser can store it. A Cookie is used to remember stateful information between multiple requests or even across multiple sessions.
  • Creating a Cookie object and understanding its methods.

Following example retrieves/stores a cookie containing user selected currency pair (e.g. USD/EUR) information. It will be used to display corresponding currency exchange rate between the multiple requests.

Retrieving cookie from the request

Following servlet displays exchange rates, only if it finds the cookie which contains currency pair information; otherwise, the servlet forwards the request to a static html page for currency pair selection.

@WebServlet(name = "exchangeRatesServlet",
      urlPatterns = {"/exchange-rate"},
      loadOnStartup = 1)
public class ExchangeRatesServlet extends HttpServlet {
  static final String currencyPairKey = "currencyPair";

  @Override
  protected void doGet(HttpServletRequest req, HttpServletResponse resp)
          throws ServletException, IOException {
      Optional<Cookie> op = Arrays.stream(req.getCookies())
                                  .filter(c -> currencyPairKey.equals(c.getName()))
                                  .findAny();
      if (op.isPresent()) {
          showCurrencyRate(resp, op.get().getValue());
      } else {
          RequestDispatcher rd = req.getRequestDispatcher("/currencySelection.html");
          rd.forward(req, resp);
      }
  }

  private static void showCurrencyRate(HttpServletResponse resp, String currencyPair)
          throws IOException {
      resp.setContentType("text/html");
      PrintWriter writer = resp.getWriter();
      writer.write(String.format("<p>The exchange rate for %s = %s</p>",
              currencyPair, Math.round((Math.random() + 1) * 100)));
      writer.write("<p>Select <a href='/remove-currency-pair'>Remove currency selection</a>");
      writer.close();
  }
}

Currency selection

src/main/webapp/currencySelection.html

<html>
<p>Select your preferred currency pair</p>
<form method="post" action="/save-exchange-rates-pair">
    <input type="radio" name="currencyPair" value="USD/EUR">USD/EUR<br/>
    <input type="radio" name="currencyPair" value="USD/CAD"> USD/CAD<br/>
    <input type="radio" name="currencyPair" value="USD/AUD"> USD/AUD<br/>
    <input type="submit" value="Submit">
</form>
</html>

Creating and adding Cookie

The following servlet creates the currency pair cookie and add it to the response. The response is also redirected to the '/exchange-rate' uri which maps to our first servlet (shown above).

@WebServlet(name = "saveExchangeRatesServlet",
      urlPatterns = {"/save-exchange-rates-pair"},
      loadOnStartup = 1)
public class AddExchangeRateCookieServlet extends HttpServlet {
   static final String currencyPairKey = "currencyPair";

  @Override
  protected void doPost(HttpServletRequest req, HttpServletResponse resp)
          throws ServletException, IOException {

      String thePair = req.getParameter(currencyPairKey);
      if (thePair != null) {
          Cookie cookie = new Cookie(currencyPairKey, thePair);
          cookie.setMaxAge(30 * 24 * 60 * 60);// for 30 days
          resp.addCookie(cookie);
          //better to redirect a post request
          resp.sendRedirect("/exchange-rate");
      }
  }
}

Note that by default, the Cookie's max-age is set as -1, which means cookie is not stored persistently and will be deleted when the Web browser exits.

Following are some of the other useful methods of Cookie class:

  • setDomain(String domain): By default, cookies are only returned to the server that sent them. We may set it to use the cookies across the multiple servers in a specified DNS zone.
  • setPath(String uri): specifies the subset of URLs to which this cookie applies. Defaults to the path of the request URL.
  • setSecure(boolean flag): specifies whether the cookie should only be sent using a secure protocol, such as HTTPS or SSL. Default is false.
  • setVersion(int v): specifies a particular W3 cookie specification version. Default is 0 which is for original Netscape cookie specification. Version 1 complies with RFC 2109.
A quick note on cookie specifications

A Response cookie object is sent as 'Set-Cookie' HTTP header. This header consists of various semi-colon separated directives:

Set-Cookie: <name>=<value>;Max-Age=<value>;Path=<value>;version=<value>;Domain=<value>;Comment=<value>;Secure

Multiple cookies can be sent in separate lines of 'Set-Cookie' headers or in a single comma separated line.

A valid cookie name and value cannot have semicolon, comma, and white spaces. No standard exists, for encoding these characters. We must avoid using them for portability and to avoid unexpected results.

A Request cookie object is sent by the browser. It is nothing but 'Cookie' HTTP header. These headers are applied based on previously persisted Domain/Max-Age/Path/Secure attributes. It has the similar syntax as described above.

Deleting Cookie

To delete a cookie, we just need to add it to the response with max-age of 0 seconds.

@WebServlet(name = "removeCookieServlet",
      urlPatterns = {"/remove-currency-pair"},
      loadOnStartup = 1)
public class RemoveExchangeRateCookieServlet extends HttpServlet {

  @Override
  protected void doGet(HttpServletRequest req,
                       HttpServletResponse resp)
          throws ServletException, IOException {
      Optional<Cookie> cookieOptional = Arrays.stream(req.getCookies())
                                              .filter(c -> ExchangeRatesServlet
                                                      .currencyPairKey.equals(c.getName()))
                                              .findAny();
      if (cookieOptional.isPresent()) {
          Cookie cookie = cookieOptional.get();
          cookie.setMaxAge(0);
          resp.addCookie(cookie);
          resp.sendRedirect("/currencySelection.html");
      } else {
          resp.setContentType("text/html");
          PrintWriter writer = resp.getWriter();
          writer.write("Currency pair Cookie does not exist on the browser");
      }
  }
}

To try examples, run embedded Jetty (configured in pom.xml of example project below):

mvn jetty:run

Output

Example Project

Dependencies and Technologies Used :

  • javax.servlet-api 3.1.0 Java Servlet API
  • jetty-maven-plugin 9.4.1.v20170120: Jetty maven plugins.
  • JDK 1.8
  • Maven 3.3.9

Servlet Cookie Example Select All Download
  • servlet-cookie-examples
    • src
      • main
        • java
          • com
            • logicbig
              • example
        • webapp

See Also