diff --git a/spring-context/src/main/java/org/springframework/cache/concurrent/ConcurrentMapCacheManager.java b/spring-context/src/main/java/org/springframework/cache/concurrent/ConcurrentMapCacheManager.java
index 5f69a828e55..14c6956bf58 100644
--- a/spring-context/src/main/java/org/springframework/cache/concurrent/ConcurrentMapCacheManager.java
+++ b/spring-context/src/main/java/org/springframework/cache/concurrent/ConcurrentMapCacheManager.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2013 the original author or authors.
+ * Copyright 2002-2014 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -19,6 +19,7 @@ package org.springframework.cache.concurrent;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
+import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
@@ -70,6 +71,8 @@ public class ConcurrentMapCacheManager implements CacheManager {
* Specify the set of cache names for this CacheManager's 'static' mode.
*
The number of caches and their names will be fixed after a call to this method,
* with no creation of further cache regions at runtime.
+ *
Calling this with a {@code null} collection argument resets the
+ * mode to 'dynamic', allowing for further creation of caches again.
*/
public void setCacheNames(Collection cacheNames) {
if (cacheNames != null) {
@@ -78,6 +81,9 @@ public class ConcurrentMapCacheManager implements CacheManager {
}
this.dynamic = false;
}
+ else {
+ this.dynamic = true;
+ }
}
/**
@@ -85,9 +91,17 @@ public class ConcurrentMapCacheManager implements CacheManager {
* in this cache manager.
* Default is "true", despite ConcurrentHashMap itself not supporting {@code null}
* values. An internal holder object will be used to store user-level {@code null}s.
+ *
Note: A change of the null-value setting will reset all existing caches,
+ * if any, to reconfigure them with the new null-value requirement.
*/
public void setAllowNullValues(boolean allowNullValues) {
- this.allowNullValues = allowNullValues;
+ if (allowNullValues != this.allowNullValues) {
+ this.allowNullValues = allowNullValues;
+ // Need to recreate all Cache instances with the new null-value configuration...
+ for (Map.Entry entry : this.cacheMap.entrySet()) {
+ entry.setValue(createConcurrentMapCache(entry.getKey()));
+ }
+ }
}
/**
diff --git a/spring-context/src/test/java/org/springframework/cache/concurrent/ConcurrentMapCacheManagerTests.java b/spring-context/src/test/java/org/springframework/cache/concurrent/ConcurrentMapCacheManagerTests.java
index 661e4a3d352..7e19619a7d9 100644
--- a/spring-context/src/test/java/org/springframework/cache/concurrent/ConcurrentMapCacheManagerTests.java
+++ b/spring-context/src/test/java/org/springframework/cache/concurrent/ConcurrentMapCacheManagerTests.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2013 the original author or authors.
+ * Copyright 2002-2014 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -56,7 +56,7 @@ public class ConcurrentMapCacheManagerTests {
@Test
public void testStaticMode() {
- CacheManager cm = new ConcurrentMapCacheManager("c1", "c2");
+ ConcurrentMapCacheManager cm = new ConcurrentMapCacheManager("c1", "c2");
Cache cache1 = cm.getCache("c1");
assertTrue(cache1 instanceof ConcurrentMapCache);
Cache cache1again = cm.getCache("c1");
@@ -76,6 +76,36 @@ public class ConcurrentMapCacheManagerTests {
assertNull(cache1.get("key3").get());
cache1.evict("key3");
assertNull(cache1.get("key3"));
+
+ cm.setAllowNullValues(false);
+ Cache cache1x = cm.getCache("c1");
+ assertTrue(cache1x instanceof ConcurrentMapCache);
+ assertTrue(cache1x != cache1);
+ Cache cache2x = cm.getCache("c2");
+ assertTrue(cache2x instanceof ConcurrentMapCache);
+ assertTrue(cache2x != cache2);
+ Cache cache3x = cm.getCache("c3");
+ assertNull(cache3x);
+
+ cache1x.put("key1", "value1");
+ assertEquals("value1", cache1x.get("key1").get());
+ cache1x.put("key2", 2);
+ assertEquals(2, cache1x.get("key2").get());
+ try {
+ cache1x.put("key3", null);
+ fail("Should have thrown NullPointerException");
+ }
+ catch (NullPointerException ex) {
+ // expected
+ }
+
+ cm.setAllowNullValues(true);
+ Cache cache1y = cm.getCache("c1");
+
+ cache1y.put("key3", null);
+ assertNull(cache1y.get("key3").get());
+ cache1y.evict("key3");
+ assertNull(cache1y.get("key3"));
}
}