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
pull/32521/head
Andy Wilkinson 2 years ago
parent 5afa04f3cd
commit ab2b04fafd

@ -77,11 +77,10 @@ class HealthEndpointConfiguration {
@Bean
@ConditionalOnMissingBean
HealthContributorRegistry healthContributorRegistry(ApplicationContext applicationContext,
HealthEndpointGroups groups) {
Map<String, HealthContributor> healthContributors = new LinkedHashMap<>(
applicationContext.getBeansOfType(HealthContributor.class));
HealthEndpointGroups groups, Map<String, HealthContributor> healthContributors,
Map<String, ReactiveHealthContributor> 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<String, HealthContributor> adapted;
AdaptedReactiveHealthContributors(ApplicationContext applicationContext) {
AdaptedReactiveHealthContributors(Map<String, ReactiveHealthContributor> reactiveContributors) {
Map<String, HealthContributor> 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);
}

@ -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<String, HealthComponent> 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<String, HealthComponent> components = ((SystemHealth) health).getComponents();
assertThat(components).containsKeys("additional", "ping", "simple");
}));
}
@Configuration(proxyBeanMethods = false)
static class HealthIndicatorsConfiguration {

Loading…
Cancel
Save