diff --git a/spring-context-support/src/main/java/org/springframework/cache/jcache/interceptor/DefaultJCacheOperationSource.java b/spring-context-support/src/main/java/org/springframework/cache/jcache/interceptor/DefaultJCacheOperationSource.java index d9dd6a5881..f320d6f2dc 100644 --- a/spring-context-support/src/main/java/org/springframework/cache/jcache/interceptor/DefaultJCacheOperationSource.java +++ b/spring-context-support/src/main/java/org/springframework/cache/jcache/interceptor/DefaultJCacheOperationSource.java @@ -16,6 +16,8 @@ package org.springframework.cache.jcache.interceptor; +import java.util.Collection; + import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.BeanFactory; import org.springframework.beans.factory.BeanFactoryAware; @@ -23,7 +25,9 @@ import org.springframework.beans.factory.InitializingBean; import org.springframework.beans.factory.NoSuchBeanDefinitionException; import org.springframework.beans.factory.NoUniqueBeanDefinitionException; import org.springframework.beans.factory.SmartInitializingSingleton; +import org.springframework.cache.Cache; import org.springframework.cache.CacheManager; +import org.springframework.cache.interceptor.CacheOperationInvocationContext; import org.springframework.cache.interceptor.CacheResolver; import org.springframework.cache.interceptor.KeyGenerator; import org.springframework.cache.interceptor.SimpleCacheResolver; @@ -179,7 +183,7 @@ public class DefaultJCacheOperationSource extends AnnotationJCacheOperationSourc @Override protected CacheResolver getDefaultExceptionCacheResolver() { if (this.exceptionCacheResolver == null) { - this.exceptionCacheResolver = new SimpleExceptionCacheResolver(getDefaultCacheManager()); + this.exceptionCacheResolver = new LazyCacheResolver(); } return this.exceptionCacheResolver; } @@ -189,4 +193,29 @@ public class DefaultJCacheOperationSource extends AnnotationJCacheOperationSourc return this.adaptedKeyGenerator; } + + /** + * Only resolve the default exception cache resolver when an exception needs to be handled. + *
+ * A non-JSR-107 setup requires either a {@link CacheManager} or a {@link CacheResolver}. If only + * the latter is specified, it is not possible to extract a default exception {@code CacheResolver} + * from a custom {@code CacheResolver} implementation so we have to fallback on the {@code CacheManager}. + *
+ * This gives this weird situation of a perfectly valid configuration that breaks all the sudden + * because the JCache support is enabled. To avoid this we resolve the default exception {@code CacheResolver} + * as late as possible to avoid such hard requirement in other cases. + */ + class LazyCacheResolver implements CacheResolver { + + private CacheResolver cacheResolver; + + @Override + public Collection extends Cache> resolveCaches(CacheOperationInvocationContext> context) { + if (this.cacheResolver == null) { + this.cacheResolver = new SimpleExceptionCacheResolver(getDefaultCacheManager()); + } + return this.cacheResolver.resolveCaches(context); + } + } + } diff --git a/spring-context-support/src/test/java/org/springframework/cache/jcache/config/JCacheJavaConfigTests.java b/spring-context-support/src/test/java/org/springframework/cache/jcache/config/JCacheJavaConfigTests.java index 4b0c4a8f12..94cf49bc0e 100644 --- a/spring-context-support/src/test/java/org/springframework/cache/jcache/config/JCacheJavaConfigTests.java +++ b/spring-context-support/src/test/java/org/springframework/cache/jcache/config/JCacheJavaConfigTests.java @@ -102,7 +102,7 @@ public class JCacheJavaConfigTests extends AbstractJCacheAnnotationTests { } @Test - public void exceptionCacheResolverFallbacksToMainOne() { + public void exceptionCacheResolverLazilyRequired() { ConfigurableApplicationContext context = new AnnotationConfigApplicationContext( NoExceptionCacheResolverConfig.class); try {