Add failure analyzer for BeanCreationException

Closes gh-9220
pull/8428/merge
Stephane Nicoll 8 years ago
parent d058ed38a8
commit 2ca92e2a45

@ -0,0 +1,58 @@
/*
* Copyright 2012-2017 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.boot.diagnostics.analyzer;
import org.springframework.beans.factory.BeanCreationException;
import org.springframework.boot.diagnostics.AbstractFailureAnalyzer;
import org.springframework.boot.diagnostics.FailureAnalysis;
import org.springframework.boot.diagnostics.FailureAnalyzer;
import org.springframework.core.annotation.Order;
/**
* A {@link FailureAnalyzer} that performs analysis of failures caused by a
* {@link BeanCreationException}.
*
* @author Stephane Nicoll
* @see BeanCurrentlyInCreationFailureAnalyzer
*/
@Order(100)
public class BeanCreationFailureAnalyzer
extends AbstractFailureAnalyzer<BeanCreationException> {
@Override
protected FailureAnalysis analyze(Throwable rootFailure,
BeanCreationException cause) {
StringBuilder sb = new StringBuilder();
sb.append("A bean named '").append(cause.getBeanName()).append("'");
if (cause.getResourceDescription() != null) {
sb.append(" defined in ").append(cause.getResourceDescription());
}
sb.append(" failed to be created:");
sb.append(String.format("%n%n"));
Throwable nested = findMostNestedCause(cause);
sb.append(String.format("\t%s", nested.getMessage()));
return new FailureAnalysis(sb.toString(), null, cause);
}
private Throwable findMostNestedCause(Throwable exception) {
if (exception.getCause() == null) {
return exception;
}
return findMostNestedCause(exception.getCause());
}
}

@ -25,6 +25,7 @@ import org.springframework.beans.factory.InjectionPoint;
import org.springframework.beans.factory.UnsatisfiedDependencyException;
import org.springframework.boot.diagnostics.AbstractFailureAnalyzer;
import org.springframework.boot.diagnostics.FailureAnalysis;
import org.springframework.core.annotation.Order;
import org.springframework.util.StringUtils;
/**
@ -33,6 +34,7 @@ import org.springframework.util.StringUtils;
*
* @author Andy Wilkinson
*/
@Order(0)
class BeanCurrentlyInCreationFailureAnalyzer
extends AbstractFailureAnalyzer<BeanCurrentlyInCreationException> {

@ -33,6 +33,7 @@ org.springframework.boot.env.SpringApplicationJsonEnvironmentPostProcessor
# Failure Analyzers
org.springframework.boot.diagnostics.FailureAnalyzer=\
org.springframework.boot.diagnostics.analyzer.BeanCreationFailureAnalyzer,\
org.springframework.boot.diagnostics.analyzer.BeanCurrentlyInCreationFailureAnalyzer,\
org.springframework.boot.diagnostics.analyzer.BeanNotOfRequiredTypeFailureAnalyzer,\
org.springframework.boot.diagnostics.analyzer.BindFailureAnalyzer,\

@ -805,25 +805,6 @@ public class SpringApplicationTests {
TestPropertySourceUtils.INLINED_PROPERTIES_PROPERTY_SOURCE_NAME);
}
@Test
public void failureResultsInSingleStackTrace() throws Exception {
ThreadGroup group = new ThreadGroup("main");
Thread thread = new Thread(group, "main") {
@Override
public void run() {
SpringApplication application = new SpringApplication(
FailingConfig.class);
application.setWebEnvironment(false);
application.run();
};
};
thread.start();
thread.join(6000);
int occurrences = StringUtils.countOccurrencesOf(this.output.toString(),
"Caused by: java.lang.RuntimeException: ExpectedError");
assertThat(occurrences).as("Expected single stacktrace").isEqualTo(1);
}
private Condition<ConfigurableEnvironment> matchingPropertySource(
final Class<?> propertySourceClass, final String name) {
return new Condition<ConfigurableEnvironment>("has property source") {
@ -966,16 +947,6 @@ public class SpringApplicationTests {
}
@Configuration
static class FailingConfig {
@Bean
public Object fail() {
throw new RuntimeException("ExpectedError");
}
}
@Configuration
static class CommandLineRunConfig {

@ -0,0 +1,84 @@
/*
* Copyright 2012-2017 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.boot.diagnostics.analyzer;
import org.junit.Test;
import org.springframework.boot.diagnostics.FailureAnalysis;
import org.springframework.boot.diagnostics.FailureAnalyzer;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.Assert.fail;
/**
* Tests for {@link BeanCreationFailureAnalyzer}.
*
* @author Stephane Nicoll
*/
public class BeanCreationFailureAnalyzerTest {
private final FailureAnalyzer analyzer = new BeanCreationFailureAnalyzer();
@Test
public void failureWithDefinition() {
FailureAnalysis analysis = performAnalysis(
BeanCreationFailureConfiguration.class);
assertThat(analysis.getDescription()).contains("bean named 'foo'",
"Property bar is not set",
"defined in " + BeanCreationFailureConfiguration.class.getName());
assertThat(analysis.getDescription()).doesNotContain("Failed to instantiate");
assertThat(analysis.getAction()).isNull();
}
private FailureAnalysis performAnalysis(Class<?> configuration) {
FailureAnalysis analysis = this.analyzer.analyze(createFailure(configuration));
assertThat(analysis).isNotNull();
return analysis;
}
private Exception createFailure(Class<?> configuration) {
ConfigurableApplicationContext context = null;
try {
context = new AnnotationConfigApplicationContext(configuration);
}
catch (Exception ex) {
return ex;
}
finally {
if (context != null) {
context.close();
}
}
fail("Expected failure did not occur");
return null;
}
@Configuration
static class BeanCreationFailureConfiguration {
@Bean
public String foo() {
throw new IllegalStateException("Property bar is not set");
}
}
}
Loading…
Cancel
Save