Guard reactive Cloud Foundry health extension

Move the reactive Cloud Foundry health endpoint extension into a
health-specific configuration guarded by @ConditionalOnClass. When
spring-boot-health is absent, scanning the outer configuration attempts
to resolve ReactiveHealthEndpointWebExtension and causes context refresh
to fail.

See gh-50916

Signed-off-by: Lee JiWon <dlwldnjs1009@gmail.com>
This commit is contained in:
Lee JiWon
2026-07-14 08:37:44 +02:00
committed by Stéphane Nicoll
parent d2b538be08
commit bda889997d
2 changed files with 36 additions and 9 deletions
@@ -83,15 +83,6 @@ public final class CloudFoundryReactiveActuatorAutoConfiguration {
private static final String BASE_PATH = "/cloudfoundryapplication";
@Bean
@ConditionalOnMissingBean
@ConditionalOnAvailableEndpoint
@ConditionalOnBean({ HealthEndpoint.class, ReactiveHealthEndpointWebExtension.class })
CloudFoundryReactiveHealthEndpointWebExtension cloudFoundryReactiveHealthEndpointWebExtension(
ReactiveHealthEndpointWebExtension reactiveHealthEndpointWebExtension) {
return new CloudFoundryReactiveHealthEndpointWebExtension(reactiveHealthEndpointWebExtension);
}
@Bean
@ConditionalOnMissingBean
@ConditionalOnAvailableEndpoint
@@ -151,6 +142,21 @@ public final class CloudFoundryReactiveActuatorAutoConfiguration {
return corsConfiguration;
}
@Configuration(proxyBeanMethods = false)
@ConditionalOnClass(HealthEndpoint.class)
static class HealthConfiguration {
@Bean
@ConditionalOnMissingBean
@ConditionalOnAvailableEndpoint
@ConditionalOnBean({ HealthEndpoint.class, ReactiveHealthEndpointWebExtension.class })
CloudFoundryReactiveHealthEndpointWebExtension cloudFoundryReactiveHealthEndpointWebExtension(
ReactiveHealthEndpointWebExtension reactiveHealthEndpointWebExtension) {
return new CloudFoundryReactiveHealthEndpointWebExtension(reactiveHealthEndpointWebExtension);
}
}
@Configuration(proxyBeanMethods = false)
@ConditionalOnClass(MatcherSecurityWebFilterChain.class)
static class IgnoredPathsSecurityConfiguration {
@@ -59,6 +59,7 @@ import org.springframework.boot.ssl.SslBundle;
import org.springframework.boot.ssl.jks.JksSslStoreBundle;
import org.springframework.boot.ssl.jks.JksSslStoreDetails;
import org.springframework.boot.test.context.runner.ReactiveWebApplicationContextRunner;
import org.springframework.boot.testsupport.classpath.ClassPathExclusions;
import org.springframework.boot.testsupport.classpath.resources.WithPackageResources;
import org.springframework.boot.testsupport.classpath.resources.WithResource;
import org.springframework.boot.webclient.WebClientCustomizer;
@@ -108,6 +109,17 @@ class CloudFoundryReactiveActuatorAutoConfigurationTests {
ProjectInfoAutoConfiguration.class, CloudFoundryReactiveActuatorAutoConfiguration.class))
.withUserConfiguration(UserDetailsServiceConfiguration.class);
private final ReactiveWebApplicationContextRunner withoutHealthContextRunner = new ReactiveWebApplicationContextRunner()
.withConfiguration(
AutoConfigurations.of(ReactiveWebSecurityAutoConfiguration.class, WebFluxAutoConfiguration.class,
JacksonAutoConfiguration.class, HttpMessageConvertersAutoConfiguration.class,
PropertyPlaceholderAutoConfiguration.class, WebClientCustomizerConfig.class,
WebClientAutoConfiguration.class, ManagementContextAutoConfiguration.class,
EndpointAutoConfiguration.class, WebEndpointAutoConfiguration.class,
InfoContributorAutoConfiguration.class, InfoEndpointAutoConfiguration.class,
ProjectInfoAutoConfiguration.class, CloudFoundryReactiveActuatorAutoConfiguration.class))
.withUserConfiguration(UserDetailsServiceConfiguration.class);
private static final String BASE_PATH = "/cloudfoundryapplication";
@AfterEach
@@ -115,6 +127,15 @@ class CloudFoundryReactiveActuatorAutoConfigurationTests {
HttpResources.reset();
}
@Test
@ClassPathExclusions(packages = "org.springframework.boot.health.actuate.endpoint")
void refreshSucceedsWithoutHealth() {
this.withoutHealthContextRunner
.withPropertyValues("VCAP_APPLICATION:---", "vcap.application.application_id:my-app-id",
"vcap.application.cf_api:https://my-cloud-controller.com")
.run((context) -> assertThat(context).hasNotFailed());
}
@Test
void cloudFoundryPlatformActive() {
this.contextRunner