From ab2b04fafdbe5daa57370810bd3985272577f2a7 Mon Sep 17 00:00:00 2001 From: Andy Wilkinson Date: Wed, 20 Jul 2022 20:46:49 +0100 Subject: [PATCH] Find health contributors in ancestor contexts in non-reactive apps Previously, health contributors in a non-reative app were found by retrieving them from the application context rather than via dependency injection. This results in only contributors from the current context being found, with contributors in ancestor contexts ignored. This commit moves to injection of the contributors, aligning the behaviour with that of a reactive application. Closes gh-27308 --- .../health/HealthEndpointConfiguration.java | 12 +++---- .../HealthEndpointAutoConfigurationTests.java | 31 ++++++++++++++++++- 2 files changed, 35 insertions(+), 8 deletions(-) diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/health/HealthEndpointConfiguration.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/health/HealthEndpointConfiguration.java index a63d67739e..9f5082d7c3 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/health/HealthEndpointConfiguration.java +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/health/HealthEndpointConfiguration.java @@ -77,11 +77,10 @@ class HealthEndpointConfiguration { @Bean @ConditionalOnMissingBean HealthContributorRegistry healthContributorRegistry(ApplicationContext applicationContext, - HealthEndpointGroups groups) { - Map healthContributors = new LinkedHashMap<>( - applicationContext.getBeansOfType(HealthContributor.class)); + HealthEndpointGroups groups, Map healthContributors, + Map reactiveHealthContributors) { if (ClassUtils.isPresent("reactor.core.publisher.Flux", applicationContext.getClassLoader())) { - healthContributors.putAll(new AdaptedReactiveHealthContributors(applicationContext).get()); + healthContributors.putAll(new AdaptedReactiveHealthContributors(reactiveHealthContributors).get()); } return new AutoConfiguredHealthContributorRegistry(healthContributors, groups.getNames()); } @@ -137,10 +136,9 @@ class HealthEndpointConfiguration { private final Map adapted; - AdaptedReactiveHealthContributors(ApplicationContext applicationContext) { + AdaptedReactiveHealthContributors(Map reactiveContributors) { Map adapted = new LinkedHashMap<>(); - applicationContext.getBeansOfType(ReactiveHealthContributor.class) - .forEach((name, contributor) -> adapted.put(name, adapt(contributor))); + reactiveContributors.forEach((name, contributor) -> adapted.put(name, adapt(contributor))); this.adapted = Collections.unmodifiableMap(adapted); } diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/health/HealthEndpointAutoConfigurationTests.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/health/HealthEndpointAutoConfigurationTests.java index 4f43c0b95f..a9ad0df229 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/health/HealthEndpointAutoConfigurationTests.java +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/health/HealthEndpointAutoConfigurationTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2021 the original author or authors. + * Copyright 2012-2022 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. @@ -17,6 +17,7 @@ package org.springframework.boot.actuate.autoconfigure.health; import java.util.Collections; +import java.util.Map; import org.junit.jupiter.api.Test; import reactor.core.publisher.Flux; @@ -45,8 +46,10 @@ import org.springframework.boot.actuate.health.ReactiveHealthEndpointWebExtensio import org.springframework.boot.actuate.health.ReactiveHealthIndicator; import org.springframework.boot.actuate.health.Status; import org.springframework.boot.actuate.health.StatusAggregator; +import org.springframework.boot.actuate.health.SystemHealth; import org.springframework.boot.autoconfigure.AutoConfigurations; import org.springframework.boot.test.context.FilteredClassLoader; +import org.springframework.boot.test.context.runner.ApplicationContextRunner; import org.springframework.boot.test.context.runner.ReactiveWebApplicationContextRunner; import org.springframework.boot.test.context.runner.WebApplicationContextRunner; import org.springframework.context.annotation.Bean; @@ -264,6 +267,32 @@ class HealthEndpointAutoConfigurationTests { }); } + @Test + void runWithIndicatorsInParentContextFindsIndicators() { + new ApplicationContextRunner().withUserConfiguration(HealthIndicatorsConfiguration.class) + .run((parent) -> new WebApplicationContextRunner().withConfiguration(AutoConfigurations + .of(HealthContributorAutoConfiguration.class, HealthEndpointAutoConfiguration.class)) + .withParent(parent).run((context) -> { + HealthComponent health = context.getBean(HealthEndpoint.class).health(); + Map components = ((SystemHealth) health).getComponents(); + assertThat(components).containsKeys("additional", "ping", "simple"); + })); + } + + @Test + void runWithReactiveContextAndIndicatorsInParentContextFindsIndicators() { + new ApplicationContextRunner().withUserConfiguration(HealthIndicatorsConfiguration.class) + .run((parent) -> new ReactiveWebApplicationContextRunner() + .withConfiguration(AutoConfigurations.of(HealthContributorAutoConfiguration.class, + HealthEndpointAutoConfiguration.class, WebEndpointAutoConfiguration.class, + EndpointAutoConfiguration.class)) + .withParent(parent).run((context) -> { + HealthComponent health = context.getBean(HealthEndpoint.class).health(); + Map components = ((SystemHealth) health).getComponents(); + assertThat(components).containsKeys("additional", "ping", "simple"); + })); + } + @Configuration(proxyBeanMethods = false) static class HealthIndicatorsConfiguration {