diff --git a/module/spring-boot-webflux/src/main/java/org/springframework/boot/webflux/autoconfigure/WebFluxAutoConfiguration.java b/module/spring-boot-webflux/src/main/java/org/springframework/boot/webflux/autoconfigure/WebFluxAutoConfiguration.java index f06694403cc..d19f3a49b06 100644 --- a/module/spring-boot-webflux/src/main/java/org/springframework/boot/webflux/autoconfigure/WebFluxAutoConfiguration.java +++ b/module/spring-boot-webflux/src/main/java/org/springframework/boot/webflux/autoconfigure/WebFluxAutoConfiguration.java @@ -25,6 +25,9 @@ import org.apache.commons.logging.LogFactory; import org.jspecify.annotations.Nullable; import reactor.core.publisher.Mono; +import org.springframework.aot.hint.RuntimeHints; +import org.springframework.aot.hint.RuntimeHintsRegistrar; +import org.springframework.aot.hint.TypeReference; import org.springframework.beans.factory.ListableBeanFactory; import org.springframework.beans.factory.ObjectProvider; import org.springframework.boot.autoconfigure.AutoConfiguration; @@ -308,6 +311,7 @@ public final class WebFluxAutoConfiguration { */ @Configuration(proxyBeanMethods = false) @EnableConfigurationProperties({ WebProperties.class, ServerProperties.class }) + @ImportRuntimeHints(WebFluxValidatorRuntimeHints.class) static class EnableWebFluxConfiguration extends DelegatingWebFluxConfiguration { private final WebFluxProperties webFluxProperties; @@ -452,4 +456,14 @@ public final class WebFluxAutoConfiguration { } + static class WebFluxValidatorRuntimeHints implements RuntimeHintsRegistrar { + + @Override + public void registerHints(RuntimeHints hints, @Nullable ClassLoader classLoader) { + hints.reflection() + .registerType(TypeReference.of("org.springframework.boot.validation.autoconfigure.ValidatorAdapter")); + } + + } + } diff --git a/module/spring-boot-webflux/src/test/java/org/springframework/boot/webflux/autoconfigure/WebFluxAutoConfigurationTests.java b/module/spring-boot-webflux/src/test/java/org/springframework/boot/webflux/autoconfigure/WebFluxAutoConfigurationTests.java index 7ca7f5ea8a3..43084d0f1c4 100644 --- a/module/spring-boot-webflux/src/test/java/org/springframework/boot/webflux/autoconfigure/WebFluxAutoConfigurationTests.java +++ b/module/spring-boot-webflux/src/test/java/org/springframework/boot/webflux/autoconfigure/WebFluxAutoConfigurationTests.java @@ -46,6 +46,8 @@ import org.junit.jupiter.params.provider.ValueSource; import reactor.core.publisher.Mono; import org.springframework.aop.support.AopUtils; +import org.springframework.aot.hint.RuntimeHints; +import org.springframework.aot.hint.predicate.RuntimeHintsPredicates; import org.springframework.boot.autoconfigure.AutoConfigurations; import org.springframework.boot.autoconfigure.task.TaskExecutionAutoConfiguration; import org.springframework.boot.http.codec.CodecCustomizer; @@ -59,6 +61,7 @@ import org.springframework.boot.web.context.reactive.ReactiveWebApplicationConte import org.springframework.boot.web.server.autoconfigure.ServerProperties; import org.springframework.boot.web.server.reactive.MockReactiveWebServerFactory; import org.springframework.boot.webflux.autoconfigure.WebFluxAutoConfiguration.WebFluxConfig; +import org.springframework.boot.webflux.autoconfigure.WebFluxAutoConfiguration.WebFluxValidatorRuntimeHints; import org.springframework.boot.webflux.autoconfigure.WebFluxAutoConfigurationTests.OrderedControllerAdviceBeansConfiguration.HighestOrderedControllerAdvice; import org.springframework.boot.webflux.autoconfigure.WebFluxAutoConfigurationTests.OrderedControllerAdviceBeansConfiguration.LowestOrderedControllerAdvice; import org.springframework.boot.webflux.filter.OrderedHiddenHttpMethodFilter; @@ -907,6 +910,13 @@ class WebFluxAutoConfigurationTests { }); } + @Test + void registersRuntimeHintsForValidatorCreation() { + RuntimeHints hints = new RuntimeHints(); + new WebFluxValidatorRuntimeHints().registerHints(hints, getClass().getClassLoader()); + assertThat(RuntimeHintsPredicates.reflection().onType(ValidatorAdapter.class)).accepts(hints); + } + private ContextConsumer assertExchangeWithSession( Consumer exchange) { return (context) -> { diff --git a/module/spring-boot-webmvc/src/main/java/org/springframework/boot/webmvc/autoconfigure/WebMvcAutoConfiguration.java b/module/spring-boot-webmvc/src/main/java/org/springframework/boot/webmvc/autoconfigure/WebMvcAutoConfiguration.java index 28e042fb836..da1e334a302 100644 --- a/module/spring-boot-webmvc/src/main/java/org/springframework/boot/webmvc/autoconfigure/WebMvcAutoConfiguration.java +++ b/module/spring-boot-webmvc/src/main/java/org/springframework/boot/webmvc/autoconfigure/WebMvcAutoConfiguration.java @@ -28,6 +28,9 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.jspecify.annotations.Nullable; +import org.springframework.aot.hint.RuntimeHints; +import org.springframework.aot.hint.RuntimeHintsRegistrar; +import org.springframework.aot.hint.TypeReference; import org.springframework.beans.factory.BeanFactory; import org.springframework.beans.factory.ListableBeanFactory; import org.springframework.beans.factory.NoSuchBeanDefinitionException; @@ -435,6 +438,7 @@ public final class WebMvcAutoConfiguration { */ @Configuration(proxyBeanMethods = false) @EnableConfigurationProperties(WebProperties.class) + @ImportRuntimeHints(MvcValidatorRuntimeHints.class) static class EnableWebMvcConfiguration extends DelegatingWebMvcConfiguration implements ResourceLoaderAware { private final Resources resourceProperties; @@ -724,4 +728,14 @@ public final class WebMvcAutoConfiguration { } + static class MvcValidatorRuntimeHints implements RuntimeHintsRegistrar { + + @Override + public void registerHints(RuntimeHints hints, @Nullable ClassLoader classLoader) { + hints.reflection() + .registerType(TypeReference.of("org.springframework.boot.validation.autoconfigure.ValidatorAdapter")); + } + + } + } diff --git a/module/spring-boot-webmvc/src/test/java/org/springframework/boot/webmvc/autoconfigure/WebMvcAutoConfigurationTests.java b/module/spring-boot-webmvc/src/test/java/org/springframework/boot/webmvc/autoconfigure/WebMvcAutoConfigurationTests.java index 362228a292c..38c329ca428 100644 --- a/module/spring-boot-webmvc/src/test/java/org/springframework/boot/webmvc/autoconfigure/WebMvcAutoConfigurationTests.java +++ b/module/spring-boot-webmvc/src/test/java/org/springframework/boot/webmvc/autoconfigure/WebMvcAutoConfigurationTests.java @@ -45,6 +45,8 @@ import org.junit.jupiter.api.Test; import org.mockito.InOrder; import org.springframework.aop.support.AopUtils; +import org.springframework.aot.hint.RuntimeHints; +import org.springframework.aot.hint.predicate.RuntimeHintsPredicates; import org.springframework.boot.autoconfigure.AutoConfigurations; import org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration; import org.springframework.boot.autoconfigure.task.TaskExecutionAutoConfiguration; @@ -64,6 +66,7 @@ import org.springframework.boot.web.server.servlet.ServletWebServerFactory; import org.springframework.boot.web.server.servlet.context.AnnotationConfigServletWebServerApplicationContext; import org.springframework.boot.web.servlet.FilterRegistrationBean; import org.springframework.boot.web.servlet.ServletRegistrationBean; +import org.springframework.boot.webmvc.autoconfigure.WebMvcAutoConfiguration.MvcValidatorRuntimeHints; import org.springframework.boot.webmvc.autoconfigure.WebMvcAutoConfiguration.WebMvcAutoConfigurationAdapter; import org.springframework.boot.webmvc.autoconfigure.WebMvcAutoConfigurationTests.OrderedControllerAdviceBeansConfiguration.HighestOrderedControllerAdvice; import org.springframework.boot.webmvc.autoconfigure.WebMvcAutoConfigurationTests.OrderedControllerAdviceBeansConfiguration.LowestOrderedControllerAdvice; @@ -1137,6 +1140,13 @@ class WebMvcAutoConfigurationTests { }); } + @Test + void registersRuntimeHintsForValidatorCreation() { + RuntimeHints hints = new RuntimeHints(); + new MvcValidatorRuntimeHints().registerHints(hints, getClass().getClassLoader()); + assertThat(RuntimeHintsPredicates.reflection().onType(ValidatorAdapter.class)).accepts(hints); + } + private void assertResourceHttpRequestHandler(AssertableWebApplicationContext context, Consumer handlerConsumer) { Map handlerMap = getHandlerMap(context.getBean("resourceHandlerMapping", HandlerMapping.class));