diff --git a/spring-context-support/src/main/java/org/springframework/cache/ehcache/EhCacheCache.java b/spring-context-support/src/main/java/org/springframework/cache/ehcache/EhCacheCache.java index 048581cfec..c730c637e8 100644 --- a/spring-context-support/src/main/java/org/springframework/cache/ehcache/EhCacheCache.java +++ b/spring-context-support/src/main/java/org/springframework/cache/ehcache/EhCacheCache.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. @@ -70,7 +70,7 @@ public class EhCacheCache implements Cache { public T get(Object key, Class type) { Element element = this.cache.get(key); Object value = (element != null ? element.getObjectValue() : null); - if (type != null && !type.isInstance(value)) { + if (value != null && type != null && !type.isInstance(value)) { throw new IllegalStateException("Cached value is not of required type [" + type.getName() + "]: " + value); } return (T) value; diff --git a/spring-context-support/src/main/java/org/springframework/cache/guava/GuavaCache.java b/spring-context-support/src/main/java/org/springframework/cache/guava/GuavaCache.java index 24b634935e..6a9cf4cbe7 100644 --- a/spring-context-support/src/main/java/org/springframework/cache/guava/GuavaCache.java +++ b/spring-context-support/src/main/java/org/springframework/cache/guava/GuavaCache.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. @@ -90,7 +90,7 @@ public class GuavaCache implements Cache { @SuppressWarnings("unchecked") public T get(Object key, Class type) { Object value = fromStoreValue(this.cache.getIfPresent(key)); - if (type != null && !type.isInstance(value)) { + if (value != null && type != null && !type.isInstance(value)) { throw new IllegalStateException("Cached value is not of required type [" + type.getName() + "]: " + value); } return (T) value; diff --git a/spring-context-support/src/main/java/org/springframework/cache/jcache/JCacheCache.java b/spring-context-support/src/main/java/org/springframework/cache/jcache/JCacheCache.java index b988be59e3..a0b34470f1 100644 --- a/spring-context-support/src/main/java/org/springframework/cache/jcache/JCacheCache.java +++ b/spring-context-support/src/main/java/org/springframework/cache/jcache/JCacheCache.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. @@ -84,7 +84,7 @@ public class JCacheCache implements Cache { @SuppressWarnings("unchecked") public T get(Object key, Class type) { Object value = fromStoreValue(this.cache.get(key)); - if (type != null && !type.isInstance(value)) { + if (value != null && type != null && !type.isInstance(value)) { throw new IllegalStateException("Cached value is not of required type [" + type.getName() + "]: " + value); } return (T) value; diff --git a/spring-context-support/src/test/java/org/springframework/cache/ehcache/EhCacheCacheTests.java b/spring-context-support/src/test/java/org/springframework/cache/ehcache/EhCacheCacheTests.java index a76ddb98ed..587eb95a1f 100644 --- a/spring-context-support/src/test/java/org/springframework/cache/ehcache/EhCacheCacheTests.java +++ b/spring-context-support/src/test/java/org/springframework/cache/ehcache/EhCacheCacheTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2010-2013 the original author or authors. + * Copyright 2010-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. @@ -31,6 +31,7 @@ import static org.junit.Assert.*; /** * @author Costin Leau + * @author Juergen Hoeller */ public class EhCacheCacheTests { @@ -71,11 +72,20 @@ public class EhCacheCacheTests { Object value = "george"; assertNull(cache.get(key)); + assertNull(cache.get(key, String.class)); + assertNull(cache.get(key, Object.class)); + cache.put(key, value); assertEquals(value, cache.get(key).get()); assertEquals(value, cache.get(key, String.class)); assertEquals(value, cache.get(key, Object.class)); assertEquals(value, cache.get(key, null)); + + cache.put(key, null); + assertNotNull(cache.get(key)); + assertNull(cache.get(key).get()); + assertNull(cache.get(key, String.class)); + assertNull(cache.get(key, Object.class)); } @Test diff --git a/spring-context/src/main/java/org/springframework/cache/Cache.java b/spring-context/src/main/java/org/springframework/cache/Cache.java index 2051d67a0b..bfe32443d1 100644 --- a/spring-context/src/main/java/org/springframework/cache/Cache.java +++ b/spring-context/src/main/java/org/springframework/cache/Cache.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. @@ -24,6 +24,7 @@ package org.springframework.cache; * cache methods that return {@code null}). * * @author Costin Leau + * @author Juergen Hoeller * @since 3.1 */ public interface Cache { @@ -59,11 +60,14 @@ public interface Cache { * between a cached {@code null} value and no cache entry found at all. * Use the standard {@link #get(Object)} variant for that purpose instead. * @param key the key whose associated value is to be returned - * @param type the required type of the returned value + * @param type the required type of the returned value (may be + * {@code null} to bypass a type check; in case of a {@code null} + * value found in the cache, the specified type is irrelevant) * @return the value to which this cache maps the specified key * (which may be {@code null} itself), or also {@code null} if * the cache contains no mapping for this key * @see #get(Object) + * @since 4.0 */ T get(Object key, Class type); diff --git a/spring-context/src/main/java/org/springframework/cache/concurrent/ConcurrentMapCache.java b/spring-context/src/main/java/org/springframework/cache/concurrent/ConcurrentMapCache.java index 58b384bac9..0cf8264dd0 100644 --- a/spring-context/src/main/java/org/springframework/cache/concurrent/ConcurrentMapCache.java +++ b/spring-context/src/main/java/org/springframework/cache/concurrent/ConcurrentMapCache.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. @@ -110,7 +110,7 @@ public class ConcurrentMapCache implements Cache { @SuppressWarnings("unchecked") public T get(Object key, Class type) { Object value = fromStoreValue(this.store.get(key)); - if (type != null && !type.isInstance(value)) { + if (value != null && type != null && !type.isInstance(value)) { throw new IllegalStateException("Cached value is not of required type [" + type.getName() + "]: " + value); } return (T) value; diff --git a/spring-context/src/test/java/org/springframework/cache/concurrent/ConcurrentCacheTests.java b/spring-context/src/test/java/org/springframework/cache/concurrent/ConcurrentCacheTests.java index 62d1993b87..a80bc9560b 100644 --- a/spring-context/src/test/java/org/springframework/cache/concurrent/ConcurrentCacheTests.java +++ b/spring-context/src/test/java/org/springframework/cache/concurrent/ConcurrentCacheTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2010-2013 the original author or authors. + * Copyright 2010-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. @@ -28,6 +28,7 @@ import static org.junit.Assert.*; /** * @author Costin Leau + * @author Juergen Hoeller */ public class ConcurrentCacheTests { @@ -62,11 +63,20 @@ public class ConcurrentCacheTests { Object value = "george"; assertNull(cache.get(key)); + assertNull(cache.get(key, String.class)); + assertNull(cache.get(key, Object.class)); + cache.put(key, value); assertEquals(value, cache.get(key).get()); assertEquals(value, cache.get(key, String.class)); assertEquals(value, cache.get(key, Object.class)); assertEquals(value, cache.get(key, null)); + + cache.put(key, null); + assertNotNull(cache.get(key)); + assertNull(cache.get(key).get()); + assertNull(cache.get(key, String.class)); + assertNull(cache.get(key, Object.class)); } @Test