Browse Source

Initialize FailureAnalyzer earlier

This commit changes `FailureAnalyzers` so that the loaded
`FailureAnalyzer` instances are initialized before the context eventually
fails.

Before this commit, the `BeanFactoryAware` callback was processed at a
time where the context has already shutdown. Some implementations need
to access components that are no longer available.

Instead, we now initialize them before the context is refreshed.

Closes gh-6748
pull/6746/merge
Stephane Nicoll 10 years ago
parent
commit
25e72fab71
  1. 15
      spring-boot/src/main/java/org/springframework/boot/SpringApplication.java
  2. 52
      spring-boot/src/main/java/org/springframework/boot/diagnostics/FailureAnalyzers.java
  3. 6
      spring-boot/src/test/java/org/springframework/boot/diagnostics/FailureAnalyzersTests.java

15
spring-boot/src/main/java/org/springframework/boot/SpringApplication.java

@ -298,6 +298,7 @@ public class SpringApplication { @@ -298,6 +298,7 @@ public class SpringApplication {
StopWatch stopWatch = new StopWatch();
stopWatch.start();
ConfigurableApplicationContext context = null;
FailureAnalyzers analyzers = null;
configureHeadlessProperty();
SpringApplicationRunListeners listeners = getRunListeners(args);
listeners.started();
@ -308,6 +309,7 @@ public class SpringApplication { @@ -308,6 +309,7 @@ public class SpringApplication {
applicationArguments);
Banner printedBanner = printBanner(environment);
context = createApplicationContext();
analyzers = new FailureAnalyzers(context);
prepareContext(context, environment, listeners, applicationArguments,
printedBanner);
refreshContext(context);
@ -321,7 +323,7 @@ public class SpringApplication { @@ -321,7 +323,7 @@ public class SpringApplication {
return context;
}
catch (Throwable ex) {
handleRunFailure(context, listeners, ex);
handleRunFailure(context, listeners, analyzers, ex);
throw new IllegalStateException(ex);
}
}
@ -803,14 +805,15 @@ public class SpringApplication { @@ -803,14 +805,15 @@ public class SpringApplication {
}
private void handleRunFailure(ConfigurableApplicationContext context,
SpringApplicationRunListeners listeners, Throwable exception) {
SpringApplicationRunListeners listeners, FailureAnalyzers analyzers,
Throwable exception) {
try {
try {
handleExitCode(context, exception);
listeners.finished(context, exception);
}
finally {
reportFailure(exception, context);
reportFailure(analyzers, exception);
if (context != null) {
context.close();
}
@ -822,11 +825,9 @@ public class SpringApplication { @@ -822,11 +825,9 @@ public class SpringApplication {
ReflectionUtils.rethrowRuntimeException(exception);
}
private void reportFailure(Throwable failure,
ConfigurableApplicationContext context) {
private void reportFailure(FailureAnalyzers analyzers, Throwable failure) {
try {
if (FailureAnalyzers.analyzeAndReport(failure, getClass().getClassLoader(),
context)) {
if (analyzers != null && analyzers.analyzeAndReport(failure)) {
registerLoggedException(failure);
return;
}

52
spring-boot/src/main/java/org/springframework/boot/diagnostics/FailureAnalyzers.java

@ -42,22 +42,50 @@ import org.springframework.util.ReflectionUtils; @@ -42,22 +42,50 @@ import org.springframework.util.ReflectionUtils;
*
* @author Andy Wilkinson
* @author Phillip Webb
* @author Stephane Nicoll
* @since 1.4.0
*/
public final class FailureAnalyzers {
private static final Log log = LogFactory.getLog(FailureAnalyzers.class);
private FailureAnalyzers() {
private final ClassLoader classLoader;
private final List<FailureAnalyzer> analyzers;
public FailureAnalyzers(ConfigurableApplicationContext context) {
this.classLoader = context.getClassLoader();
this.analyzers = loadFailureAnalyzers(this.classLoader);
prepareFailureAnalyzers(this.analyzers, context);
}
/**
* Analyze and report the specified {@code failure}.
*
* @param failure the failure to analyze
* @return {@code true} if the failure was handled
*/
public boolean analyzeAndReport(Throwable failure) {
FailureAnalysis analysis = analyze(failure, this.analyzers);
return report(analysis, this.classLoader);
}
/**
* Analyze and report the specified {@code failure}.
*
* @param failure the failure to analyze
* @param classLoader the classloader to use
* @param context the context to use
* @return {@code true} if the failure was handled
* @deprecated in favour of {@link #analyzeAndReport(Throwable)}
*/
@Deprecated
public static boolean analyzeAndReport(Throwable failure, ClassLoader classLoader,
ConfigurableApplicationContext context) {
List<FailureAnalyzer> analyzers = loadFailureAnalyzers(classLoader);
List<FailureAnalysisReporter> reporters = SpringFactoriesLoader
.loadFactories(FailureAnalysisReporter.class, classLoader);
FailureAnalysis analysis = analyze(failure, analyzers, context);
return report(analysis, reporters);
prepareFailureAnalyzers(analyzers, context);
FailureAnalysis analysis = analyze(failure, analyzers);
return report(analysis, classLoader);
}
private static List<FailureAnalyzer> loadFailureAnalyzers(ClassLoader classLoader) {
@ -79,10 +107,16 @@ public final class FailureAnalyzers { @@ -79,10 +107,16 @@ public final class FailureAnalyzers {
return analyzers;
}
private static FailureAnalysis analyze(Throwable failure,
List<FailureAnalyzer> analyzers, ConfigurableApplicationContext context) {
private static void prepareFailureAnalyzers(List<FailureAnalyzer> analyzers,
ConfigurableApplicationContext context) {
for (FailureAnalyzer analyzer : analyzers) {
prepareAnalyzer(context, analyzer);
}
}
private static FailureAnalysis analyze(Throwable failure,
List<FailureAnalyzer> analyzers) {
for (FailureAnalyzer analyzer : analyzers) {
FailureAnalysis analysis = analyzer.analyze(failure);
if (analysis != null) {
return analysis;
@ -99,7 +133,9 @@ public final class FailureAnalyzers { @@ -99,7 +133,9 @@ public final class FailureAnalyzers {
}
private static boolean report(FailureAnalysis analysis,
List<FailureAnalysisReporter> reporters) {
ClassLoader classLoader) {
List<FailureAnalysisReporter> reporters = SpringFactoriesLoader
.loadFactories(FailureAnalysisReporter.class, classLoader);
if (analysis == null || reporters.isEmpty()) {
return false;
}

6
spring-boot/src/test/java/org/springframework/boot/diagnostics/FailureAnalyzersTests.java

@ -70,8 +70,7 @@ public class FailureAnalyzersTests { @@ -70,8 +70,7 @@ public class FailureAnalyzersTests {
private void analyzeAndReport(final String factoriesName, Throwable failure) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
FailureAnalyzers.analyzeAndReport(failure,
context.setClassLoader(
new ClassLoader(getClass().getClassLoader()) {
@Override
@ -85,7 +84,8 @@ public class FailureAnalyzersTests { @@ -85,7 +84,8 @@ public class FailureAnalyzersTests {
}
}
}, context);
});
new FailureAnalyzers(context).analyzeAndReport(failure);
}
static class BasicFailureAnalyzer implements FailureAnalyzer {

Loading…
Cancel
Save