While writing a RESTful web service, I am encountering issues if I enable any sort of caching on my client (currently a .NET thick client). By default Jersey is not sending any sort of cache control header, so the client is caching most pages automatically (which seems to be valid behaviour).
I would like to have Jersey by default send a cache control of "no-cache", and then in particular responses override the cache control.
Is there any way to do this with Jersey?
I've found that RESTeasy has the ability to use the @NoCache annotation to specify the setting for the whole class, but I've not found anything similar with Jersey.
The directive CACHE-CONTROL:NO-CACHE indicates cached information should not be used and instead requests should be forwarded to the origin server. This directive has the same semantics as the PRAGMA:NO-CACHE.
Add an Expires or a Cache-Control header in JSP HttpServletResponse httpResponse = (HttpServletResponse) response; httpResponse. setHeader("Cache-Control", "no-cache, no-store, must-revalidate"); // HTTP 1.1 httpResponse. setHeader("Pragma", "no-cache"); // HTTP 1.0 httpResponse.
Cache-Control: No-Store The no-store directive means browsers aren't allowed to cache a response and must pull it from the server each time it's requested. This setting is usually used for sensitive data, such as personal banking details.
Cache-control is an important way by which developers can dictate how resources will be cached when a user browses the internet. Without cache-control, the browser caching and the resulting experience for the user will be sub-optimal.
This is easy with Jersey by using a ResourceFilterFactory - you can create any custom annotation you attach to your methods to set cache control settings. ResourceFilterFactories get called for each discovered resource method when the application initializes - in your ResourceFilterFactory you can check if the method has your @CacheControlHeader annotation (or whatever you want to call it) - if not, simply return response filter that adds "no-cache" directive to the response, otherwise it should use the settings from the annotation. Here is an example of how to do that:
public class CacheFilterFactory implements ResourceFilterFactory { private static final List<ResourceFilter> NO_CACHE_FILTER = Collections.<ResourceFilter>singletonList(new CacheResponseFilter("no-cache")); @Override public List<ResourceFilter> create(AbstractMethod am) { CacheControlHeader cch = am.getAnnotation(CacheControlHeader.class); if (cch == null) { return NO_CACHE_FILTER; } else { return Collections.<ResourceFilter>singletonList(new CacheResponseFilter(cch.value())); } } private static class CacheResponseFilter implements ResourceFilter, ContainerResponseFilter { private final String headerValue; CacheResponseFilter(String headerValue) { this.headerValue = headerValue; } @Override public ContainerRequestFilter getRequestFilter() { return null; } @Override public ContainerResponseFilter getResponseFilter() { return this; } @Override public ContainerResponse filter(ContainerRequest request, ContainerResponse response) { // attache Cache Control header to each response based on the annotation value response.getHttpHeaders().putSingle(HttpHeaders.CACHE_CONTROL, headerValue); return response; } } }
The annotation can look like this:
@Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) public @interface CacheControlHeader { String value(); }
The ResourceFilterFactory can be registered in your application by adding the following init param to the definition of Jersey servlet in web.xml:
<init-param> <param-name>com.sun.jersey.spi.container.ResourceFilters</param-name> <param-value>package.name.CacheFilterFactory</param-value> </init-param>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With