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

java.lang.Object
  extended by net.sf.ehcache.constructs.web.filter.Filter
      extended by net.sf.ehcache.constructs.web.filter.CachingFilter
All Implemented Interfaces:
javax.servlet.Filter
Direct Known Subclasses:
PageFragmentCachingFilter, SimplePageCachingFilter

public abstract class CachingFilter
extends Filter

An abstract CachingFilter.

This class should be sub-classed for each page to be cached.

The filters must be declared in the web.xml deployment descriptor. Then a mapping from a web resource, such as a JSP Page, FreeMarker page, Velocity page, Servlet or static resouce needs to be defined. Finally, a succession of mappings can be used to create a filter chain. See SRV.6 of the Servlet 2.3 specification for more details.

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.

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.

Author:
@author Greg Luck

Field Summary
protected  net.sf.ehcache.constructs.blocking.BlockingCache blockingCache
          The cache holding the web pages.
protected  String cacheName
          The cache name can be set through init parameters.
 
Fields inherited from class net.sf.ehcache.constructs.web.filter.Filter
exceptionsToLogDifferently, filterConfig, NO_FILTER, suppressStackTraces
 
Constructor Summary
CachingFilter()
           
 
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  PageInfo buildPageInfo(javax.servlet.http.HttpServletRequest request, javax.servlet.http.HttpServletResponse response, javax.servlet.FilterChain chain)
          Build page info either using the cache or building the page directly.
protected abstract  String calculateKey(javax.servlet.http.HttpServletRequest httpRequest)
          CachingFilter works off a key.
protected  void checkNoReentry(javax.servlet.http.HttpServletRequest httpRequest)
          Check that this caching filter is not being reentered by the same recursively.
protected  void doDestroy()
          Destroys the filter.
protected  void doFilter(javax.servlet.http.HttpServletRequest request, javax.servlet.http.HttpServletResponse response, javax.servlet.FilterChain chain)
          Performs the filtering for a request.
 void doInit(javax.servlet.FilterConfig filterConfig)
          Initialises blockingCache to use.
protected abstract  net.sf.ehcache.CacheManager getCacheManager()
          Gets the CacheManager for this CachingFilter.
protected  String getCacheName()
          A meaningful name representative of the JSP page being cached.
protected  void setCacheNameIfAnyConfigured(javax.servlet.FilterConfig filterConfig)
          Sets the cacheName from the filterConfig
protected  void setContentType(javax.servlet.http.HttpServletResponse response, PageInfo pageInfo)
          Set the content type.
protected  void setCookies(PageInfo pageInfo, javax.servlet.http.HttpServletResponse response)
          Set the serializableCookies
protected  void setHeaders(PageInfo pageInfo, boolean requestAcceptsGzipEncoding, javax.servlet.http.HttpServletResponse response)
          Set the headers in the response object, excluding the Gzip header
protected  void setStatus(javax.servlet.http.HttpServletResponse response, PageInfo pageInfo)
          Status code
protected  void writeContent(javax.servlet.http.HttpServletRequest request, javax.servlet.http.HttpServletResponse response, PageInfo pageInfo)
          Writes the response content.
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.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

cacheName

protected String cacheName
The cache name can be set through init parameters. If it is set it is stored here.


blockingCache

protected net.sf.ehcache.constructs.blocking.BlockingCache blockingCache
The cache holding the web pages. Ensure that all threads for a given cache name are using the same instance of this.

Constructor Detail

CachingFilter

public CachingFilter()
Method Detail

doInit

public void doInit(javax.servlet.FilterConfig filterConfig)
            throws net.sf.ehcache.CacheException
Initialises blockingCache to use. The BlockingCache created by this method does not have a lock timeout set.

A timeout can be appled using blockingCache.setTimeoutMillis(int timeout) and takes effect immediately for all new requests

Specified by:
doInit in class Filter
Parameters:
filterConfig - this filter's configuration.
Throws:
net.sf.ehcache.CacheException - The most likely cause is that a cache has not been configured in ehcache's configuration file ehcache.xml for the filter name

setCacheNameIfAnyConfigured

protected void setCacheNameIfAnyConfigured(javax.servlet.FilterConfig filterConfig)
Sets the cacheName from the filterConfig


doDestroy

protected void doDestroy()
Destroys the filter.

Specified by:
doDestroy in class Filter

doFilter

protected void doFilter(javax.servlet.http.HttpServletRequest request,
                        javax.servlet.http.HttpServletResponse response,
                        javax.servlet.FilterChain chain)
                 throws AlreadyGzippedException,
                        AlreadyCommittedException,
                        FilterNonReentrantException,
                        net.sf.ehcache.constructs.blocking.LockTimeoutException,
                        Exception
