From d7d5cbf9599f62d1fa2d4ade1a9977eceaf09c5b Mon Sep 17 00:00:00 2001 From: Madhura Bhave Date: Fri, 14 Sep 2018 12:55:43 -0700 Subject: [PATCH] Simplify printing ConditionEvaluationReport when using context runner Closes gh-13119 --- ...ditionEvaluationReportLoggingListener.java | 52 ++++++++++++++++--- ...nEvaluationReportLoggingListenerTests.java | 23 ++++++++ .../main/asciidoc/spring-boot-features.adoc | 17 ++++++ .../AbstractApplicationContextRunner.java | 9 ++-- .../runner/ApplicationContextRunner.java | 4 +- .../ReactiveWebApplicationContextRunner.java | 4 +- .../runner/WebApplicationContextRunner.java | 4 +- 7 files changed, 95 insertions(+), 18 deletions(-) diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/logging/ConditionEvaluationReportLoggingListener.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/logging/ConditionEvaluationReportLoggingListener.java index 6a780ac749..3b9910e56a 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/logging/ConditionEvaluationReportLoggingListener.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/logging/ConditionEvaluationReportLoggingListener.java @@ -31,6 +31,7 @@ import org.springframework.context.event.GenericApplicationListener; import org.springframework.context.support.GenericApplicationContext; import org.springframework.core.Ordered; import org.springframework.core.ResolvableType; +import org.springframework.util.Assert; /** * {@link ApplicationContextInitializer} that writes the {@link ConditionEvaluationReport} @@ -45,6 +46,7 @@ import org.springframework.core.ResolvableType; * @author Dave Syer * @author Phillip Webb * @author Andy Wilkinson + * @author Madhura Bhave */ public class ConditionEvaluationReportLoggingListener implements ApplicationContextInitializer { @@ -55,6 +57,26 @@ public class ConditionEvaluationReportLoggingListener private ConditionEvaluationReport report; + private final LogLevel logLevelForReport; + + public ConditionEvaluationReportLoggingListener() { + this(LogLevel.DEBUG); + } + + public ConditionEvaluationReportLoggingListener(LogLevel logLevelForReport) { + Assert.isTrue(isInfoOrDebug(logLevelForReport), "LogLevel must be INFO or DEBUG"); + this.logLevelForReport = logLevelForReport; + } + + private boolean isInfoOrDebug(LogLevel logLevelForReport) { + return LogLevel.INFO.equals(logLevelForReport) + || LogLevel.DEBUG.equals(logLevelForReport); + } + + public LogLevel getLogLevelForReport() { + return this.logLevelForReport; + } + @Override public void initialize(ConfigurableApplicationContext applicationContext) { this.applicationContext = applicationContext; @@ -97,19 +119,33 @@ public class ConditionEvaluationReportLoggingListener .get(this.applicationContext.getBeanFactory()); } if (!this.report.getConditionAndOutcomesBySource().isEmpty()) { - if (isCrashReport && this.logger.isInfoEnabled() - && !this.logger.isDebugEnabled()) { - this.logger.info(String - .format("%n%nError starting ApplicationContext. To display the " - + "conditions report re-run your application with " - + "'debug' enabled.")); + if (this.getLogLevelForReport().equals(LogLevel.INFO)) { + if (this.logger.isInfoEnabled()) { + this.logger.info(new ConditionEvaluationReportMessage(this.report)); + } + else if (isCrashReport) { + logMessage("info"); + } } - if (this.logger.isDebugEnabled()) { - this.logger.debug(new ConditionEvaluationReportMessage(this.report)); + else { + if (isCrashReport && this.logger.isInfoEnabled() + && !this.logger.isDebugEnabled()) { + logMessage("debug"); + } + if (this.logger.isDebugEnabled()) { + this.logger.debug(new ConditionEvaluationReportMessage(this.report)); + } } } } + private void logMessage(String logLevel) { + this.logger.info( + String.format("%n%nError starting ApplicationContext. To display the " + + "conditions report re-run your application with '" + logLevel + + "' enabled.")); + } + private class ConditionEvaluationReportListener implements GenericApplicationListener { diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/logging/ConditionEvaluationReportLoggingListenerTests.java b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/logging/ConditionEvaluationReportLoggingListenerTests.java index 3f22dedd4b..01ca0da25c 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/logging/ConditionEvaluationReportLoggingListenerTests.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/logging/ConditionEvaluationReportLoggingListenerTests.java @@ -31,6 +31,7 @@ import org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoCon import org.springframework.boot.autoconfigure.http.HttpMessageConvertersAutoConfiguration; import org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration; import org.springframework.boot.context.event.ApplicationFailedEvent; +import org.springframework.boot.logging.LogLevel; import org.springframework.boot.testsupport.rule.OutputCapture; import org.springframework.context.annotation.AnnotationConfigApplicationContext; import org.springframework.context.annotation.Bean; @@ -41,6 +42,7 @@ import org.springframework.mock.web.MockServletContext; import org.springframework.web.context.support.AnnotationConfigWebApplicationContext; import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatExceptionOfType; import static org.junit.Assert.fail; /** @@ -48,6 +50,7 @@ import static org.junit.Assert.fail; * * @author Phillip Webb * @author Andy Wilkinson + * @author Madhura Bhave */ public class ConditionEvaluationReportLoggingListenerTests { @@ -137,6 +140,26 @@ public class ConditionEvaluationReportLoggingListenerTests { assertThat(context.getBean(ConditionEvaluationReport.class)).isNotNull(); } + @Test + public void listenerWithInfoLevelShouldLogAtInfo() { + AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(); + ConditionEvaluationReportLoggingListener initializer = new ConditionEvaluationReportLoggingListener( + LogLevel.INFO); + initializer.initialize(context); + context.register(Config.class); + context.refresh(); + initializer.onApplicationEvent(new ContextRefreshedEvent(context)); + assertThat(this.outputCapture.toString()) + .contains("CONDITIONS EVALUATION REPORT"); + } + + @Test + public void listenerSupportsOnlyInfoAndDebug() { + assertThatExceptionOfType(IllegalArgumentException.class).isThrownBy( + () -> new ConditionEvaluationReportLoggingListener(LogLevel.TRACE)) + .withMessage("LogLevel must be INFO or DEBUG"); + } + @Test public void noErrorIfNotInitialized() { this.initializer diff --git a/spring-boot-project/spring-boot-docs/src/main/asciidoc/spring-boot-features.adoc b/spring-boot-project/spring-boot-docs/src/main/asciidoc/spring-boot-features.adoc index bf1eea4b3c..a277544d47 100644 --- a/spring-boot-project/spring-boot-docs/src/main/asciidoc/spring-boot-features.adoc +++ b/spring-boot-project/spring-boot-docs/src/main/asciidoc/spring-boot-features.adoc @@ -7659,6 +7659,23 @@ example: include::{test-examples}/autoconfigure/UserServiceAutoConfigurationTests.java[tag=test-env] ---- +The runner can also be used to display the `ConditionEvaluationReport`. The report can be printed +at `INFO` or `DEBUG` level. The following example shows how to use the `ConditionEvaluationReportLoggingListener` +to print the report in auto-configuration tests. + +[source,java,indent=0] +---- + @Test + public void autoConfigTest { + ConditionEvaluationReportLoggingListener initializer = new ConditionEvaluationReportLoggingListener( + LogLevel.INFO); + ApplicationContextRunner contextRunner = new ApplicationContextRunner() + .withInitializer(initializer).run((context -> { + // Do something... + })); + } +---- + ==== Simulating a Web Context diff --git a/spring-boot-project/spring-boot-test/src/main/java/org/springframework/boot/test/context/runner/AbstractApplicationContextRunner.java b/spring-boot-project/spring-boot-test/src/main/java/org/springframework/boot/test/context/runner/AbstractApplicationContextRunner.java index 9c971ef59d..94550ae4be 100644 --- a/spring-boot-project/spring-boot-test/src/main/java/org/springframework/boot/test/context/runner/AbstractApplicationContextRunner.java +++ b/spring-boot-project/spring-boot-test/src/main/java/org/springframework/boot/test/context/runner/AbstractApplicationContextRunner.java @@ -100,7 +100,7 @@ public abstract class AbstractApplicationContextRunner contextFactory; - private final List> initializers; + private final List> initializers; private final TestPropertyValues environmentProperties; @@ -132,7 +132,7 @@ public abstract class AbstractApplicationContextRunner contextFactory, - List> initializers, + List> initializers, TestPropertyValues environmentProperties, TestPropertyValues systemProperties, ClassLoader classLoader, ApplicationContext parent, List configurations) { @@ -156,7 +156,8 @@ public abstract class AbstractApplicationContextRunner initializer) { + public SELF withInitializer( + ApplicationContextInitializer initializer) { Assert.notNull(initializer, "Initializer must not be null"); return newInstance(this.contextFactory, add(this.initializers, initializer), this.environmentProperties, this.systemProperties, this.classLoader, @@ -259,7 +260,7 @@ public abstract class AbstractApplicationContextRunner contextFactory, - List> initializers, + List> initializers, TestPropertyValues environmentProperties, TestPropertyValues systemProperties, ClassLoader classLoader, ApplicationContext parent, List configurations); diff --git a/spring-boot-project/spring-boot-test/src/main/java/org/springframework/boot/test/context/runner/ApplicationContextRunner.java b/spring-boot-project/spring-boot-test/src/main/java/org/springframework/boot/test/context/runner/ApplicationContextRunner.java index a1b393c561..7401409e9e 100644 --- a/spring-boot-project/spring-boot-test/src/main/java/org/springframework/boot/test/context/runner/ApplicationContextRunner.java +++ b/spring-boot-project/spring-boot-test/src/main/java/org/springframework/boot/test/context/runner/ApplicationContextRunner.java @@ -61,7 +61,7 @@ public class ApplicationContextRunner extends private ApplicationContextRunner( Supplier contextFactory, - List> initializers, + List> initializers, TestPropertyValues environmentProperties, TestPropertyValues systemProperties, ClassLoader classLoader, ApplicationContext parent, List configurations) { @@ -72,7 +72,7 @@ public class ApplicationContextRunner extends @Override protected ApplicationContextRunner newInstance( Supplier contextFactory, - List> initializers, + List> initializers, TestPropertyValues environmentProperties, TestPropertyValues systemProperties, ClassLoader classLoader, ApplicationContext parent, List configurations) { diff --git a/spring-boot-project/spring-boot-test/src/main/java/org/springframework/boot/test/context/runner/ReactiveWebApplicationContextRunner.java b/spring-boot-project/spring-boot-test/src/main/java/org/springframework/boot/test/context/runner/ReactiveWebApplicationContextRunner.java index 2df945cc3a..3f582a7b1c 100644 --- a/spring-boot-project/spring-boot-test/src/main/java/org/springframework/boot/test/context/runner/ReactiveWebApplicationContextRunner.java +++ b/spring-boot-project/spring-boot-test/src/main/java/org/springframework/boot/test/context/runner/ReactiveWebApplicationContextRunner.java @@ -61,7 +61,7 @@ public final class ReactiveWebApplicationContextRunner extends private ReactiveWebApplicationContextRunner( Supplier contextFactory, - List> initializers, + List> initializers, TestPropertyValues environmentProperties, TestPropertyValues systemProperties, ClassLoader classLoader, ApplicationContext parent, List configurations) { @@ -72,7 +72,7 @@ public final class ReactiveWebApplicationContextRunner extends @Override protected ReactiveWebApplicationContextRunner newInstance( Supplier contextFactory, - List> initializers, + List> initializers, TestPropertyValues environmentProperties, TestPropertyValues systemProperties, ClassLoader classLoader, ApplicationContext parent, List configurations) { diff --git a/spring-boot-project/spring-boot-test/src/main/java/org/springframework/boot/test/context/runner/WebApplicationContextRunner.java b/spring-boot-project/spring-boot-test/src/main/java/org/springframework/boot/test/context/runner/WebApplicationContextRunner.java index 8a5924c9c2..ff76e9b8df 100644 --- a/spring-boot-project/spring-boot-test/src/main/java/org/springframework/boot/test/context/runner/WebApplicationContextRunner.java +++ b/spring-boot-project/spring-boot-test/src/main/java/org/springframework/boot/test/context/runner/WebApplicationContextRunner.java @@ -65,7 +65,7 @@ public final class WebApplicationContextRunner extends private WebApplicationContextRunner( Supplier contextFactory, - List> initializers, + List> initializers, TestPropertyValues environmentProperties, TestPropertyValues systemProperties, ClassLoader classLoader, ApplicationContext parent, List configurations) { @@ -76,7 +76,7 @@ public final class WebApplicationContextRunner extends @Override protected WebApplicationContextRunner newInstance( Supplier contextFactory, - List> initializers, + List> initializers, TestPropertyValues environmentProperties, TestPropertyValues systemProperties, ClassLoader classLoader, ApplicationContext parent, List configurations) {