Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- import org.apache.log4j.Logger;
- import org.hibernate.exception.ExceptionUtils;
- import org.apache.commons.lang.ObjectUtils;
- import net.sf.ehcache.CacheException;
- import net.sf.ehcache.CacheManager;
- import net.sf.ehcache.Element;
- import net.sf.ehcache.constructs.blocking.SelfPopulatingCache;
- import net.sf.ehcache.Ehcache;
- import net.sf.ehcache.constructs.blocking.CacheEntryFactory;
- import net.sf.ehcache.event.CacheEventListener;
- /**
- * SelfPopulatingAgedCache is a SelfPopulatingCache
- * which means it uses a CacheEntryFactory to create missing elements
- * and return them from get. It also inherits the ability to block
- * other attempts to get the same key while a load is in progress with
- * an upper bound timeout (which does not apply to the client that first
- * tries to load the key). If you want to keep the cache fresh with
- * a background thread and have the same upper bound for all calls,
- * look into also using an ehcache Loader with this.
- *
- * This class adds a add way to set it's timeout in the constructor,
- * and also tests for expired elements and reloads them transparently.
- *
- * ehcache.xml can only setup the basic cache properties (age till timeout
- * and so forth), so to use this decorated cache, install it like this:
- *
- * MyImplConstructor or similar init() method {
- * Ehcache c = CacheManager.getInstance().getEhcache("com.whatever.ThingCache");
- * if (!(c instanceof SelfPopulatingAgedCache)) {
- * c = new SelfPopulatingAgedCache(c, categoryGetter, 5000);
- * }
- *
- * All this make final usage a one-liner:
- *
- * Thing getThing(Object key) {
- * return (Thing) CacheManager.getInstance().getEhcache("com.netjets.ThingCache")
- * .get(key).getValue();
- *
- * @author pinkham
- */
- public class SelfPopulatingAgedCache extends SelfPopulatingCache {
- static final Logger logger = Logger.getLogger(SelfPopulatingAgedCache.class);
- public SelfPopulatingAgedCache(Ehcache c, CacheEntryFactory ef, int timeout) {
- // super sets factory to this wrapper
- super(c, new ExceptionEatingCacheEntryFactoryWrapper(ef, "Credential token expired"));
- setTimeoutMillis(timeout);
- CacheManager.getInstance().replaceCacheWithDecoratedCache(c, this);
- // cache factory wrapper is also a listener but we need to register it
- getCacheEventNotificationService().registerListener((CacheEventListener)factory);
- }
- @Override
- public Element get(Object key) {
- try {
- return super.get(key); // decorated base cache handles expiration
- } catch (CacheException e) {
- // for some reason, CacheException doesn't call super(msg, cause) but has it's own cause field.
- // Add the cache name too
- // finally, subclass RuntimeException with empty {}
- // to get the more descriptive exception name
- // SelfPopulatingAgedCache$RuntimeException.
- RuntimeException e2 = new RuntimeException(
- e.getMessage()+ " for cache: "+cache.getName(), e.getInitialCause()){};
- //e2.setStackTrace(e.getStackTrace()); // as if they had done it right
- throw e2;
- }
- }
- // TODO: Fix the real root cause, but meanwhile, this might buy us some time QC 44371
- protected static final class ExceptionEatingCacheEntryFactoryWrapper implements CacheEventListener, CacheEntryFactory {
- private CacheEntryFactory factory;
- private String contains;
- protected ExceptionEatingCacheEntryFactoryWrapper(CacheEntryFactory factory, String contains) {
- this.factory = factory;
- this.contains = contains;
- }
- private Element lastExpiredElement;
- public Object createEntry(Object key) throws Exception {
- try {
- return factory.createEntry(key);
- } catch (Exception e) {
- if (contains == null || ExceptionUtils.getStackTrace(e).contains(contains)) {
- // lets not fail if key is null
- if (lastExpiredElement != null && ObjectUtils.equals(lastExpiredElement.getObjectKey(), key)) {
- Object ret = lastExpiredElement.getObjectValue(); // keep re-using it's data
- logger.warn(factory.getClass().getName()+
- " Ignoring exception and using old cache value: ",e);
- return ret;
- }
- logger.warn(factory.getClass().getName()+
- " Unable to ignore first exception since cache has no old value: "+e);
- }
- throw e;
- } finally {
- lastExpiredElement = null; // don't leak memory if there's no exception
- }
- }
- public void dispose() {}
- public void notifyElementEvicted(Ehcache ehcache, Element element) {}
- public void notifyElementExpired(Ehcache ehcache, Element element) {
- lastExpiredElement = element; // save it before it goes away
- }
- public void notifyElementPut(Ehcache ehcache, Element element) {}
- public void notifyElementRemoved(Ehcache ehcache, Element element) {}
- public void notifyElementUpdated(Ehcache ehcache, Element element) {}
- public void notifyRemoveAll(Ehcache ehcache) {}
- public Object clone() throws CloneNotSupportedException { return super.clone(); }
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement