Skip to content

Commit 314b069

Browse files
committed
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
1 parent d23893f commit 314b069

File tree

5 files changed

+62
-19
lines changed

5 files changed

+62
-19
lines changed

spring-context-support/src/main/java/org/springframework/cache/jcache/config/AbstractJCacheConfiguration.java

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2014 the original author or authors.
2+
* Copyright 2002-2015 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -18,6 +18,7 @@
1818

1919
import org.springframework.beans.factory.config.BeanDefinition;
2020
import org.springframework.cache.annotation.AbstractCachingConfiguration;
21+
import org.springframework.cache.annotation.CachingConfigurer;
2122
import org.springframework.cache.interceptor.CacheResolver;
2223
import org.springframework.cache.jcache.interceptor.DefaultJCacheOperationSource;
2324
import org.springframework.cache.jcache.interceptor.JCacheOperationSource;
@@ -34,14 +35,16 @@
3435
* @see JCacheConfigurer
3536
*/
3637
@Configuration
37-
public class AbstractJCacheConfiguration extends AbstractCachingConfiguration<JCacheConfigurer> {
38+
public class AbstractJCacheConfiguration extends AbstractCachingConfiguration {
3839

3940
protected CacheResolver exceptionCacheResolver;
4041

4142
@Override
42-
protected void useCachingConfigurer(JCacheConfigurer config) {
43+
protected void useCachingConfigurer(CachingConfigurer config) {
4344
super.useCachingConfigurer(config);
44-
this.exceptionCacheResolver = config.exceptionCacheResolver();
45+
if (config instanceof JCacheConfigurer) {
46+
this.exceptionCacheResolver = ((JCacheConfigurer) config).exceptionCacheResolver();
47+
}
4548
}
4649

4750
@Bean(name = "jCacheOperationSource")

spring-context-support/src/main/java/org/springframework/cache/jcache/interceptor/DefaultJCacheOperationSource.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2014 the original author or authors.
2+
* Copyright 2002-2015 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -128,9 +128,9 @@ public void afterPropertiesSet() {
128128

129129
@Override
130130
public void afterSingletonsInstantiated() {
131-
// Make sure those are initialized on startup...
131+
// Make sure that the cache resolver is initialized. An exception cache resolver is only
132+
// required if the exceptionCacheName attribute is set on an operation
132133
Assert.notNull(getDefaultCacheResolver(), "Cache resolver should have been initialized");
133-
Assert.notNull(getDefaultExceptionCacheResolver(), "Exception cache resolver should have been initialized");
134134
}
135135

136136

spring-context-support/src/test/java/org/springframework/cache/jcache/config/JCacheJavaConfigTests.java

Lines changed: 46 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2014 the original author or authors.
2+
* Copyright 2002-2015 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -18,12 +18,15 @@
1818

1919
import java.util.Arrays;
2020

21+
import org.junit.Rule;
2122
import org.junit.Test;
23+
import org.junit.rules.ExpectedException;
2224

2325
import org.springframework.cache.Cache;
2426
import org.springframework.cache.CacheManager;
2527
import org.springframework.cache.annotation.EnableCaching;
2628
import org.springframework.cache.concurrent.ConcurrentMapCache;
29+
import org.springframework.cache.concurrent.ConcurrentMapCacheManager;
2730
import org.springframework.cache.config.SomeKeyGenerator;
2831
import org.springframework.cache.interceptor.CacheErrorHandler;
2932
import org.springframework.cache.interceptor.CacheResolver;
@@ -35,7 +38,6 @@
3538
import org.springframework.cache.jcache.interceptor.AnnotatedJCacheableService;
3639
import org.springframework.cache.jcache.interceptor.DefaultJCacheOperationSource;
3740
import org.springframework.cache.jcache.interceptor.JCacheInterceptor;
38-
import org.springframework.cache.jcache.interceptor.SimpleExceptionCacheResolver;
3941
import org.springframework.cache.support.NoOpCacheManager;
4042
import org.springframework.cache.support.SimpleCacheManager;
4143
import org.springframework.context.ApplicationContext;
@@ -51,6 +53,9 @@
5153
*/
5254
public class JCacheJavaConfigTests extends AbstractJCacheAnnotationTests {
5355

56+
@Rule
57+
public final ExpectedException thrown = ExpectedException.none();
58+
5459
@Override
5560
protected ApplicationContext getApplicationContext() {
5661
return new AnnotationConfigApplicationContext(EnableCachingConfig.class);
@@ -80,10 +85,7 @@ public void emptyConfigSupport() {
8085
assertEquals(SimpleCacheResolver.class, cos.getCacheResolver().getClass());
8186
assertSame(context.getBean(CacheManager.class),
8287
((SimpleCacheResolver) cos.getCacheResolver()).getCacheManager());
83-
assertNotNull(cos.getExceptionCacheResolver());
84-
assertEquals(SimpleExceptionCacheResolver.class, cos.getExceptionCacheResolver().getClass());
85-
assertSame(context.getBean(CacheManager.class),
86-
((SimpleExceptionCacheResolver) cos.getExceptionCacheResolver()).getCacheManager());
88+
assertNull(cos.getExceptionCacheResolver());
8789
context.close();
8890
}
8991

@@ -99,6 +101,28 @@ public void bothSetOnlyResolverIsUsed() {
99101
context.close();
100102
}
101103

104+
@Test
105+
public void exceptionCacheResolverFallbacksToMainOne() {
106+
ConfigurableApplicationContext context = new AnnotationConfigApplicationContext(
107+
NoExceptionCacheResolverConfig.class);
108+
try {
109+
DefaultJCacheOperationSource cos = context.getBean(DefaultJCacheOperationSource.class);
110+
assertSame(context.getBean("cacheResolver"), cos.getCacheResolver());
111+
assertNull(cos.getExceptionCacheResolver());
112+
113+
JCacheableService<?> service = context.getBean(JCacheableService.class);
114+
115+
service.cache("id");
116+
117+
// This call requires the cache manager to be set
118+
thrown.expect(IllegalStateException.class);
119+
service.cacheWithException("test", false);
120+
}
121+
finally {
122+
context.close();
123+
}
124+
}
125+
102126

103127
@Configuration
104128
@EnableCaching
@@ -200,4 +224,20 @@ public CacheResolver exceptionCacheResolver() {
200224
}
201225
}
202226

227+
@Configuration
228+
@EnableCaching
229+
static class NoExceptionCacheResolverConfig extends JCacheConfigurerSupport {
230+
231+
@Override
232+
@Bean
233+
public CacheResolver cacheResolver() {
234+
return new NamedCacheResolver(new ConcurrentMapCacheManager(), "default");
235+
}
236+
237+
@Bean
238+
public JCacheableService<?> cacheableService() {
239+
return new AnnotatedJCacheableService(new ConcurrentMapCache("default"));
240+
}
241+
}
242+
203243
}

spring-context/src/main/java/org/springframework/cache/annotation/AbstractCachingConfiguration.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@
3939
* @see EnableCaching
4040
*/
4141
@Configuration
42-
public abstract class AbstractCachingConfiguration<C extends CachingConfigurer> implements ImportAware {
42+
public abstract class AbstractCachingConfiguration implements ImportAware {
4343

4444
protected AnnotationAttributes enableCaching;
4545

@@ -63,7 +63,7 @@ public void setImportMetadata(AnnotationMetadata importMetadata) {
6363
}
6464

6565
@Autowired(required = false)
66-
void setConfigurers(Collection<C> configurers) {
66+
void setConfigurers(Collection<CachingConfigurer> configurers) {
6767
if (CollectionUtils.isEmpty(configurers)) {
6868
return;
6969
}
@@ -73,14 +73,14 @@ void setConfigurers(Collection<C> configurers) {
7373
"Refactor the configuration such that CachingConfigurer is " +
7474
"implemented only once or not at all.");
7575
}
76-
C configurer = configurers.iterator().next();
76+
CachingConfigurer configurer = configurers.iterator().next();
7777
useCachingConfigurer(configurer);
7878
}
7979

8080
/**
8181
* Extract the configuration from the nominated {@link CachingConfigurer}.
8282
*/
83-
protected void useCachingConfigurer(C config) {
83+
protected void useCachingConfigurer(CachingConfigurer config) {
8484
this.cacheManager = config.cacheManager();
8585
this.cacheResolver = config.cacheResolver();
8686
this.keyGenerator = config.keyGenerator();

spring-context/src/main/java/org/springframework/cache/annotation/ProxyCachingConfiguration.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2014 the original author or authors.
2+
* Copyright 2002-2015 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -35,7 +35,7 @@
3535
* @see CachingConfigurationSelector
3636
*/
3737
@Configuration
38-
public class ProxyCachingConfiguration extends AbstractCachingConfiguration<CachingConfigurer> {
38+
public class ProxyCachingConfiguration extends AbstractCachingConfiguration {
3939

4040
@Bean(name = CacheManagementConfigUtils.CACHE_ADVISOR_BEAN_NAME)
4141
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)

0 commit comments

Comments
 (0)