spring-projects / spring-projects/spring-boot
ConditionEvaluationReportLoggingListener registered in ApplicationContextRunner should log the report if the context fails to start
Nobody has claimed this yet.
- Dominant language
- Java
- Stars
- 81.5k
- Forks
- 42.7k
- Avg merge
- 2d 4h
- Merged PRs (30d)
- 65
Description
In order to help me diagnose failures of test (in particular when context fails to be initialized), I need to get a report such as the following to understand whether my @ConditionalOnProperty logic is correct.
@Configuration
@ConditionalOnProperty(value= DynamicCatalogConstants.OPT_IN_PROPERTY)
@EnableConfigurationProperties
public class DynamicCatalogServiceAutoConfiguration {
[...]
20-11-2020 14:47:02.380 [main] DEBUG o.s.b.a.l.ConditionEvaluationReportLoggingListener.logAutoConfigurationReport -
============================
CONDITIONS EVALUATION REPORT
============================
Positive matches:
-----------------
DynamicCatalogServiceAutoConfiguration matched:
- @ConditionalOnProperty (osbcmdb.dynamic-catalog.enabled) matched (OnPropertyCondition)
Negative matches:
-----------------
None
Exclusions:
-----------
None
Unconditional classes:
----------------------
None
I'm using spring-boot 2.3.6.
Observed behavior
The condition report is not invoked when context fails to start
Instead of a condition report, only the following context init exception is displayed
20-11-2020 14:24:10.609 [main] WARN o.s.c.a.AnnotationConfigApplicationContext.refresh - Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.support.BeanDefinitionOverrideException: Invalid bean definition with name 'dynamicCatalogService' defined in com.orange.oss.osbcmdb.catalog.DynamicCatalogServiceAutoConfigurationTest$SingleServiceDefinitionAnswerAutoConfig: Cannot register bean definition [Root bean: class [null]; scope=; abstract=false; lazyInit=null; autowireMode=3; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=dynamicCatalogServiceAutoConfigurationTest.SingleServiceDefinitionAnswerAutoConfig; factoryMethodName=dynamicCatalogService; initMethodName=null; destroyMethodName=(inferred); defined in com.orange.oss.osbcmdb.catalog.DynamicCatalogServiceAutoConfigurationTest$SingleServiceDefinitionAnswerAutoConfig] for bean 'dynamicCatalogService': There is already [Root bean: class [null]; scope=; abstract=false; lazyInit=null; autowireMode=3; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=dynamicCatalogServiceAutoConfiguration; factoryMethodName=dynamicCatalogService; initMethodName=null; destroyMethodName=(inferred); defined in com.orange.oss.osbcmdb.catalog.DynamicCatalogServiceAutoConfiguration] bound.
java.lang.IllegalStateException: Unstarted application context org.springframework.boot.test.context.assertj.AssertableApplicationContext[startupFailure=org.springframework.beans.factory.support.BeanDefinitionOverrideException] failed to start
at org.springframework.boot.test.context.assertj.AssertProviderApplicationContextInvocationHandler.getStartedApplicationContext(AssertProviderApplicationContextInvocationHandler.java:156)
at org.springframework.boot.test.context.assertj.AssertProviderApplicationContextInvocationHandler.invokeApplicationContextMethod(AssertProviderApplicationContextInvocationHandler.java:147)
at org.springframework.boot.test.context.assertj.AssertProviderApplicationContextInvocationHandler.invoke(AssertProviderApplicationContextInvocationHandler.java:85)
at com.sun.proxy.$Proxy20.getBean(Unknown Source)
at com.orange.oss.osbcmdb.catalog.DynamicCatalogServiceAutoConfigurationTest.lambda$dynamicServiceLoadWhenOptInProperty$2(DynamicCatalogServiceAutoConfigurationTest.java:84)
Sample code:
@Test
void dynamicServiceLoadWhenOptInProperty() {
ConditionEvaluationReportLoggingListener initializer = new ConditionEvaluationReportLoggingListener(LogLevel.INFO);
ApplicationContextRunner contextRunner = new ApplicationContextRunner()
.withInitializer(initializer)
.withConfiguration(AutoConfigurations.of(
SingleServiceDefinitionAnswerAutoConfig.class,
DynamicCatalogServiceAutoConfiguration.class,
MockedMaintenanceInfoFormatterServiceConfig.class
))
.withPropertyValues(DynamicCatalogConstants.OPT_IN_PROPERTY + "=true");
contextRunner.run(context -> {
Catalog catalog = context.getBean(Catalog.class);
assertThat(catalog.getServiceDefinitions()).isNotEmpty();
assertThat(context).hasSingleBean(Catalog.class);
});
}
What I tried
The logging level is properly set to debug.
Stepping into the debugger, it seems that the ConditionEvaluationReportLoggingListener is never invoked for event notifications.
I however managed to manually trigger the condition report printed by invoking it explicitly with the debugger:
References
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start by reproducing the supplied ApplicationContextRunner example with a failing context and inspect how ConditionEvaluationReportLoggingListener receives event notifications. Confirm the behavior when startup fails, then verify that the condition evaluation report is logged alongside the failure diagnostics.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- java, spring-boot
- Domain
- testing
- Issue type
- Bug
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 55/100