diff --git a/src/main/java/org/springframework/data/couchbase/cache/CouchbaseCache.java b/src/main/java/org/springframework/data/couchbase/cache/CouchbaseCache.java index f38bab57..32625792 100644 --- a/src/main/java/org/springframework/data/couchbase/cache/CouchbaseCache.java +++ b/src/main/java/org/springframework/data/couchbase/cache/CouchbaseCache.java @@ -27,6 +27,7 @@ import org.springframework.cache.support.SimpleValueWrapper; * @see * Official Spring Cache Reference * @author Michael Nitschinger + * @author Konrad Król */ public class CouchbaseCache implements Cache { @@ -39,7 +40,12 @@ public class CouchbaseCache implements Cache { * The name of the cache. */ private final String name; - + + /** + * TTL value for objects in this cache + */ + private final int ttl; + /** * Construct the cache and pass in the CouchbaseClient instance. * @@ -49,6 +55,20 @@ public class CouchbaseCache implements Cache { public CouchbaseCache(final String name, final CouchbaseClient client) { this.name = name; this.client = client; + this.ttl = 0; + } + + /** + * Construct the cache and pass in the CouchbaseClient instance. + * + * @param name the name of the cache reference. + * @param client the CouchbaseClient instance. + * @param ttl TTL value for objects in this cache + */ + public CouchbaseCache(final String name, final CouchbaseClient client, int ttl) { + this.name = name; + this.client = client; + this.ttl = ttl; } /** @@ -68,6 +88,15 @@ public class CouchbaseCache implements Cache { public final CouchbaseClient getNativeCache() { return client; } + + /** + * Returns the TTL value for this cache. + * + * @return TTL value + */ + public final int getTtl() { + return ttl; + } /** * Get an element from the cache. @@ -96,7 +125,7 @@ public class CouchbaseCache implements Cache { public final void put(final Object key, final Object value) { if (value != null) { String documentId = key.toString(); - client.set(documentId, 0, value); + client.set(documentId, ttl, value); } else { evict(key); } diff --git a/src/main/java/org/springframework/data/couchbase/cache/CouchbaseCacheManager.java b/src/main/java/org/springframework/data/couchbase/cache/CouchbaseCacheManager.java index 0bd04381..26e5b6cb 100644 --- a/src/main/java/org/springframework/data/couchbase/cache/CouchbaseCacheManager.java +++ b/src/main/java/org/springframework/data/couchbase/cache/CouchbaseCacheManager.java @@ -32,6 +32,7 @@ import java.util.Map; * {@link CouchbaseCacheManager} orchestrates and handles them for the Spring Cache abstraction layer. * * @author Michael Nitschinger + * @author Konrad Król */ public class CouchbaseCacheManager extends AbstractCacheManager { @@ -39,6 +40,11 @@ public class CouchbaseCacheManager extends AbstractCacheManager { * Holds the reference to all stored CouchbaseClient cache connections. */ private final HashMap clients; + + /** + * Holds the TTL configuration for each cache. + */ + private final HashMap ttlConfiguration; /** * Construct a new CouchbaseCacheManager. @@ -47,6 +53,18 @@ public class CouchbaseCacheManager extends AbstractCacheManager { */ public CouchbaseCacheManager(final HashMap clients) { this.clients = clients; + this.ttlConfiguration = new HashMap(); + } + + /** + * Construct a new CouchbaseCacheManager. + * + * @param clients one ore more CouchbaseClients to reference. + * @param ttlConfiguration one or more TTL values (in seconds) + */ + public CouchbaseCacheManager(final HashMap clients, final HashMap ttlConfiguration) { + this.clients = clients; + this.ttlConfiguration = ttlConfiguration; } /** @@ -68,10 +86,20 @@ public class CouchbaseCacheManager extends AbstractCacheManager { Collection caches = new LinkedHashSet(); for (Map.Entry cache : clients.entrySet()) { - caches.add(new CouchbaseCache(cache.getKey(), cache.getValue())); + caches.add(new CouchbaseCache(cache.getKey(), cache.getValue(), getTtl(cache.getKey()))); } return caches; } + + /** + * Returns TTL value for single cache + * @param name cache name + * @return either the cache TTL value or 0 as a default value + */ + private int getTtl ( String name ) { + Integer expirationTime = ttlConfiguration.get(name); + return (expirationTime != null ? expirationTime : 0); + } } diff --git a/src/test/java/org/springframework/data/couchbase/cache/CouchbaseCacheManagerTests.java b/src/test/java/org/springframework/data/couchbase/cache/CouchbaseCacheManagerTests.java index addd3237..46f4e377 100644 --- a/src/test/java/org/springframework/data/couchbase/cache/CouchbaseCacheManagerTests.java +++ b/src/test/java/org/springframework/data/couchbase/cache/CouchbaseCacheManagerTests.java @@ -17,9 +17,11 @@ package org.springframework.data.couchbase.cache; import com.couchbase.client.CouchbaseClient; + import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.cache.Cache; import org.springframework.data.couchbase.TestApplicationConfig; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; @@ -27,6 +29,7 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import java.util.HashMap; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; /** * Verifies the correct functionality of the CouchbaseCacheManager. @@ -53,7 +56,55 @@ public class CouchbaseCacheManagerTests { instances.put("test", client); CouchbaseCacheManager manager = new CouchbaseCacheManager(instances); + manager.afterPropertiesSet(); + assertEquals(instances, manager.getClients()); + + Cache cache = manager.getCache("test"); + + assertNotNull(cache); + + assertEquals(cache.getClass(), CouchbaseCache.class); + assertEquals(((CouchbaseCache) cache).getName(), "test"); + assertEquals(((CouchbaseCache) cache).getTtl(), 0); // default TTL value + assertEquals(((CouchbaseCache) cache).getNativeCache(), client); + } + + /** + * Test cache creation with custom TTL values. + */ + @Test + public void testCacheInitWithTtl() { + HashMap instances = new HashMap(); + instances.put("cache1", client); + instances.put("cache2", client); + + HashMap ttlConfiguration = new HashMap(); + ttlConfiguration.put("cache1", 100); + ttlConfiguration.put("cache2", 200); + + CouchbaseCacheManager manager = new CouchbaseCacheManager(instances, ttlConfiguration); + manager.afterPropertiesSet(); + + assertEquals(instances, manager.getClients()); + + Cache cache1 = manager.getCache("cache1"); + Cache cache2 = manager.getCache("cache2"); + + assertNotNull(cache1); + assertNotNull(cache2); + + assertEquals(cache1.getClass(), CouchbaseCache.class); + assertEquals(cache2.getClass(), CouchbaseCache.class); + + assertEquals(((CouchbaseCache) cache1).getName(), "cache1"); + assertEquals(((CouchbaseCache) cache2).getName(), "cache2"); + + assertEquals(((CouchbaseCache) cache1).getTtl(), 100); + assertEquals(((CouchbaseCache) cache2).getTtl(), 200); + + assertEquals(((CouchbaseCache) cache1).getNativeCache(), client); + assertEquals(((CouchbaseCache) cache2).getNativeCache(), client); } } diff --git a/src/test/java/org/springframework/data/couchbase/cache/CouchbaseCacheTests.java b/src/test/java/org/springframework/data/couchbase/cache/CouchbaseCacheTests.java index 9d87518a..62ef68a3 100644 --- a/src/test/java/org/springframework/data/couchbase/cache/CouchbaseCacheTests.java +++ b/src/test/java/org/springframework/data/couchbase/cache/CouchbaseCacheTests.java @@ -17,6 +17,7 @@ package org.springframework.data.couchbase.cache; import com.couchbase.client.CouchbaseClient; + import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; @@ -33,6 +34,7 @@ import static org.junit.Assert.*; * Tests the CouchbaseCache class and verifies its functionality. * * @author Michael Nitschinger + * @author Konrad Król */ @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(classes = TestApplicationConfig.class) @@ -78,6 +80,24 @@ public class CouchbaseCacheTests { ValueWrapper loaded = cache.get(key); assertEquals(value, loaded.get()); } + + /** + * Verifies set() with TTL value. + */ + @Test + public void testSetWithTtl() throws InterruptedException { + CouchbaseCache cache = new CouchbaseCache(cacheName, client, 1); // cache for 1 second + + String key = "couchbase-cache-test"; + String value = "Hello World!"; + cache.put(key, value); + + // wait for TTL to expire (double time of TTL) + Thread.sleep(2000); + + String stored = (String) client.get(key); + assertNull(stored); + } @Test public void testGetSetWithCast() {