Skip to content

Commit 2a4aa4b

Browse files
committed
- NoSuchCacheManagerFailureAnalyzer - analyzer for 'CacheManager' is not found.
1 parent 1a2ebab commit 2a4aa4b

File tree

5 files changed

+213
-13
lines changed

5 files changed

+213
-13
lines changed

spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/cache/CacheAutoConfiguration.java

Lines changed: 51 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,12 @@
1717
package org.springframework.boot.autoconfigure.cache;
1818

1919
import java.util.List;
20+
import java.util.Map;
21+
import java.util.Set;
2022

2123
import org.springframework.beans.factory.InitializingBean;
24+
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
25+
import org.springframework.beans.factory.NoUniqueBeanDefinitionException;
2226
import org.springframework.beans.factory.ObjectProvider;
2327
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
2428
import org.springframework.boot.autoconfigure.AutoConfigureBefore;
@@ -43,7 +47,7 @@
4347
import org.springframework.core.type.AnnotationMetadata;
4448
import org.springframework.orm.jpa.AbstractEntityManagerFactoryBean;
4549
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
46-
import org.springframework.util.Assert;
50+
import org.springframework.util.CollectionUtils;
4751

4852
/**
4953
* {@link EnableAutoConfiguration Auto-configuration} for the cache abstraction. Creates a
@@ -75,8 +79,9 @@ public CacheManagerCustomizers cacheManagerCustomizers(
7579

7680
@Bean
7781
public CacheManagerValidator cacheAutoConfigurationValidator(
78-
CacheProperties cacheProperties, ObjectProvider<CacheManager> cacheManager) {
79-
return new CacheManagerValidator(cacheProperties, cacheManager);
82+
CacheProperties cacheProperties,
83+
ObjectProvider<Map<String, CacheManager>> cacheManagers) {
84+
return new CacheManagerValidator(cacheProperties, cacheManagers);
8085
}
8186

8287
@Configuration
@@ -92,27 +97,28 @@ public CacheManagerJpaDependencyConfiguration() {
9297
}
9398

9499
/**
95-
* Bean used to validate that a CacheManager exists and provide a more meaningful
96-
* exception.
100+
* Bean used to validate that a CacheManager exists and it unique.
97101
*/
98102
static class CacheManagerValidator implements InitializingBean {
99103

100104
private final CacheProperties cacheProperties;
101105

102-
private final ObjectProvider<CacheManager> cacheManager;
106+
private final Map<String, CacheManager> cacheManagers;
103107

104108
CacheManagerValidator(CacheProperties cacheProperties,
105-
ObjectProvider<CacheManager> cacheManager) {
109+
ObjectProvider<Map<String, CacheManager>> cacheManagers) {
106110
this.cacheProperties = cacheProperties;
107-
this.cacheManager = cacheManager;
111+
this.cacheManagers = cacheManagers.getIfAvailable();
108112
}
109113

110114
@Override
111115
public void afterPropertiesSet() {
112-
Assert.notNull(this.cacheManager.getIfAvailable(),
113-
() -> "No cache manager could "
114-
+ "be auto-configured, check your configuration (caching "
115-
+ "type is '" + this.cacheProperties.getType() + "')");
116+
if (CollectionUtils.isEmpty(this.cacheManagers)) {
117+
throw new NoSuchCacheManagerException(this.cacheProperties);
118+
}
119+
if (this.cacheManagers.size() > 1) {
120+
throw new NonUniqueCacheManagerException(this.cacheManagers.keySet());
121+
}
116122
}
117123

118124
}
@@ -134,4 +140,37 @@ public String[] selectImports(AnnotationMetadata importingClassMetadata) {
134140

135141
}
136142

143+
/**
144+
* Exception thrown when {@link org.springframework.cache.CacheManager} implementation
145+
* are not specified.
146+
*/
147+
static class NoSuchCacheManagerException extends NoSuchBeanDefinitionException {
148+
149+
private final CacheProperties properties;
150+
151+
NoSuchCacheManagerException(CacheProperties properties) {
152+
super("No cache manager could be auto-configured, check your configuration"
153+
+ " (caching type is '" + properties.getType() + "')");
154+
this.properties = properties;
155+
}
156+
157+
CacheProperties getProperties() {
158+
return this.properties;
159+
}
160+
161+
}
162+
163+
/**
164+
* Exception thrown when multiple {@link org.springframework.cache.CacheManager}
165+
* implementations are available with no way to know which implementation should be
166+
* used.
167+
*/
168+
static class NonUniqueCacheManagerException extends NoUniqueBeanDefinitionException {
169+
170+
NonUniqueCacheManagerException(Set<String> beans) {
171+
super(CacheManager.class, beans);
172+
}
173+
174+
}
175+
137176
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
/*
2+
* Copyright 2012-2018 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.springframework.boot.autoconfigure.cache;
18+
19+
import org.springframework.boot.diagnostics.AbstractFailureAnalyzer;
20+
import org.springframework.boot.diagnostics.FailureAnalysis;
21+
22+
/**
23+
* An {@link AbstractFailureAnalyzer} for
24+
* {@link CacheAutoConfiguration.NoSuchCacheManagerException}.
25+
*
26+
* @author Dmytro Nosan
27+
* @since 2.1.0
28+
*/
29+
class NoSuchCacheManagerFailureAnalyzer extends
30+
AbstractFailureAnalyzer<CacheAutoConfiguration.NoSuchCacheManagerException> {
31+
32+
@Override
33+
protected FailureAnalysis analyze(Throwable rootFailure,
34+
CacheAutoConfiguration.NoSuchCacheManagerException cause) {
35+
CacheProperties cacheProperties = cause.getProperties();
36+
if (cacheProperties.getType() == CacheType.GENERIC) {
37+
String description = String
38+
.format("No 'CacheManager' could be auto-configured.%n");
39+
String action = String.format("'spring.cache.type=generic' "
40+
+ "property was used, it requires that one or more 'Cache' bean(s) "
41+
+ "must be specified.%n");
42+
return new FailureAnalysis(description, action, cause);
43+
}
44+
return null;
45+
}
46+
47+
}

