Skip to content

Commit 7dd9f64

Browse files
committed
- NoSuchCacheManagerFailureAnalyzer - analyzer for 'CacheManager' is not found/not unique.
- AbstractNoSuchBeanDefinitionFailureAnalyzer.
1 parent 8367c57 commit 7dd9f64

File tree

9 files changed

+1034
-344
lines changed

9 files changed

+1034
-344
lines changed

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

Lines changed: 55 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@
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;
2224
import org.springframework.beans.factory.ObjectProvider;
@@ -43,7 +45,7 @@
4345
import org.springframework.core.type.AnnotationMetadata;
4446
import org.springframework.orm.jpa.AbstractEntityManagerFactoryBean;
4547
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
46-
import org.springframework.util.Assert;
48+
import org.springframework.util.CollectionUtils;
4749

4850
/**
4951
* {@link EnableAutoConfiguration Auto-configuration} for the cache abstraction. Creates a
@@ -75,8 +77,9 @@ public CacheManagerCustomizers cacheManagerCustomizers(
7577

7678
@Bean
7779
public CacheManagerValidator cacheAutoConfigurationValidator(
78-
CacheProperties cacheProperties, ObjectProvider<CacheManager> cacheManager) {
79-
return new CacheManagerValidator(cacheProperties, cacheManager);
80+
CacheProperties cacheProperties,
81+
ObjectProvider<Map<String, CacheManager>> cacheManagers) {
82+
return new CacheManagerValidator(cacheProperties, cacheManagers);
8083
}
8184

8285
@Configuration
@@ -92,27 +95,29 @@ public CacheManagerJpaDependencyConfiguration() {
9295
}
9396

9497
/**
95-
* Bean used to validate that a CacheManager exists and provide a more meaningful
96-
* exception.
98+
* Bean used to validate that a CacheManager exists and it unique.
9799
*/
98100
static class CacheManagerValidator implements InitializingBean {
99101

100102
private final CacheProperties cacheProperties;
101103

102-
private final ObjectProvider<CacheManager> cacheManager;
104+
private final Map<String, CacheManager> cacheManagers;
103105

104106
CacheManagerValidator(CacheProperties cacheProperties,
105-
ObjectProvider<CacheManager> cacheManager) {
107+
ObjectProvider<Map<String, CacheManager>> cacheManagers) {
106108
this.cacheProperties = cacheProperties;
107-
this.cacheManager = cacheManager;
109+
this.cacheManagers = cacheManagers.getIfAvailable();
108110
}
109111

110112
@Override
111113
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() + "')");
114+
if (CollectionUtils.isEmpty(this.cacheManagers)) {
115+
throw new NoSuchCacheManagerException(this.cacheProperties);
116+
}
117+
if (this.cacheManagers.size() > 1) {
118+
throw new NoUniqueCacheManagerException(this.cacheManagers.keySet(),
119+
this.cacheProperties);
120+
}
116121
}
117122

118123
}
@@ -134,4 +139,42 @@ public String[] selectImports(AnnotationMetadata importingClassMetadata) {
134139

135140
}
136141

