From 3d0e6f3a2ce3351eba8dcfd7f3b54459c124c902 Mon Sep 17 00:00:00 2001 From: Andrey Litvitski Date: Tue, 3 Mar 2026 15:33:58 +0300 Subject: [PATCH] Fix health auto-configuration condition timing Fixes a timing issue. Currently, the logic in GrpcServerHealthAutoConfiguration.OnHealthIndicatorPathsCondition is incorrect; it can never find the bean, since the condition itself is checked before the beans themselves are created. The tests passed because we were passing the bean itself, not the autoconfiguration with the bean. Closes: gh-380 Signed-off-by: Andrey Litvitski --- .../GrpcServerHealthAutoConfiguration.java | 8 +++++++- ...rpcServerHealthAutoConfigurationTests.java | 20 +++++++++++++++++++ 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/spring-grpc-server-spring-boot-autoconfigure/src/main/java/org/springframework/boot/grpc/server/autoconfigure/health/GrpcServerHealthAutoConfiguration.java b/spring-grpc-server-spring-boot-autoconfigure/src/main/java/org/springframework/boot/grpc/server/autoconfigure/health/GrpcServerHealthAutoConfiguration.java index 2ef51ede..6e348e38 100644 --- a/spring-grpc-server-spring-boot-autoconfigure/src/main/java/org/springframework/boot/grpc/server/autoconfigure/health/GrpcServerHealthAutoConfiguration.java +++ b/spring-grpc-server-spring-boot-autoconfigure/src/main/java/org/springframework/boot/grpc/server/autoconfigure/health/GrpcServerHealthAutoConfiguration.java @@ -43,6 +43,7 @@ import org.springframework.context.annotation.ConditionContext; import org.springframework.context.annotation.Conditional; import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.ConfigurationCondition; import org.springframework.core.type.AnnotatedTypeMetadata; import org.springframework.scheduling.annotation.EnableScheduling; @@ -129,7 +130,12 @@ public ConditionOutcome getMatchOutcome(ConditionContext context, AnnotatedTypeM } - static class OnHealthDefaultEnablementCondition extends SpringBootCondition { + static class OnHealthDefaultEnablementCondition extends SpringBootCondition implements ConfigurationCondition { + + @Override + public ConfigurationCondition.ConfigurationPhase getConfigurationPhase() { + return ConfigurationCondition.ConfigurationPhase.REGISTER_BEAN; + } @Override public ConditionOutcome getMatchOutcome(ConditionContext context, AnnotatedTypeMetadata metadata) { diff --git a/spring-grpc-server-spring-boot-autoconfigure/src/test/java/org/springframework/boot/grpc/server/autoconfigure/health/GrpcServerHealthAutoConfigurationTests.java b/spring-grpc-server-spring-boot-autoconfigure/src/test/java/org/springframework/boot/grpc/server/autoconfigure/health/GrpcServerHealthAutoConfigurationTests.java index c42b4a18..a54d0c46 100644 --- a/spring-grpc-server-spring-boot-autoconfigure/src/test/java/org/springframework/boot/grpc/server/autoconfigure/health/GrpcServerHealthAutoConfigurationTests.java +++ b/spring-grpc-server-spring-boot-autoconfigure/src/test/java/org/springframework/boot/grpc/server/autoconfigure/health/GrpcServerHealthAutoConfigurationTests.java @@ -26,6 +26,7 @@ import org.junit.jupiter.api.Test; import org.mockito.Mockito; +import org.springframework.boot.autoconfigure.AutoConfiguration; import org.springframework.boot.autoconfigure.AutoConfigurations; import org.springframework.boot.autoconfigure.task.TaskSchedulingAutoConfiguration; import org.springframework.boot.grpc.server.autoconfigure.health.GrpcServerHealthAutoConfiguration.ActuatorHealthAdapterConfiguration; @@ -36,6 +37,7 @@ import org.springframework.boot.test.context.FilteredClassLoader; import org.springframework.boot.test.context.runner.ApplicationContextRunner; import org.springframework.context.ConfigurableApplicationContext; +import org.springframework.context.annotation.Bean; import org.springframework.grpc.server.GrpcServerFactory; import org.springframework.util.StringUtils; @@ -181,6 +183,24 @@ private String beanDefinitionNameForConfigClass(Class configClass) { return StringUtils.uncapitalize(fullName); } + @Test + void whenBindableServiceRegisteredViaAutoConfigurationHealthIsEnabled() { + new ApplicationContextRunner() + .withConfiguration(AutoConfigurations.of(LateBindableServiceAutoConfiguration.class, + GrpcServerHealthAutoConfiguration.class)) + .run((context) -> assertThat(context).hasSingleBean(GrpcServerHealthAutoConfiguration.class)); + } + + @AutoConfiguration(before = GrpcServerHealthAutoConfiguration.class) + static class LateBindableServiceAutoConfiguration { + + @Bean + BindableService bindableService() { + return Mockito.mock(BindableService.class); + } + + } + @Nested class ActuatorHealthAdapterConfigurationTests {