spring-boot-project/spring-boot-autoconfigure/src/main/resources/META-INF/spring.factories

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,8 @@ org.springframework.boot.diagnostics.FailureAnalyzer=\
134134
org.springframework.boot.autoconfigure.diagnostics.analyzer.NoSuchBeanDefinitionFailureAnalyzer,\
135135
org.springframework.boot.autoconfigure.jdbc.DataSourceBeanCreationFailureAnalyzer,\
136136
org.springframework.boot.autoconfigure.jdbc.HikariDriverConfigurationFailureAnalyzer,\
137-
org.springframework.boot.autoconfigure.session.NonUniqueSessionRepositoryFailureAnalyzer
137+
org.springframework.boot.autoconfigure.session.NonUniqueSessionRepositoryFailureAnalyzer,\
138+
org.springframework.boot.autoconfigure.cache.NoSuchCacheManagerFailureAnalyzer
138139

139140
# Template availability providers
140141
org.springframework.boot.autoconfigure.template.TemplateAvailabilityProvider=\

spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/cache/CacheAutoConfigurationTests.java

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,16 @@ public void simpleCacheExplicitWithCacheNames() {
170170
});
171171
}
172172

173+
@Test
174+
public void multiplyCacheManagers() {
175+
this.contextRunner.withUserConfiguration(DefaultCacheConfiguration.class)
176+
.withConfiguration(AutoConfigurations.of(CacheManagerConfiguration.class))
177+
.withPropertyValues("spring.cache.type=simple")
178+
.run((context) -> assertThat(context).getFailure()
179+
.isInstanceOf(BeanCreationException.class).hasMessageContaining(
180+
"No qualifying bean of type 'org.springframework.cache.CacheManager'"));
181+
}
182+
173183
@Test
174184
public void genericCacheWithCaches() {
175185
this.contextRunner.withUserConfiguration(GenericCacheConfiguration.class)
@@ -804,6 +814,16 @@ static class DefaultCacheAndCustomizersConfiguration {
804814

805815
}
806816

817+
@Configuration
818+
static class CacheManagerConfiguration {
819+
820+
@Bean
821+
public CacheManager customCacheManager() {
822+
return new SimpleCacheManager();
823+
}
824+
825+
}
826+
807827
@Configuration
808828
@EnableCaching
809829
static class GenericCacheConfiguration {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
/*
2+
* Copyright 2012-2018 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.springframework.boot.autoconfigure.cache;
18+
19+
import org.junit.Test;
20+
21+
import org.springframework.beans.factory.BeanCreationException;
22+
import org.springframework.boot.autoconfigure.ImportAutoConfiguration;
23+
import org.springframework.boot.diagnostics.FailureAnalysis;
24+
import org.springframework.boot.diagnostics.LoggingFailureAnalysisReporter;
25+
import org.springframework.boot.test.util.TestPropertyValues;
26+
import org.springframework.cache.annotation.EnableCaching;
27+
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
28+
import org.springframework.context.annotation.Configuration;
29+
import org.springframework.context.annotation.Import;
30+
31+
import static org.assertj.core.api.Assertions.assertThat;
32+
33+
/**
34+
* Tests for {@link NoSuchCacheManagerFailureAnalyzer}.
35+
*
36+
* @author Dmytro Nosan
37+
*/
38+
public class NoSuchCacheManagerFailureAnalyzerTests {
39+
40+
private final NoSuchCacheManagerFailureAnalyzer analyzer = new NoSuchCacheManagerFailureAnalyzer();
41+
42+
@Test
43+
public void failureAnalysisForNoCacheManagers() {
44+
assertThat(analyzeFailure(createFailure(DefaultCacheAutoConfiguration.class,
45+
"spring.cache.type=jcache"))).isNull();
46+
}
47+
48+
@Test
49+
public void failureAnalysisForGenericCacheType() {
50+
FailureAnalysis analysis = analyzeFailure(createFailure(
51+
DefaultCacheAutoConfiguration.class, "spring.cache.type=generic"));
52+
assertThat(analysis.getAction())
53+
.contains("'spring.cache.type=generic' property was used")
54+
.doesNotContain("Check your configuration");
55+
assertThat(analysis.getDescription())
56+
.contains("No 'CacheManager' could be auto-configured.");
57+
58+
}
59+
60+
private BeanCreationException createFailure(Class<?> config, String... environment) {
61+
try (AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext()) {
62+
TestPropertyValues.of(environment).applyTo(context);
63+
context.register(config);
64+
context.refresh();
65+
return null;
66+
}
67+
catch (BeanCreationException ex) {
68+
return ex;
69+
}
70+
}
71+
72+
private FailureAnalysis analyzeFailure(Exception failure) {
73+
FailureAnalysis analysis = this.analyzer.analyze(failure);
74+
if (analysis != null) {
75+
new LoggingFailureAnalysisReporter().report(analysis);
76+
}
77+
return analysis;
78+
}
79+
80+
@EnableCaching
81+
@Configuration
82+
static class DefaultCacheConfiguration {
83+
84+
}
85+
86+
@Configuration
87+
@ImportAutoConfiguration(CacheAutoConfiguration.class)
88+
@Import(DefaultCacheConfiguration.class)
89+
static class DefaultCacheAutoConfiguration {
90+
91+
}
92+
93+
}

0 commit comments

Comments
 (0)