142+
/**
143+
* Exception thrown when {@link org.springframework.cache.CacheManager} implementation
144+
* are not specified.
145+
*/
146+
static class NoSuchCacheManagerException extends RuntimeException {
147+
148+
private final CacheProperties properties;
149+
150+
NoSuchCacheManagerException(CacheProperties properties) {
151+
this.properties = properties;
152+
}
153+
154+
CacheProperties getProperties() {
155+
return this.properties;
156+
}
157+
158+
}
159+
160+
/**
161+
* Exception thrown when multiple {@link org.springframework.cache.CacheManager}
162+
* implementations are available with no way to know which implementation should be
163+
* used.
164+
*/
165+
static class NoUniqueCacheManagerException extends NoSuchCacheManagerException {
166+
167+
private final Set<String> beanNames;
168+
169+
NoUniqueCacheManagerException(Set<String> beanNames, CacheProperties properties) {
170+
super(properties);
171+
this.beanNames = beanNames;
172+
}
173+
174+
Set<String> getBeanNames() {
175+
return this.beanNames;
176+
}
177+
178+
}
179+
137180
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
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 java.util.Set;
20+
21+
import org.springframework.beans.BeansException;
22+
import org.springframework.beans.factory.BeanFactory;
23+
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
24+
import org.springframework.beans.factory.config.BeanDefinition;
25+
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
26+
import org.springframework.boot.autoconfigure.diagnostics.analyzer.NoSuchBeanDefinitionFailureAnalyzerSupport;
27+
import org.springframework.boot.diagnostics.AbstractFailureAnalyzer;
28+
import org.springframework.boot.diagnostics.FailureAnalysis;
29+
import org.springframework.cache.CacheManager;
30+
import org.springframework.util.Assert;
31+
import org.springframework.util.CollectionUtils;
32+
import org.springframework.util.StringUtils;
33+
34+
/**
35+
* An {@link AbstractFailureAnalyzer} for
36+
* {@link CacheAutoConfiguration.NoSuchCacheManagerException}.
37+
*
38+
* @author Dmytro Nosan
39+
*/
40+
class NoSuchCacheManagerFailureAnalyzer extends
41+
NoSuchBeanDefinitionFailureAnalyzerSupport<CacheAutoConfiguration.NoSuchCacheManagerException> {
42+
43+
private ConfigurableListableBeanFactory beanFactory;
44+
45+
@Override
46+
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
47+
Assert.isInstanceOf(ConfigurableListableBeanFactory.class, beanFactory);
48+
this.beanFactory = (ConfigurableListableBeanFactory) beanFactory;
49+
super.setBeanFactory(beanFactory);
50+
}
51+
52+
@Override
53+
public FailureAnalysis analyze(Throwable failure) {
54+
CacheAutoConfiguration.NoUniqueCacheManagerException cause = findCause(failure,
55+
CacheAutoConfiguration.NoUniqueCacheManagerException.class);
56+
if (cause != null) {
57+
return analyzeNoUniqueCacheManagerException(cause);
58+
}
59+
return super.analyze(failure);
60+
}
61+
62+
@Override
63+
protected BeanMetadata getBeanMetadata(Throwable rootFailure,
64+
CacheAutoConfiguration.NoSuchCacheManagerException cause) {
65+
return new BeanMetadata(CacheManager.class);
66+
}
67+
68+
private FailureAnalysis analyzeNoUniqueCacheManagerException(
69+
CacheAutoConfiguration.NoUniqueCacheManagerException cause) {
70+
Set<String> beanNames = cause.getBeanNames();
71+
if (CollectionUtils.isEmpty(beanNames)) {
72+
return null;
73+
}
74+
StringBuilder description = new StringBuilder();
75+
description.append(String.format("Found %d beans of the type " + "'%s'%n",
76+
beanNames.size(), CacheManager.class.getName()));
77+
for (String beanName : beanNames) {
78+
try {
79+
BeanDefinition definition = this.beanFactory
80+
.getMergedBeanDefinition(beanName);
81+
if (StringUtils.hasText(definition.getFactoryMethodName())) {
82+
description.append(
83+
String.format("\t- '%s': defined by method '%s' in %s%n",
84+
beanName, definition.getFactoryMethodName(),
85+
definition.getResourceDescription()));
86+
}
87+
else {
88+
description.append(String.format("\t- '%s': defined in %s%n",
89+
beanName, definition.getResourceDescription()));
90+
}
91+
}
92+
catch (NoSuchBeanDefinitionException ex) {
93+
description.append(String.format(
94+
"\t- '%s': a programmatically registered singleton", beanName));
95+
}
96+
}
97+
return new FailureAnalysis(description.toString(),
98+
"Consider marking one of the beans as @Primary, updating the consumer to"
99+
+ " accept multiple beans, or using @Qualifier to identify the"
100+
+ " bean that should be consumed",
101+
cause);
102+
}
103+
104+
}

0 commit comments

Comments
 (0)