Is it somehow possible to define cache control level for each resource?
Is there some annotation i could put on top of each Resource class so to specify cache control in a custom way?
To solve this issue I ended up defining an @Cache
aspect. There are a couple of caveats that I ran into:
The cached method needs to return a Response
object (not POJOs) so that the aspect can modify the headers.
If you want to use ETags then the class containing the method (or the method arguments themselves) needs to expose the @Request
so that the aspect can inspect the incoming tag.
Make sure that your method arguments combined with your method name will in fact create unique keys. Another catch here is response type. The client may issue two requests with identical parameters but different response types.
You could easily add options to the aspect to control max-age
and other parameters on a per-method basis.
Here's my invoke
method:
@Override
public Object invoke(MethodInvocation invocation) throws Throwable {
if (Response.class != invocation.getMethod().getReturnType()) {
logger.warning(String.format("%s is @Cachable but does not return a Response object", invocation.getMethod()));
return invocation.proceed();
}
Optional<Request> request = getRequest(invocation);
if (!request.isPresent()) {
logger.warning(String.format("%s is @Cachable but does not declare a public Request field named \"request\"", invocation.getMethod()));
return invocation.proceed();
}
Object response = super.invoke(invocation);
EntityTag responseTag = JaxRsUtil.getEntityTag(response);
Response.ResponseBuilder builder = request.get().evaluatePreconditions(responseTag);
if (null != builder) {
logger.finer("Found matching etag: " + responseTag);
return builder.build();
}
CacheControl cc = new CacheControl();
cc.setMaxAge(maxAge);
builder = Response.fromResponse((Response)response).tag(responseTag).cacheControl(cc);
return builder.build();
}