- The Expires header or a response which tells the browser that it doesn’t need to request the resource or even check back before the expiration date
- The Etag header which associates an ID or checksum with a resource. Once a browser knows about the Etag associated with a resource, it can request that resource by passing the last known Etag along with the request. The server may then use that information to tell the browser that the resource has not changed.
interface GeoService{ String[] getListOfPlaces(String countryCode); double[] getGeoCoordinatesForPlace(String placeCode); }
interface GeoServiceAsync{ void getListOfPlaces(String countryCode, AsyncCallback callback); double[] getGeoCoordinatesForPlace(String placeCode, AsyncCallback callback); }
- The client needs to send RPC requests as an Http GET and the service parameters as URL query parameters
- The server needs to accept GET requests instead of POST requests
1. Changing a request to GET involves setting up the client proxy of the service with a custom request builder. Since your service will probably have both methods that you want to cache and methods you don’t want to cache, you should either maintain a separate instance of the service proxy for each occasion or implement a smart switch within the request builder.
public void getGeoCoordinates(final String placeCode, final AsyncCallback callback){ ((ServiceDefTarget)geoService).setRpcRequestBuilder(new RpcRequestBuilder(){ @Override protected RequestBuilder doCreate(String serviceEntryPoint) { return new RequestBuilder(RequestBuilder.GET, "/myapp/geoservice?placecode="+placeCode); } }); geoService.read(placeCode, callback); }
Note that the service interface obviously doesn’t change, so we need to pass the request arguments to the read() method and the request payload will be constructed anyway – only that it will not be used as the request builder will ignore it.
2. Preparing the server for GET requests
GWT’s RemoteServiceServlet will reject any attempts to contact it via GET, so you will need to bypass it and write your own servlet or controller (when talking about Spring):
public void doPost(HttpServletRequest request, HttpServletResponse response) throws Exception{ String placeCode = request.getParameter("placecode"); Method method = geoService.getClass().getMethod("read", new Class[]{String.class}); double[] coordinates = geoService.read(placeCode); String sPayload = RPC.encodeResponseForSuccess(method, coordinates); byte[] payload; payload = sPayload.getBytes("utf-8"); response.setHeader("Content-Disposition", "attachment"); response.setContentType("application/json;charset=utf-8"); response.setContentLength(payload.length); ServletOutputStream stream = response.getOutputStream(); stream.write(payload); }
At this point you might want to add further details like an Etag header, expiration dates (and handling for requests that carry them), gzip compression of the response payload etc.