Friday, November 9, 2012

Cache Control using RESTfull Web Service


Caching is one of the most important features of web.Web caching is a mechanism for storing web document  like images, text etc. in memory and on local disk, to avoid reload of data on network. This greatly speeds up the rendering of revisited page and cut down the server loads.

In this post, we will be learning about caching in JAX-RS web service.
So any URI that can be reached with an  HTTP GET is a candidate for caching as they are read only and idempotent.


The HTTP protocol defines a rich set of built-in caching semantics. You can control the caching behavior by exchanging request and response header defined by HTTP protocol.
HTTP1.0 defines a simple header response called Expires which tells the browser that it can cache data and for how long.
The value of this header is a date in future. After reaching the date, browser does not use cache data and retrieve data from server.

HTTP/1.1 200 OK
Content-Type: application/xml
Expires: Mon, 29 Oct 2012 16:00 GMT

The cached XML data is valid until Monday, 29 October 2012 16:00 GMT.
We can achieve it using the following excerpt in our web service implementation class


ResponseBuilder responseBuilder = Response.ok(employeeDTO, MediaType.APPLICATION_JSON);
Calendar calendar = Calendar.getInstance();
calendar.set(2012, 10, 29, 16, 0);
responseBuilder.expires(calendar.getInstance().getTime());

Cache Control

HTTP1.1 specification introduced much richer semantics and control over browser caching. Expires header  was  deprecated in HTTP1.1 specification and Cache-Control header was introduced. w3
Unlike Expires having date, Cache-Control has set of directives which define who can cache, how and how long etc. as described below. Click here for details

Private : Only client can cache the data. No shared intermediately is allowed to cache data.
Public : Response can be cached by any entity within request/response chain.
no-cache : Response should not be cached. If cached, data should be validated with server
no-store : No response storage on disk
max-age : Defines how long cached data is valid

Example
This response is valid for 300 seconds and must not be stored on disk.

HTTP/1.1 200 OK
Content-Type: application/xml
Cache-Control: private, no-store, max-age=300

The JAX-RS specification provides javax.ws.rs.core.CacheControl, a simple class to represent the Cache-Control header. The  ResponseBuilder  class  has  a  method  called  cacheControl()  that  can  accept  a CacheControl object.


We will modify our previous post code to demonstrate the cache-control usage. So we have one interface and class which implements the interface.
All other sections of the application will be same as our previous post : REST Web Service


HelloWorldRestService.java
package com.sarf.service;

import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;

@Path("/hello-service/")
@Produces(MediaType.TEXT_PLAIN)
public interface HelloWorldRestService {
     @GET
     @Path("/hello")
     @Produces(MediaType.TEXT_PLAIN)
     public Response sayHello();
 }


HelloWorldRestServiceImpl.java
package com.sarf.service;

import java.io.IOException;
import java.net.URI;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

import javax.servlet.http.HttpServletResponse;
import javax.ws.rs.core.CacheControl;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Request;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.ResponseBuilder;
import javax.ws.rs.core.Response.Status;
import javax.ws.rs.core.UriInfo; 

public class HelloWorldRestServiceImpl implements HelloWorldRestService{
   public HelloWorldRestServiceImpl() {}

    @Override
    public Response sayHello() {
     System.out.println("Calling rest service at "+new Date());
     ResponseBuilder responseBuilder = Response.ok("Hello World");
  CacheControl cc = new CacheControl();
  cc.setMaxAge(30);
  cc.setPrivate(true);
  cc.setNoStore(true);
  responseBuilder.cacheControl(cc);
  return responseBuilder.build();
    }
}

So in this implementation class, we have introduced   javax.ws.rs.core.CacheControl [doc] to set Cache-Control response header.



How to verify
Build the application after taking the other part of the code from previous REST Web Service post and deploy it in Application server.
Type the following URL : http://localhost:8080/Test1/index.jsp
Click on  Say Hello link
Check the console :
You should see one line printing the value "Calling rest service at <DateTime>"
Click again on Say Hello link,  the above console statement will not get printed.
After 30 seconds, click on Say Hello link,  You should see one line printing the value "Calling rest service at <DateTime>" again on the console.