Author: rmannibucau Date: Tue May 22 14:49:09 2018 New Revision: 1832033 URL: http://svn.apache.org/viewvc?rev=1832033&view=rev Log: JCS-190 [JCACHE] listener onExpired callback not always called
Added: commons/proper/jcs/branches/commons-jcs-2.2.x/commons-jcs-jcache/src/main/java/org/apache/commons/jcs/jcache/ExpiryAwareCache.java commons/proper/jcs/branches/commons-jcs-2.2.x/commons-jcs-jcache/src/test/java/org/apache/commons/jcs/jcache/ExpiryListenerTest.java - copied, changed from r1832029, commons/proper/jcs/branches/commons-jcs-2.2.x/commons-jcs-jcache/src/test/java/org/apache/commons/jcs/jcache/ImmediateExpiryTest.java Modified: commons/proper/jcs/branches/commons-jcs-2.2.x/commons-jcs-core/src/main/java/org/apache/commons/jcs/engine/control/CompositeCache.java commons/proper/jcs/branches/commons-jcs-2.2.x/commons-jcs-core/src/main/java/org/apache/commons/jcs/engine/control/CompositeCacheConfigurator.java commons/proper/jcs/branches/commons-jcs-2.2.x/commons-jcs-core/src/main/java/org/apache/commons/jcs/engine/control/CompositeCacheManager.java commons/proper/jcs/branches/commons-jcs-2.2.x/commons-jcs-jcache/src/main/java/org/apache/commons/jcs/jcache/JCSCache.java commons/proper/jcs/branches/commons-jcs-2.2.x/commons-jcs-jcache/src/main/java/org/apache/commons/jcs/jcache/JCSCachingManager.java Modified: commons/proper/jcs/branches/commons-jcs-2.2.x/commons-jcs-core/src/main/java/org/apache/commons/jcs/engine/control/CompositeCache.java URL: http://svn.apache.org/viewvc/commons/proper/jcs/branches/commons-jcs-2.2.x/commons-jcs-core/src/main/java/org/apache/commons/jcs/engine/control/CompositeCache.java?rev=1832033&r1=1832032&r2=1832033&view=diff ============================================================================== --- commons/proper/jcs/branches/commons-jcs-2.2.x/commons-jcs-core/src/main/java/org/apache/commons/jcs/engine/control/CompositeCache.java (original) +++ commons/proper/jcs/branches/commons-jcs-2.2.x/commons-jcs-core/src/main/java/org/apache/commons/jcs/engine/control/CompositeCache.java Tue May 22 14:49:09 2018 @@ -526,8 +526,7 @@ public class CompositeCache<K, V> log.debug( cacheAttr.getCacheName() + " - Memory cache hit, but element expired" ); } - missCountExpired.incrementAndGet(); - remove( key ); + doExpires(element); element = null; } else @@ -586,13 +585,11 @@ public class CompositeCache<K, V> log.debug( cacheAttr.getCacheName() + " - Aux cache[" + aux.getCacheName() + "] hit, but element expired." ); } - missCountExpired.incrementAndGet(); - // This will tell the remotes to remove the item // based on the element's expiration policy. The elements attributes // associated with the item when it created govern its behavior // everywhere. - remove( key ); + doExpires(element); element = null; } else @@ -639,6 +636,11 @@ public class CompositeCache<K, V> return element; } + protected void doExpires(ICacheElement<K, V> element) { + missCountExpired.incrementAndGet(); + remove( element.getKey() ); + } + /** * Gets multiple items from the cache based on the given set of keys. * <p> @@ -745,8 +747,7 @@ public class CompositeCache<K, V> log.debug( cacheAttr.getCacheName() + " - Memory cache hit, but element expired" ); } - missCountExpired.incrementAndGet(); - remove( element.getKey() ); + doExpires(element); elementsFromMemory.remove( element.getKey() ); } else @@ -1000,13 +1001,11 @@ public class CompositeCache<K, V> log.debug( cacheAttr.getCacheName() + " - Aux cache[" + aux.getCacheName() + "] hit, but element expired." ); } - missCountExpired.incrementAndGet(); - // This will tell the remote caches to remove the item // based on the element's expiration policy. The elements attributes // associated with the item when it created govern its behavior // everywhere. - remove( element.getKey() ); + doExpires(element); elementsFromAuxiliary.remove( element.getKey() ); } else Modified: commons/proper/jcs/branches/commons-jcs-2.2.x/commons-jcs-core/src/main/java/org/apache/commons/jcs/engine/control/CompositeCacheConfigurator.java URL: http://svn.apache.org/viewvc/commons/proper/jcs/branches/commons-jcs-2.2.x/commons-jcs-core/src/main/java/org/apache/commons/jcs/engine/control/CompositeCacheConfigurator.java?rev=1832033&r1=1832032&r2=1832033&view=diff ============================================================================== --- commons/proper/jcs/branches/commons-jcs-2.2.x/commons-jcs-core/src/main/java/org/apache/commons/jcs/engine/control/CompositeCacheConfigurator.java (original) +++ commons/proper/jcs/branches/commons-jcs-2.2.x/commons-jcs-core/src/main/java/org/apache/commons/jcs/engine/control/CompositeCacheConfigurator.java Tue May 22 14:49:09 2018 @@ -202,10 +202,10 @@ public class CompositeCacheConfigurator IElementAttributes ea = parseElementAttributes( props, regName, ccm.getDefaultElementAttributes(), regionPrefix ); - CompositeCache<K, V> cache = ( cca == null ) - ? new CompositeCache<K, V>( parseCompositeCacheAttributes( props, regName, - ccm.getDefaultCacheAttributes(), regionPrefix ), ea ) - : new CompositeCache<K, V>( cca, ea ); + ICompositeCacheAttributes instantiationCca = cca == null + ? parseCompositeCacheAttributes(props, regName, ccm.getDefaultCacheAttributes(), regionPrefix) + : cca; + CompositeCache<K, V> cache = newCache(instantiationCca, ea); // Inject cache manager cache.setCompositeCacheManager(ccm); @@ -282,6 +282,12 @@ public class CompositeCacheConfigurator return cache; } + protected <K, V> CompositeCache<K, V> newCache( + ICompositeCacheAttributes cca, IElementAttributes ea) + { + return new CompositeCache<K, V>( cca, ea ); + } + /** * Get an ICompositeCacheAttributes for the listed region. *<p> Modified: commons/proper/jcs/branches/commons-jcs-2.2.x/commons-jcs-core/src/main/java/org/apache/commons/jcs/engine/control/CompositeCacheManager.java URL: http://svn.apache.org/viewvc/commons/proper/jcs/branches/commons-jcs-2.2.x/commons-jcs-core/src/main/java/org/apache/commons/jcs/engine/control/CompositeCacheManager.java?rev=1832033&r1=1832032&r2=1832033&view=diff ============================================================================== --- commons/proper/jcs/branches/commons-jcs-2.2.x/commons-jcs-core/src/main/java/org/apache/commons/jcs/engine/control/CompositeCacheManager.java (original) +++ commons/proper/jcs/branches/commons-jcs-2.2.x/commons-jcs-core/src/main/java/org/apache/commons/jcs/engine/control/CompositeCacheManager.java Tue May 22 14:49:09 2018 @@ -460,7 +460,7 @@ public class CompositeCacheManager } // configure the cache - CompositeCacheConfigurator configurator = new CompositeCacheConfigurator(); + CompositeCacheConfigurator configurator = newConfigurator(); long start = System.currentTimeMillis(); @@ -604,7 +604,7 @@ public class CompositeCacheManager if ( cache == null ) { - CompositeCacheConfigurator configurator = new CompositeCacheConfigurator(); + CompositeCacheConfigurator configurator = newConfigurator(); cache = configurator.parseRegion( this.getConfigurationProperties(), this, cattr.getCacheName(), this.defaultAuxValues, cattr ); @@ -621,6 +621,10 @@ public class CompositeCacheManager return cache; } + protected CompositeCacheConfigurator newConfigurator() { + return new CompositeCacheConfigurator(); + } + /** * @param name */ Added: commons/proper/jcs/branches/commons-jcs-2.2.x/commons-jcs-jcache/src/main/java/org/apache/commons/jcs/jcache/ExpiryAwareCache.java URL: http://svn.apache.org/viewvc/commons/proper/jcs/branches/commons-jcs-2.2.x/commons-jcs-jcache/src/main/java/org/apache/commons/jcs/jcache/ExpiryAwareCache.java?rev=1832033&view=auto ============================================================================== --- commons/proper/jcs/branches/commons-jcs-2.2.x/commons-jcs-jcache/src/main/java/org/apache/commons/jcs/jcache/ExpiryAwareCache.java (added) +++ commons/proper/jcs/branches/commons-jcs-2.2.x/commons-jcs-jcache/src/main/java/org/apache/commons/jcs/jcache/ExpiryAwareCache.java Tue May 22 14:49:09 2018 @@ -0,0 +1,61 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.commons.jcs.jcache; + +import java.util.Arrays; +import java.util.Map; + +import javax.cache.Cache; +import javax.cache.configuration.CacheEntryListenerConfiguration; +import javax.cache.event.CacheEntryEvent; +import javax.cache.event.EventType; + +import org.apache.commons.jcs.engine.behavior.ICacheElement; +import org.apache.commons.jcs.engine.behavior.ICompositeCacheAttributes; +import org.apache.commons.jcs.engine.behavior.IElementAttributes; +import org.apache.commons.jcs.engine.control.CompositeCache; + +// allows us to plug some lifecycle callbacks on the core cache without impacting too much the core +public class ExpiryAwareCache<A, B> extends CompositeCache<A, B> +{ + private Map<CacheEntryListenerConfiguration<A, B>, JCSListener<A, B>> listeners; + private Cache<A, B> cacheRef; + + ExpiryAwareCache(final ICompositeCacheAttributes cattr, final IElementAttributes attr) + { + super(cattr, attr); + } + + @Override + protected void doExpires(final ICacheElement<A, B> element) + { + super.doExpires(element); + for (final JCSListener<A, B> listener : listeners.values()) + { + listener.onExpired(Arrays.<CacheEntryEvent<? extends A, ? extends B>> asList(new JCSCacheEntryEvent<A, B>( + cacheRef, EventType.REMOVED, null, element.getKey(), element.getVal()))); + } + } + + void init(final Cache<A, B> cache, final Map<CacheEntryListenerConfiguration<A, B>, JCSListener<A, B>> listeners) + { + this.cacheRef = cache; + this.listeners = listeners; + } +} Modified: commons/proper/jcs/branches/commons-jcs-2.2.x/commons-jcs-jcache/src/main/java/org/apache/commons/jcs/jcache/JCSCache.java URL: http://svn.apache.org/viewvc/commons/proper/jcs/branches/commons-jcs-2.2.x/commons-jcs-jcache/src/main/java/org/apache/commons/jcs/jcache/JCSCache.java?rev=1832033&r1=1832032&r2=1832033&view=diff ============================================================================== --- commons/proper/jcs/branches/commons-jcs-2.2.x/commons-jcs-jcache/src/main/java/org/apache/commons/jcs/jcache/JCSCache.java (original) +++ commons/proper/jcs/branches/commons-jcs-2.2.x/commons-jcs-jcache/src/main/java/org/apache/commons/jcs/jcache/JCSCache.java Tue May 22 14:49:09 2018 @@ -23,7 +23,6 @@ import org.apache.commons.jcs.engine.Ele import org.apache.commons.jcs.engine.behavior.ICacheElement; import org.apache.commons.jcs.engine.behavior.IElementAttributes; import org.apache.commons.jcs.engine.behavior.IElementSerializer; -import org.apache.commons.jcs.engine.control.CompositeCache; import org.apache.commons.jcs.jcache.jmx.JCSCacheMXBean; import org.apache.commons.jcs.jcache.jmx.JCSCacheStatisticsMXBean; import org.apache.commons.jcs.jcache.jmx.JMXs; @@ -71,7 +70,7 @@ import static org.apache.commons.jcs.jca // TODO: configure serializer public class JCSCache<K, V> implements Cache<K, V> { - private final CompositeCache<K, V> delegate; + private final ExpiryAwareCache<K, V> delegate; private final JCSCachingManager manager; private final JCSConfiguration<K, V> config; private final CacheLoader<K, V> loader; @@ -89,7 +88,7 @@ public class JCSCache<K, V> implements C public JCSCache(final ClassLoader classLoader, final JCSCachingManager mgr, final String cacheName, final JCSConfiguration<K, V> configuration, - final Properties properties, final CompositeCache<K, V> cache) + final Properties properties, final ExpiryAwareCache<K, V> cache) { manager = mgr; @@ -153,6 +152,7 @@ public class JCSCache<K, V> implements C { listeners.put(listener, new JCSListener<K, V>(listener)); } + delegate.init(this, listeners); statistics.setActive(config.isStatisticsEnabled()); @@ -307,7 +307,7 @@ public class JCSCache<K, V> implements C } else { - expires(key); + forceExpires(key); } } } @@ -401,7 +401,7 @@ public class JCSCache<K, V> implements C { if (!created) { - expires(key); + forceExpires(key); } } } @@ -411,7 +411,7 @@ public class JCSCache<K, V> implements C return duration == null || !duration.isZero(); } - private void expires(final K cacheKey) + private void forceExpires(final K cacheKey) { final ICacheElement<K, V> elt = delegate.get(cacheKey); delegate.remove(cacheKey); @@ -549,7 +549,7 @@ public class JCSCache<K, V> implements C final Duration expiryForAccess = expiryPolicy.getExpiryForAccess(); if (!isNotZero(expiryForAccess)) { - expires(key); + forceExpires(key); } else if (expiryForAccess != null && (!elt.getElementAttributes().getIsEternal() || !expiryForAccess.isEternal())) { Modified: commons/proper/jcs/branches/commons-jcs-2.2.x/commons-jcs-jcache/src/main/java/org/apache/commons/jcs/jcache/JCSCachingManager.java URL: http://svn.apache.org/viewvc/commons/proper/jcs/branches/commons-jcs-2.2.x/commons-jcs-jcache/src/main/java/org/apache/commons/jcs/jcache/JCSCachingManager.java?rev=1832033&r1=1832032&r2=1832033&view=diff ============================================================================== --- commons/proper/jcs/branches/commons-jcs-2.2.x/commons-jcs-jcache/src/main/java/org/apache/commons/jcs/jcache/JCSCachingManager.java (original) +++ commons/proper/jcs/branches/commons-jcs-2.2.x/commons-jcs-jcache/src/main/java/org/apache/commons/jcs/jcache/JCSCachingManager.java Tue May 22 14:49:09 2018 @@ -18,6 +18,10 @@ */ package org.apache.commons.jcs.jcache; +import org.apache.commons.jcs.engine.behavior.ICompositeCacheAttributes; +import org.apache.commons.jcs.engine.behavior.IElementAttributes; +import org.apache.commons.jcs.engine.control.CompositeCache; +import org.apache.commons.jcs.engine.control.CompositeCacheConfigurator; import org.apache.commons.jcs.engine.control.CompositeCacheManager; import org.apache.commons.jcs.jcache.lang.Subsitutor; import org.apache.commons.jcs.jcache.proxy.ClassLoaderAwareCache; @@ -65,6 +69,19 @@ public class JCSCachingManager implement return new InternalManager(); } + protected CompositeCacheConfigurator newConfigurator() + { + return new CompositeCacheConfigurator() + { + @Override + protected <K, V> CompositeCache<K, V> newCache( + final ICompositeCacheAttributes cca, final IElementAttributes ea) + { + return new ExpiryAwareCache<K, V>( cca, ea ); + } + }; + } + @Override // needed to call it from JCSCachingManager protected void initialize() { super.initialize(); @@ -197,7 +214,7 @@ public class JCSCachingManager implement loader, this, cacheName, new JCSConfiguration/*<K, V>*/(configuration, keyType, valueType), properties, - delegate.getCache(cacheName))); + ExpiryAwareCache.class.cast(delegate.getCache(cacheName)))); caches.putIfAbsent(cacheName, cache); } else Copied: commons/proper/jcs/branches/commons-jcs-2.2.x/commons-jcs-jcache/src/test/java/org/apache/commons/jcs/jcache/ExpiryListenerTest.java (from r1832029, commons/proper/jcs/branches/commons-jcs-2.2.x/commons-jcs-jcache/src/test/java/org/apache/commons/jcs/jcache/ImmediateExpiryTest.java) URL: http://svn.apache.org/viewvc/commons/proper/jcs/branches/commons-jcs-2.2.x/commons-jcs-jcache/src/test/java/org/apache/commons/jcs/jcache/ExpiryListenerTest.java?p2=commons/proper/jcs/branches/commons-jcs-2.2.x/commons-jcs-jcache/src/test/java/org/apache/commons/jcs/jcache/ExpiryListenerTest.java&p1=commons/proper/jcs/branches/commons-jcs-2.2.x/commons-jcs-jcache/src/test/java/org/apache/commons/jcs/jcache/ImmediateExpiryTest.java&r1=1832029&r2=1832033&rev=1832033&view=diff ============================================================================== --- commons/proper/jcs/branches/commons-jcs-2.2.x/commons-jcs-jcache/src/test/java/org/apache/commons/jcs/jcache/ImmediateExpiryTest.java (original) +++ commons/proper/jcs/branches/commons-jcs-2.2.x/commons-jcs-jcache/src/test/java/org/apache/commons/jcs/jcache/ExpiryListenerTest.java Tue May 22 14:49:09 2018 @@ -1,53 +1,81 @@ /* * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file + * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file + * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * with the License. You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the + * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.commons.jcs.jcache; -import org.junit.Test; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; + +import java.io.Serializable; +import java.util.ArrayList; +import java.util.Collection; +import java.util.concurrent.TimeUnit; import javax.cache.Cache; import javax.cache.CacheManager; import javax.cache.Caching; import javax.cache.configuration.FactoryBuilder; +import javax.cache.configuration.MutableCacheEntryListenerConfiguration; import javax.cache.configuration.MutableConfiguration; +import javax.cache.event.CacheEntryEvent; +import javax.cache.event.CacheEntryExpiredListener; +import javax.cache.event.CacheEntryListenerException; import javax.cache.expiry.CreatedExpiryPolicy; import javax.cache.expiry.Duration; import javax.cache.expiry.ExpiryPolicy; import javax.cache.spi.CachingProvider; -import static org.junit.Assert.assertFalse; +import org.junit.Test; + +public class ExpiryListenerTest { -public class ImmediateExpiryTest -{ @Test - public void immediate() - { + public void listener() throws InterruptedException { final CachingProvider cachingProvider = Caching.getCachingProvider(); final CacheManager cacheManager = cachingProvider.getCacheManager(); - cacheManager.createCache("default", - new MutableConfiguration<Object, Object>() - .setExpiryPolicyFactory( - new FactoryBuilder.SingletonFactory<ExpiryPolicy>(new CreatedExpiryPolicy(Duration.ZERO)))); + final CacheEntryExpiredListenerImpl listener = new CacheEntryExpiredListenerImpl(); + cacheManager.createCache("default", new MutableConfiguration<String, String>() + .setExpiryPolicyFactory(new FactoryBuilder.SingletonFactory<ExpiryPolicy>( + new CreatedExpiryPolicy(new Duration(TimeUnit.MILLISECONDS, 1)))) + .addCacheEntryListenerConfiguration(new MutableCacheEntryListenerConfiguration<String, String>( + FactoryBuilder.factoryOf(listener), + null, false, false + ))); final Cache<String, String> cache = cacheManager.getCache("default"); assertFalse(cache.containsKey("foo")); cache.put("foo", "bar"); + Thread.sleep(10); assertFalse(cache.containsKey("foo")); cachingProvider.close(); + assertEquals(1, listener.events.size()); + } + + private static class CacheEntryExpiredListenerImpl implements CacheEntryExpiredListener<String, String>, Serializable { + private final Collection<CacheEntryEvent<? extends String, ? extends String>> events = + new ArrayList<CacheEntryEvent<? extends String, ? extends String>>(); + + @Override + public void onExpired(final Iterable<CacheEntryEvent<? extends String, ? extends String>> cacheEntryEvents) + throws CacheEntryListenerException { + for (final CacheEntryEvent<? extends String, ? extends String> cacheEntryEvent : cacheEntryEvents) { + events.add(cacheEntryEvent); + } + } } }