Performs the filtering for a request. This method caches based responses keyed by calculateKey(javax.servlet.http.HttpServletRequest)

By default this method will queue requests requesting the page response for a given key until the first thread in the queue has completed. The request which occurs when the page expires incurs the cost of waiting for the downstream processing to return the respone.

The maximum time to wait can be configured by setting setTimeoutMillis on the underlying BlockingCache.

Specified by:
doFilter in class Filter
Parameters:
request -
response -
chain -
Throws:
AlreadyGzippedException - if a double gzip is attempted
AlreadyCommittedException - if the response was committed on the way in or the on the way back
FilterNonReentrantException - if an attempt is made to reenter this filter in the same request.
net.sf.ehcache.constructs.blocking.LockTimeoutException - if this request is waiting on another that is populating the cache entry and timeouts while waiting. Only occurs if the BlockingCache has a timeout set.
Exception - for all other exceptions. They will be caught and logged in Filter.doFilter(javax.servlet.ServletRequest, javax.servlet.ServletResponse, javax.servlet.FilterChain)

buildPageInfo

protected PageInfo buildPageInfo(javax.servlet.http.HttpServletRequest request,
                                 javax.servlet.http.HttpServletResponse response,
                                 javax.servlet.FilterChain chain)
                          throws Exception
Build page info either using the cache or building the page directly.

Some requests are for page fragments which should never be gzipped, or for other pages which are not gzipped.

Throws:
Exception

buildPage

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

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
Exception

writeResponse

protected void writeResponse(javax.servlet.http.HttpServletRequest request,
                             javax.servlet.http.HttpServletResponse response,
                             PageInfo pageInfo)
                      throws IOException,
                             DataFormatException,
                             ResponseHeadersNotModifiableException
Writes the response from a PageInfo object.

Headers are set last so that there is an opportunity to override

Parameters:
request -
response -
pageInfo -
Throws:
IOException
DataFormatException
ResponseHeadersNotModifiableException

setContentType

protected void setContentType(javax.servlet.http.HttpServletResponse response,
                              PageInfo pageInfo)
Set the content type.

Parameters:
response -
pageInfo -

setCookies

protected void setCookies(PageInfo pageInfo,
                          javax.servlet.http.HttpServletResponse response)
Set the serializableCookies

Parameters:
pageInfo -
response -

setStatus

protected void setStatus(javax.servlet.http.HttpServletResponse response,
                         PageInfo pageInfo)
Status code

Parameters:
response -
pageInfo -

setHeaders

protected void setHeaders(PageInfo pageInfo,
                          boolean requestAcceptsGzipEncoding,
                          javax.servlet.http.HttpServletResponse response)
Set the headers in the response object, excluding the Gzip header

Parameters:
pageInfo -
requestAcceptsGzipEncoding -
response -

getCacheName

protected String getCacheName()
A meaningful name representative of the JSP page being cached.

The cacheName field is be set by the doInit method. Override to control the name used. The significance is that the name is used to find a cache configuration in ehcache.xml

Returns:
the name of the cache to use for this filter.

getCacheManager

protected abstract net.sf.ehcache.CacheManager getCacheManager()
Gets the CacheManager for this CachingFilter. It is therefore up to subclasses what CacheManager to use.

This method was introduced in ehcache 1.2.1. Older versions used a singleton CacheManager instance created with the default factory method.

Returns:
the CacheManager to be used
Since:
1.2.1

calculateKey

protected abstract String calculateKey(javax.servlet.http.HttpServletRequest httpRequest)
CachingFilter works off a key.

The key should be unique. Factors to consider in generating a key are:

Implementers should differentiate between GET and HEAD requests otherwise blank pages can result. See SimplePageCachingFilter for an example implementation.

Parameters:
httpRequest -
Returns:
the key, generally the URL plus request parameters

writeContent

protected void writeContent(javax.servlet.http.HttpServletRequest request,
                            javax.servlet.http.HttpServletResponse response,
                            PageInfo pageInfo)
                     throws IOException,
                            ResponseHeadersNotModifiableException
Writes the response content. This will be gzipped or non gzipped depending on whether the User Agent accepts GZIP encoding.

If the body is written gzipped a gzip header is added.

Parameters:
response -
pageInfo -
Throws:
IOException
ResponseHeadersNotModifiableException

checkNoReentry

protected void checkNoReentry(javax.servlet.http.HttpServletRequest httpRequest)
                       throws FilterNonReentrantException
Check that this caching filter is not being reentered by the same recursively. Recursive calls will block indefinitely because the first request has not yet unblocked the cache.

This condition usually indicates an error in filter chaining or RequestDispatcher dispatching.

Parameters:
httpRequest -
Throws:
FilterNonReentrantException - if reentry is detected


Copyright © 2003-2011 Terracotta, Inc.. All Rights Reserved.