net.sf.ehcache.constructs.web.filter
Class SimpleCachingHeadersPageCachingFilter

java.lang.Object
  extended by net.sf.ehcache.constructs.web.filter.Filter
      extended by net.sf.ehcache.constructs.web.filter.CachingFilter
          extended by net.sf.ehcache.constructs.web.filter.SimplePageCachingFilter
              extended by net.sf.ehcache.constructs.web.filter.SimpleCachingHeadersPageCachingFilter
All Implemented Interfaces:
javax.servlet.Filter

public class SimpleCachingHeadersPageCachingFilter
extends SimplePageCachingFilter

This Filter extends SimplePageCachingFilter, adding support for the HTTP cache headers: ETag, Last-Modified and Expires.

Because browsers and other HTTP clients have the expiry information returned in the response headers, they do not even need to request the page again. Even once the local browser copy has expired, the browser will do a conditional GET.

So why would you ever want to use SimplePageCachingFilter, which does not set these headers? Because in some caching scenarios you may wish to remove a page before its natural expiry. Consider a scenario where a web page shows dynamic data. Under ehcache the Element can be removed at any time. However if a browser is holding expiry information, those browsers will have to wait until the expiry time before getting updated. The caching in this scenario is more about defraying server load rather than minimising browser calls.

It uses a Singleton CacheManager created with the default factory method. Override to use a different CacheManager

The meaning of page is:

For jsp:included page fragme?nts see SimplePageFragmentCachingFilter.

calculateKey

Pages are cached based on their key. The key for this cache is the URI followed by the query string. An example is /admin/SomePage.jsp?id=1234&name=Beagle.

This key technique is suitable for a wide range of uses. It is independent of hostname and port number, so will work well in situations where there are multiple domains which get the same content, or where users access based on different port numbers.

A problem can occur with tracking software such as Google AdWords, where unique ids are inserted into request query strings. Because each request generates a unique key, there will never be a cache hit. For these situations it is better to override SimplePageCachingFilter.calculateKey(javax.servlet.http.HttpServletRequest) with an implementation that takes account of only the significant parameters.

Configuring the cacheName

A cache entry in ehcache.xml should be configured with the name of the filter.

Names can be set using the init-param cacheName, or by sub-classing this class and overriding the name.

Concurent Cache Misses

A cache miss will cause the filter chain, upstream of the caching filter to be processed. To avoid threads requesting the same key to do useless duplicate work, these threads block behind the first thread.

The thead timeout can be set to fail after a certain wait by setting the init-param blockingTimeoutMillis. By default threads wait indefinitely. In the event upstream processing never returns, eventually the web server may get overwhelmed with connections it has not responded to. By setting a timeout, the waiting threads will only block for the set time, and then throw a LockTimeoutException. Under either scenario an upstream failure will still cause a failure.

Gzipping

Significant network efficiencies can be gained by gzipping responses.

Whether a response can be gzipped depends on:

Responses are automatically gzipped and stored that way in the cache. For requests which do not accept gzip encoding the page is retrieved from the cache, ungzipped and returned to the user agent. The ungzipping is high performance.

Caching Headers

This filter sets the HTTP cache headers: ETag, Last-Modified and Expires. It supports conditional GET.

Because browsers and other HTTP clients have the expiry information returned in the response headers, they do not even need to request the page again. Even once the local browser copy has expired, the browser will do a conditional GET.

So why would you ever want to use SimplePageCachingFilter, which does not set these headers? The answer is that in some caching scenarios you may wish to remove a page before its natural expiry. Consider a scenario where a web page shows dynamic data. Under ehcache the Element can be removed at any time. However if a browser is holding expiry information, those browsers will have to wait until the expiry time before getting updated. The caching in this scenario is more about defraying server load rather than minimising browser calls.

Init-Params

The following init-params are supported:
  1. cacheName - the name in ehcache.xml used by the filter.
  2. blockingTimeoutMillis - the time, in milliseconds, to wait for the filter chain to return with a response on a cache miss. This is useful to fail fast in the event of an infrastructure failure.

Reentrance

