Only require an exception CacheResolver if necessary
Previously, a cache infrastructure with only a CacheResolver would have worked fine until the JSR-107 API is added to the classpath. When this is the case, the JCache support kicks in and an exception cache resolver is all of the sudden required. The CacheResolver _is_ different as the default implementation does look different attributes so if a custom CacheResolver is set, it is not possible to "reuse" it as a fallback exception CacheResolver. Now, an exception CacheResolver is only required if a JSR-107 annotation with an "exceptionCacheName" attribute is processed (i.e. the exception CacheResolver is lazily instantiated if necessary). The use case of having a CachingConfigurerSupport with only a CacheResolver was still broken though since the JCache support only looks for a JCacheConfigurer bean (per the generic type set on AbstractCachingConfiguration). This has been fixed as well. Issue: SPR-12850
This commit is contained in:
parent
d23893fd25
commit
314b069fd8
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2002-2014 the original author or authors.
|
* Copyright 2002-2015 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -18,6 +18,7 @@ package org.springframework.cache.jcache.config;
|
||||||
|
|
||||||
import org.springframework.beans.factory.config.BeanDefinition;
|
import org.springframework.beans.factory.config.BeanDefinition;
|
||||||
import org.springframework.cache.annotation.AbstractCachingConfiguration;
|
import org.springframework.cache.annotation.AbstractCachingConfiguration;
|
||||||
|
import org.springframework.cache.annotation.CachingConfigurer;
|
||||||
import org.springframework.cache.interceptor.CacheResolver;
|
import org.springframework.cache.interceptor.CacheResolver;
|
||||||
import org.springframework.cache.jcache.interceptor.DefaultJCacheOperationSource;
|
import org.springframework.cache.jcache.interceptor.DefaultJCacheOperationSource;
|
||||||
import org.springframework.cache.jcache.interceptor.JCacheOperationSource;
|
import org.springframework.cache.jcache.interceptor.JCacheOperationSource;
|
||||||
|
@ -34,14 +35,16 @@ import org.springframework.context.annotation.Role;
|
||||||
* @see JCacheConfigurer
|
* @see JCacheConfigurer
|
||||||
*/
|
*/
|
||||||
@Configuration
|
@Configuration
|
||||||
public class AbstractJCacheConfiguration extends AbstractCachingConfiguration<JCacheConfigurer> {
|
public class AbstractJCacheConfiguration extends AbstractCachingConfiguration {
|
||||||
|
|
||||||
protected CacheResolver exceptionCacheResolver;
|
protected CacheResolver exceptionCacheResolver;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void useCachingConfigurer(JCacheConfigurer config) {
|
protected void useCachingConfigurer(CachingConfigurer config) {
|
||||||
super.useCachingConfigurer(config);
|
super.useCachingConfigurer(config);
|
||||||
this.exceptionCacheResolver = config.exceptionCacheResolver();
|
if (config instanceof JCacheConfigurer) {
|
||||||
|
this.exceptionCacheResolver = ((JCacheConfigurer) config).exceptionCacheResolver();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Bean(name = "jCacheOperationSource")
|
@Bean(name = "jCacheOperationSource")
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2002-2014 the original author or authors.
|
* Copyright 2002-2015 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -128,9 +128,9 @@ public class DefaultJCacheOperationSource extends AnnotationJCacheOperationSourc
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void afterSingletonsInstantiated() {
|
public void afterSingletonsInstantiated() {
|
||||||
// Make sure those are initialized on startup...
|
// Make sure that the cache resolver is initialized. An exception cache resolver is only
|
||||||
|
// required if the exceptionCacheName attribute is set on an operation
|
||||||
Assert.notNull(getDefaultCacheResolver(), "Cache resolver should have been initialized");
|
Assert.notNull(getDefaultCacheResolver(), "Cache resolver should have been initialized");
|
||||||
Assert.notNull(getDefaultExceptionCacheResolver(), "Exception cache resolver should have been initialized");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2002-2014 the original author or authors.
|
* Copyright 2002-2015 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -18,12 +18,15 @@ package org.springframework.cache.jcache.config;
|
||||||
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
|
||||||
|
import org.junit.Rule;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
import org.junit.rules.ExpectedException;
|
||||||
|
|
||||||
import org.springframework.cache.Cache;
|
import org.springframework.cache.Cache;
|
||||||
import org.springframework.cache.CacheManager;
|
import org.springframework.cache.CacheManager;
|
||||||
import org.springframework.cache.annotation.EnableCaching;
|
import org.springframework.cache.annotation.EnableCaching;
|
||||||
import org.springframework.cache.concurrent.ConcurrentMapCache;
|
import org.springframework.cache.concurrent.ConcurrentMapCache;
|
||||||
|
import org.springframework.cache.concurrent.ConcurrentMapCacheManager;
|
||||||
import org.springframework.cache.config.SomeKeyGenerator;
|
import org.springframework.cache.config.SomeKeyGenerator;
|
||||||
import org.springframework.cache.interceptor.CacheErrorHandler;
|
import org.springframework.cache.interceptor.CacheErrorHandler;
|
||||||
import org.springframework.cache.interceptor.CacheResolver;
|
import org.springframework.cache.interceptor.CacheResolver;
|
||||||
|
@ -35,7 +38,6 @@ import org.springframework.cache.interceptor.SimpleKeyGenerator;
|
||||||
import org.springframework.cache.jcache.interceptor.AnnotatedJCacheableService;
|
import org.springframework.cache.jcache.interceptor.AnnotatedJCacheableService;
|
||||||
import org.springframework.cache.jcache.interceptor.DefaultJCacheOperationSource;
|
import org.springframework.cache.jcache.interceptor.DefaultJCacheOperationSource;
|
||||||
import org.springframework.cache.jcache.interceptor.JCacheInterceptor;
|
import org.springframework.cache.jcache.interceptor.JCacheInterceptor;
|
||||||
import org.springframework.cache.jcache.interceptor.SimpleExceptionCacheResolver;
|
|
||||||
import org.springframework.cache.support.NoOpCacheManager;
|
import org.springframework.cache.support.NoOpCacheManager;
|
||||||
import org.springframework.cache.support.SimpleCacheManager;
|
import org.springframework.cache.support.SimpleCacheManager;
|
||||||
import org.springframework.context.ApplicationContext;
|
import org.springframework.context.ApplicationContext;
|
||||||
|
@ -51,6 +53,9 @@ import static org.junit.Assert.*;
|
||||||
*/
|
*/
|
||||||
public class JCacheJavaConfigTests extends AbstractJCacheAnnotationTests {
|
public class JCacheJavaConfigTests extends AbstractJCacheAnnotationTests {
|
||||||
|
|
||||||
|
@Rule
|
||||||
|
public final ExpectedException thrown = ExpectedException.none();
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected ApplicationContext getApplicationContext() {
|
protected ApplicationContext getApplicationContext() {
|
||||||
return new AnnotationConfigApplicationContext(EnableCachingConfig.class);
|
return new AnnotationConfigApplicationContext(EnableCachingConfig.class);
|
||||||
|
@ -80,10 +85,7 @@ public class JCacheJavaConfigTests extends AbstractJCacheAnnotationTests {
|
||||||
assertEquals(SimpleCacheResolver.class, cos.getCacheResolver().getClass());
|
assertEquals(SimpleCacheResolver.class, cos.getCacheResolver().getClass());
|
||||||
assertSame(context.getBean(CacheManager.class),
|
assertSame(context.getBean(CacheManager.class),
|
||||||
((SimpleCacheResolver) cos.getCacheResolver()).getCacheManager());
|
((SimpleCacheResolver) cos.getCacheResolver()).getCacheManager());
|
||||||
assertNotNull(cos.getExceptionCacheResolver());
|
assertNull(cos.getExceptionCacheResolver());
|
||||||
assertEquals(SimpleExceptionCacheResolver.class, cos.getExceptionCacheResolver().getClass());
|
|
||||||
assertSame(context.getBean(CacheManager.class),
|
|
||||||
((SimpleExceptionCacheResolver) cos.getExceptionCacheResolver()).getCacheManager());
|
|
||||||
context.close();
|
context.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -99,6 +101,28 @@ public class JCacheJavaConfigTests extends AbstractJCacheAnnotationTests {
|
||||||
context.close();
|
context.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void exceptionCacheResolverFallbacksToMainOne() {
|
||||||
|
ConfigurableApplicationContext context = new AnnotationConfigApplicationContext(
|
||||||
|
NoExceptionCacheResolverConfig.class);
|
||||||
|
try {
|
||||||
|
DefaultJCacheOperationSource cos = context.getBean(DefaultJCacheOperationSource.class);
|
||||||
|
assertSame(context.getBean("cacheResolver"), cos.getCacheResolver());
|
||||||
|
assertNull(cos.getExceptionCacheResolver());
|
||||||
|
|
||||||
|
JCacheableService<?> service = context.getBean(JCacheableService.class);
|
||||||
|
|
||||||
|
service.cache("id");
|
||||||
|
|
||||||
|
// This call requires the cache manager to be set
|
||||||
|
thrown.expect(IllegalStateException.class);
|
||||||
|
service.cacheWithException("test", false);
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
context.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@Configuration
|
@Configuration
|
||||||
@EnableCaching
|
@EnableCaching
|
||||||
|
@ -200,4 +224,20 @@ public class JCacheJavaConfigTests extends AbstractJCacheAnnotationTests {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Configuration
|
||||||
|
@EnableCaching
|
||||||
|
static class NoExceptionCacheResolverConfig extends JCacheConfigurerSupport {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Bean
|
||||||
|
public CacheResolver cacheResolver() {
|
||||||
|
return new NamedCacheResolver(new ConcurrentMapCacheManager(), "default");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public JCacheableService<?> cacheableService() {
|
||||||
|
return new AnnotatedJCacheableService(new ConcurrentMapCache("default"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -39,7 +39,7 @@ import org.springframework.util.CollectionUtils;
|
||||||
* @see EnableCaching
|
* @see EnableCaching
|
||||||
*/
|
*/
|
||||||
@Configuration
|
@Configuration
|
||||||
public abstract class AbstractCachingConfiguration<C extends CachingConfigurer> implements ImportAware {
|
public abstract class AbstractCachingConfiguration implements ImportAware {
|
||||||
|
|
||||||
protected AnnotationAttributes enableCaching;
|
protected AnnotationAttributes enableCaching;
|
||||||
|
|
||||||
|
@ -63,7 +63,7 @@ public abstract class AbstractCachingConfiguration<C extends CachingConfigurer>
|
||||||
}
|
}
|
||||||
|
|
||||||
@Autowired(required = false)
|
@Autowired(required = false)
|
||||||
void setConfigurers(Collection<C> configurers) {
|
void setConfigurers(Collection<CachingConfigurer> configurers) {
|
||||||
if (CollectionUtils.isEmpty(configurers)) {
|
if (CollectionUtils.isEmpty(configurers)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -73,14 +73,14 @@ public abstract class AbstractCachingConfiguration<C extends CachingConfigurer>
|
||||||
"Refactor the configuration such that CachingConfigurer is " +
|
"Refactor the configuration such that CachingConfigurer is " +
|
||||||
"implemented only once or not at all.");
|
"implemented only once or not at all.");
|
||||||
}
|
}
|
||||||
C configurer = configurers.iterator().next();
|
CachingConfigurer configurer = configurers.iterator().next();
|
||||||
useCachingConfigurer(configurer);
|
useCachingConfigurer(configurer);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Extract the configuration from the nominated {@link CachingConfigurer}.
|
* Extract the configuration from the nominated {@link CachingConfigurer}.
|
||||||
*/
|
*/
|
||||||
protected void useCachingConfigurer(C config) {
|
protected void useCachingConfigurer(CachingConfigurer config) {
|
||||||
this.cacheManager = config.cacheManager();
|
this.cacheManager = config.cacheManager();
|
||||||
this.cacheResolver = config.cacheResolver();
|
this.cacheResolver = config.cacheResolver();
|
||||||
this.keyGenerator = config.keyGenerator();
|
this.keyGenerator = config.keyGenerator();
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2002-2014 the original author or authors.
|
* Copyright 2002-2015 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -35,7 +35,7 @@ import org.springframework.context.annotation.Role;
|
||||||
* @see CachingConfigurationSelector
|
* @see CachingConfigurationSelector
|
||||||
*/
|
*/
|
||||||
@Configuration
|
@Configuration
|
||||||
public class ProxyCachingConfiguration extends AbstractCachingConfiguration<CachingConfigurer> {
|
public class ProxyCachingConfiguration extends AbstractCachingConfiguration {
|
||||||
|
|
||||||
@Bean(name = CacheManagementConfigUtils.CACHE_ADVISOR_BEAN_NAME)
|
@Bean(name = CacheManagementConfigUtils.CACHE_ADVISOR_BEAN_NAME)
|
||||||
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
|
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
|
||||||
|
|
Loading…
Reference in New Issue