org.apache.excalibur.source.SourceValidity org.apache.cocoon.caching.validity.EventValidity org.apache.cocoon.caching.validity.NamedEvent java.io.Serializable // artificial slowdown to make the effects of the cache visible final int DELAY_SECS = 2; /** * Generate the unique key for the cache. * * This key must be unique inside the space of this XSP page, it is used * to find the page contents in the cache (if getValidity says that the * contents are still valid). * * This method will be invoked before the getValidity() method. * * @return The generated key or null if the component * is currently not cacheable. */ public Serializable getKey() { // for our test, pages having the same value of "pageKey" will share // the same cache location String key = request.getParameter("pageKey") ; return ((key==null||"".equals(key)) ? "one" : key); } /** * Generate the validity object, tells the cache how long to * keep contents having this key around. In this case, it will * be until an Event is retrieved matching the NamedEvent created below. * * Before this method can be invoked the getKey() method * will be invoked. * * @return The generated validity object or null if the * component is currently not cacheable. */ public SourceValidity getValidity() { String key = request.getParameter("pageKey") ; return new EventValidity( new NamedEvent( (key==null||"".equals(key)) ? "one" : key)); } Demonstrating Event-Aware Caching This xsp page is based on (copied from) the cacheable xsp sample but there are some important differences. If you don't already understand at least the basics of caching in Cocoon, you should probably start there, not here. Read the text below, and the sitemap and source for more details. I pause for DELAY_SECS seconds during generation, so that you can tell if I'm being served from the cache or not.
What you see here was generated on new java.util.Date().
I'm cached for each unique value of request parameter 'pageKey'. Other parameters do not matter.
Here the value is: .
If this is not the same as the 'pageKey' parameter in the page URL, we have a problem.
Unlike other cacheable pages in Cocoon, I can be un-cached by events external to Cocoon - for instance, when a database table or row is updated.
My cache entry will be invalidated (actually, removed) when an event named occurs. This can be manually simulated by clicking one of the "uncache" links below.
Test links: Note: the random numbers you see included in the url after an uncache link serve two purposes in the example, making it easier to see the effect of the cache invalidation. They prevent browser caching and they demonstrate that only our designated key matters in the retrieval from cache. This event based cache system consists essentially of three parts:
  • A new type of SourceValidity, EventValidity, which contains information on the Event which will invalidate this cached content. Until this event is received, EventValidities will usually always return valid, though they don't have to.
  • An extension to Cocoon's Cache implementation. Cocoon's Cache is really just a thin wrapper around Avalon-Excalibur's Store project. The EventAwareCacheImpl does two things. It examines each pipeline on its way into the cache to determine if any of its SourceValidities are instances of EventValidity. If so, it notifies an event registry as described next. The second critical function of the EventAware cache implementation is that it allows other components to contact it and notify it of an Event. The Cache then looks up the keys mapped to that event in the event registry and cleans out the cache and registry accordingly.
  • The EventRegistry is responsible for mapping Events to cache keys, and providing information about that mapping to systems that need it, usually just the EventAwareCache. Another crucial responsibility of the EventRegistry is to persist its data across container shutdown and startup. The default implementation does by serializing an object to disk (currently in WEB-INF). If recovering this fails, the EventAwareCache is notified, and it is expected to ensure there are no orphaned EventValidities (currently by clearing the entire cache).
Note that though this example uses xsp with actions or flow, any pipeline component can be made to use EventValidity, and any code with access to the ComponentManager can translate real-world events to Events and notify the Cache of them.
// slowdown page generation. try { Thread.sleep(DELAY_SECS * 1000L); } catch (InterruptedException ie) { // Not much that can be done... }