So, I'm running a REST backend using Jersey to serve geolocation data in multiple formats (XML and JSON). Here is the stub of the service
Code:
@Path("/map")
public class MapDataService implements MapData {
@GET
@Path("buildings")
@Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
public Response getCampusList(@Context Request request) {
.....
return ....
}
}
The data is served in XML ( default ) or JSON format based on the access header in the HTTP request ( JAX-RS does the conversion automatically ).
I want to cache the endpoint URLs for the GET requests as building the geolocation data is i/o heavy. However, hacache by default doesn't take the accept header of the request into account and the cache key just uses the request URL.
I've solved this issue already by creating a custom page caching filter and overriding the caclulateKey method....
CustomHeadersPageCachingFilter
Code:
/**
* Embed access header in cache key if JSON request
*/
public class CustomHeadersPageCachingFilter extends
SimpleCachingHeadersPageCachingFilter {
protected static final String appJSONKey="application/json";
protected static final String textJSKey="text/javascript";
protected String calculateKey(HttpServletRequest httpRequest) {
StringBuffer stringBuffer = new StringBuffer();
stringBuffer.append(httpRequest.getMethod())
.append(httpRequest.getRequestURI())
.append(httpRequest.getQueryString());
String acceptHeader = httpRequest.getHeader( "Accept" );
if ( acceptHeader != null ) {
String[] acceptHeaders = acceptHeader.split(",");
if ( Arrays.asList(acceptHeaders).contains( appJSONKey ) || Arrays.asList(acceptHeaders).contains( textJSKey ) ) {
stringBuffer.append("[" + appJSONKey + "]");
}
}
String key = stringBuffer.toString();
return key;
}
}
web.xml
Code:
<filter>
<filter-name>MapRESTServicesCachingFilter</filter-name>
<filter-class>my.domain.com.CustomHeadersPageCachingFilter</filter-class>
<init-param>
<param-name>suppressStackTraces</param-name>
<param-value>false</param-value>
</init-param>
<init-param>
<param-name>cacheName</param-name>
<param-value>MapRESTServicesCache</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>MapRESTServicesCachingFilter</filter-name>
<url-pattern>/rest/map/*</url-pattern>
</filter-mapping>
I'm a relative noob at this. Hope this is the correct way to handle this situation.