Care should be taken not to define a filter chain such that the same CachingFilter class is reentered. The CachingFilter uses the BlockingCache. It blocks until the thread which did a get which results in a null does a put. If reentry happens a second get happens before the first put. The second get could wait indefinitely. This situation is monitored and if it happens, an IllegalStateException will be thrown.

Author:
Craig Andrews, Greg Luck
See Also:
SimplePageCachingFilter

Field Summary
static java.lang.String NAME
          The name of the filter.
 
Fields inherited from class net.sf.ehcache.constructs.web.filter.SimplePageCachingFilter
DEFAULT_CACHE_NAME
 
Fields inherited from class net.sf.ehcache.constructs.web.filter.CachingFilter
blockingCache, cacheName
 
Fields inherited from class net.sf.ehcache.constructs.web.filter.Filter
exceptionsToLogDifferently, filterConfig, NO_FILTER, suppressStackTraces
 
Constructor Summary
SimpleCachingHeadersPageCachingFilter()
           
 
Method Summary
protected  PageInfo buildPage(javax.servlet.http.HttpServletRequest request, javax.servlet.http.HttpServletResponse response, javax.servlet.FilterChain chain)
          Builds the PageInfo object by passing the request along the filter chain
protected  long calculateTimeToLiveMilliseconds()
          Get the time to live for a page, in milliseconds
protected  HttpDateFormatter getHttpDateFormatter()
           
protected  void writeResponse(javax.servlet.http.HttpServletRequest request, javax.servlet.http.HttpServletResponse response, PageInfo pageInfo)
          Writes the response from a PageInfo object.
 
Methods inherited from class net.sf.ehcache.constructs.web.filter.SimplePageCachingFilter
calculateKey, getCacheManager, getCacheName
 
Methods inherited from class net.sf.ehcache.constructs.web.filter.CachingFilter
buildPageInfo, checkNoReentry, doDestroy, doFilter, doInit, setCacheNameIfAnyConfigured, setContentType, setCookies, setHeaders, setStatus, writeContent
 
Methods inherited from class net.sf.ehcache.constructs.web.filter.Filter
acceptsEncoding, acceptsGzipEncoding, destroy, doFilter, filterNotDisabled, getFilterConfig, init, logRequestHeaders, processInitParams
 
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
 

Field Detail

NAME

public static final java.lang.String NAME
The name of the filter. This should match a cache name in ehcache.xml

See Also:
Constant Field Values
Constructor Detail

SimpleCachingHeadersPageCachingFilter

public SimpleCachingHeadersPageCachingFilter()
Method Detail

buildPage

protected PageInfo buildPage(javax.servlet.http.HttpServletRequest request,
                             javax.servlet.http.HttpServletResponse response,
                             javax.servlet.FilterChain chain)
                      throws AlreadyGzippedException,
                             java.lang.Exception
Builds the PageInfo object by passing the request along the filter chain

The following headers are set:

Any of these headers aleady set in the response are ignored, and new ones generated. To control your own caching headers, use SimplePageCachingFilter.

Overrides:
buildPage in class CachingFilter
Parameters:
request -
response -
chain -
Returns:
a Serializable value object for the page or page fragment
Throws:
AlreadyGzippedException - if an attempt is made to double gzip the body
java.lang.Exception

getHttpDateFormatter

protected final HttpDateFormatter getHttpDateFormatter()
Returns:
A lazily created HttpDateFormatter instance scoped to this filter

writeResponse

protected void writeResponse(javax.servlet.http.HttpServletRequest request,
                             javax.servlet.http.HttpServletResponse response,
                             PageInfo pageInfo)
                      throws java.io.IOException,
                             java.util.zip.DataFormatException,
                             ResponseHeadersNotModifiableException
Writes the response from a PageInfo object. This method actually performs the conditional GET and returns 304 if not modified, short-circuiting the normal writeResponse.

Indeed, if the short cicruit does not occur it calls the super method.

Overrides:
writeResponse in class CachingFilter
Throws:
java.io.IOException
java.util.zip.DataFormatException
ResponseHeadersNotModifiableException

calculateTimeToLiveMilliseconds

protected long calculateTimeToLiveMilliseconds()
Get the time to live for a page, in milliseconds

Returns:
time to live in milliseconds


Copyright ? 2003-2010 Terracotta, Inc.. All Rights Reserved.