Skip to content

Commit

Permalink
Merge branch '2.0.x'
Browse files Browse the repository at this point in the history
  • Loading branch information
wilkinsona committed Oct 10, 2018
2 parents 467169a + f9b6c1a commit 646c20e
Show file tree
Hide file tree
Showing 2 changed files with 67 additions and 28 deletions.
Expand Up @@ -16,6 +16,7 @@

package org.springframework.boot.autoconfigure.diagnostics.analyzer;

import java.lang.annotation.Annotation;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
Expand All @@ -30,6 +31,7 @@
import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.beans.factory.BeanFactoryUtils;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import org.springframework.beans.factory.UnsatisfiedDependencyException;
import org.springframework.beans.factory.annotation.AnnotatedBeanDefinition;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
Expand Down Expand Up @@ -89,11 +91,23 @@ protected FailureAnalysis analyze(Throwable rootFailure,
message.append(String.format("%s required %s that could not be found.%n",
(description != null) ? description : "A component",
getBeanDescription(cause)));
for (AutoConfigurationResult result : autoConfigurationResults) {
message.append(String.format("\t- %s%n", result));
List<Annotation> injectionAnnotations = findInjectionAnnotations(rootFailure);
if (!injectionAnnotations.isEmpty()) {
message.append(String
.format("%nThe injection point has the following annotations:%n"));
for (Annotation injectionAnnotation : injectionAnnotations) {
message.append(String.format("\t- %s%n", injectionAnnotation));
}
}
for (UserConfigurationResult result : userConfigurationResults) {
message.append(String.format("\t- %s%n", result));
if (!autoConfigurationResults.isEmpty() || !userConfigurationResults.isEmpty()) {
message.append(String.format(
"%nThe following candidates were found but could not be injected:%n"));
for (AutoConfigurationResult result : autoConfigurationResults) {
message.append(String.format("\t- %s%n", result));
}
for (UserConfigurationResult result : userConfigurationResults) {
message.append(String.format("\t- %s%n", result));
}
}
String action = String.format("Consider %s %s in your configuration.",
(!autoConfigurationResults.isEmpty()
Expand Down Expand Up @@ -164,7 +178,7 @@ private void collectReportedConditionOutcomes(NoSuchBeanDefinitionException caus
if (!conditionAndOutcome.getOutcome().isMatch()) {
for (MethodMetadata method : methods) {
results.add(new AutoConfigurationResult(method,
conditionAndOutcome.getOutcome(), source.isMethod()));
conditionAndOutcome.getOutcome()));
}
}
}
Expand All @@ -179,11 +193,21 @@ private void collectExcludedAutoConfiguration(NoSuchBeanDefinitionException caus
String message = String.format("auto-configuration '%s' was excluded",
ClassUtils.getShortName(excludedClass));
results.add(new AutoConfigurationResult(method,
new ConditionOutcome(false, message), false));
new ConditionOutcome(false, message)));
}
}
}

private List<Annotation> findInjectionAnnotations(Throwable failure) {
UnsatisfiedDependencyException unsatisfiedDependencyException = findCause(failure,
UnsatisfiedDependencyException.class);
if (unsatisfiedDependencyException == null) {
return Collections.emptyList();
}
return Arrays.asList(
unsatisfiedDependencyException.getInjectionPoint().getAnnotations());
}

private class Source {

private final String className;
Expand All @@ -204,10 +228,6 @@ public String getMethodName() {
return this.methodName;
}

public boolean isMethod() {
return this.methodName != null;
}

}

private class BeanMethods implements Iterable<MethodMetadata> {
Expand Down Expand Up @@ -295,26 +315,17 @@ private class AutoConfigurationResult {

private final ConditionOutcome conditionOutcome;

private final boolean methodEvaluated;

AutoConfigurationResult(MethodMetadata methodMetadata,
ConditionOutcome conditionOutcome, boolean methodEvaluated) {
ConditionOutcome conditionOutcome) {
this.methodMetadata = methodMetadata;
this.conditionOutcome = conditionOutcome;
this.methodEvaluated = methodEvaluated;
}

@Override
public String toString() {
if (this.methodEvaluated) {
return String.format("Bean method '%s' in '%s' not loaded because %s",
this.methodMetadata.getMethodName(),
ClassUtils.getShortName(
this.methodMetadata.getDeclaringClassName()),
this.conditionOutcome.getMessage());
}
return String.format("Bean method '%s' not loaded because %s",
return String.format("Bean method '%s' in '%s' not loaded because %s",
this.methodMetadata.getMethodName(),
ClassUtils.getShortName(this.methodMetadata.getDeclaringClassName()),
this.conditionOutcome.getMessage());
}

Expand Down
Expand Up @@ -25,6 +25,7 @@
import org.springframework.beans.FatalBeanException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.NoUniqueBeanDefinitionException;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.ImportAutoConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionEvaluationReport;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
Expand Down Expand Up @@ -101,7 +102,7 @@ public void failureAnalysisForMissingClassOnAutoConfigurationType() {
assertDescriptionConstructorMissingType(analysis, StringHandler.class, 0,
String.class);
assertClassDisabled(analysis, "did not find required class 'com.example.FooBar'",
"string");
"string", ClassUtils.getShortName(TestTypeClassAutoConfiguration.class));
assertActionMissingType(analysis, String.class);
}

Expand All @@ -116,7 +117,7 @@ public void failureAnalysisForExcludedAutoConfigurationType() {
.getShortName(TestPropertyAutoConfiguration.class.getName());
assertClassDisabled(analysis,
String.format("auto-configuration '%s' was excluded", configClass),
"string");
"string", ClassUtils.getShortName(TestPropertyAutoConfiguration.class));
assertActionMissingType(analysis, String.class);
}

Expand All @@ -130,7 +131,7 @@ public void failureAnalysisForSeveralConditionsType() {
"did not find property 'spring.string.enabled'",
TestPropertyAutoConfiguration.class, "string");
assertClassDisabled(analysis, "did not find required class 'com.example.FooBar'",
"string");
"string", ClassUtils.getShortName(TestPropertyAutoConfiguration.class));
assertActionMissingType(analysis, String.class);
}

Expand Down Expand Up @@ -169,6 +170,14 @@ public void failureAnalysisForNullBeanByType() {
assertActionMissingType(analysis, String.class);
}

@Test
public void failureAnalysisForUnmatchedQualfier() {
FailureAnalysis analysis = analyzeFailure(
createFailure(QualifiedBeanConfiguration.class));
assertThat(analysis.getDescription()).contains(
"@org.springframework.beans.factory.annotation.Qualifier(value=alpha)");
}

private void assertDescriptionConstructorMissingType(FailureAnalysis analysis,
Class<?> component, int index, Class<?> type) {
String expected = String.format(
Expand Down Expand Up @@ -201,9 +210,9 @@ private void assertBeanMethodDisabled(FailureAnalysis analysis, String descripti
}

private void assertClassDisabled(FailureAnalysis analysis, String description,
String methodName) {
String expected = String.format("Bean method '%s' not loaded because",
methodName);
String methodName, String className) {
String expected = String.format("Bean method '%s' in '%s' not loaded because",
methodName, className);
assertThat(analysis.getDescription()).contains(expected);
assertThat(analysis.getDescription()).contains(description);
}
Expand Down Expand Up @@ -340,6 +349,25 @@ public String string() {

}

@Configuration
public static class QualifiedBeanConfiguration {

@Bean
public String consumer(@Qualifier("alpha") Thing thing) {
return "consumer";
}

@Bean
public Thing producer() {
return new Thing();
}

class Thing {

}

}

protected static class StringHandler {

public StringHandler(String foo) {
Expand Down

0 comments on commit 646c20e

Please sign in to comment.