From 7d39e00e036688b9f87158653b11bc70edd0aed7 Mon Sep 17 00:00:00 2001 From: Dmytro Nosan Date: Mon, 4 Aug 2025 22:52:56 +0300 Subject: [PATCH] Configure ReactorClientHttpConnectorBuilder with context's ReactorResourceFactory Signed-off-by: Dmytro Nosan --- .../ClientHttpConnectorAutoConfiguration.java | 10 +++++++++ .../ClientHttpConnectorAutoConfiguration.java | 5 ----- ...ntHttpConnectorAutoConfigurationTests.java | 21 ++++++++++++++++++- 3 files changed, 30 insertions(+), 6 deletions(-) diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/http/client/reactive/ClientHttpConnectorAutoConfiguration.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/http/client/reactive/ClientHttpConnectorAutoConfiguration.java index 7c2770d0bdd0..e074beff63a0 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/http/client/reactive/ClientHttpConnectorAutoConfiguration.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/http/client/reactive/ClientHttpConnectorAutoConfiguration.java @@ -31,6 +31,7 @@ import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.boot.http.client.reactive.ClientHttpConnectorBuilder; import org.springframework.boot.http.client.reactive.ClientHttpConnectorSettings; +import org.springframework.boot.http.client.reactive.ReactorClientHttpConnectorBuilder; import org.springframework.boot.ssl.SslBundles; import org.springframework.boot.util.LambdaSafe; import org.springframework.context.annotation.Bean; @@ -38,6 +39,8 @@ import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Import; import org.springframework.context.annotation.Lazy; +import org.springframework.core.annotation.Order; +import org.springframework.http.client.ReactorResourceFactory; import org.springframework.http.client.reactive.ClientHttpConnector; /** @@ -103,6 +106,13 @@ ClientHttpConnector clientHttpConnector(ClientHttpConnectorBuilder clientHttp @Import(ReactorNettyConfigurations.ReactorResourceFactoryConfiguration.class) static class ReactorNetty { + @Bean + @Order(0) + ClientHttpConnectorBuilderCustomizer reactorResourceFactoryClientHttpConnectorBuilderCustomizer( + ReactorResourceFactory reactorResourceFactory) { + return (builder) -> builder.withReactorResourceFactory(reactorResourceFactory); + } + } } diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/reactive/function/client/ClientHttpConnectorAutoConfiguration.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/reactive/function/client/ClientHttpConnectorAutoConfiguration.java index 87663ef25c07..635e6f627750 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/reactive/function/client/ClientHttpConnectorAutoConfiguration.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/reactive/function/client/ClientHttpConnectorAutoConfiguration.java @@ -25,13 +25,10 @@ import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.http.client.reactive.ClientHttpConnectorBuilderCustomizer; -import org.springframework.boot.autoconfigure.reactor.netty.ReactorNettyConfigurations.ReactorResourceFactoryConfiguration; import org.springframework.boot.http.client.reactive.ReactorClientHttpConnectorBuilder; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; -import org.springframework.context.annotation.Import; import org.springframework.core.annotation.Order; -import org.springframework.http.client.ReactorResourceFactory; import org.springframework.web.reactive.function.client.WebClient; /** @@ -52,14 +49,12 @@ public class ClientHttpConnectorAutoConfiguration { @Configuration(proxyBeanMethods = false) @ConditionalOnClass(HttpClient.class) - @Import(ReactorResourceFactoryConfiguration.class) @SuppressWarnings("removal") static class ReactorNetty { @Bean @Order(0) ClientHttpConnectorBuilderCustomizer reactorNettyHttpClientMapperClientHttpConnectorBuilderCustomizer( - ReactorResourceFactory reactorResourceFactory, ObjectProvider mapperProvider) { return applyMappers(mapperProvider.orderedStream().toList()); } diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/http/client/reactive/ClientHttpConnectorAutoConfigurationTests.java b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/http/client/reactive/ClientHttpConnectorAutoConfigurationTests.java index a3af3b6cfe69..6dd305e13132 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/http/client/reactive/ClientHttpConnectorAutoConfigurationTests.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/http/client/reactive/ClientHttpConnectorAutoConfigurationTests.java @@ -23,6 +23,7 @@ import org.apache.hc.client5.http.impl.async.HttpAsyncClients; import org.junit.jupiter.api.Test; import reactor.netty.http.client.HttpClient; +import reactor.netty.resources.LoopResources; import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.boot.autoconfigure.AutoConfigurations; @@ -114,6 +115,21 @@ void shouldUseCustomReactorResourceFactory() { assertThat(context).hasSingleBean(ClientHttpConnector.class); assertThat(context).hasSingleBean(ReactorResourceFactory.class); assertThat(context).hasBean("customReactorResourceFactory"); + ClientHttpConnector connector = context.getBean(ClientHttpConnector.class); + assertThat(connector).extracting("httpClient.config.loopResources") + .isEqualTo(context.getBean("customReactorResourceFactory", ReactorResourceFactory.class) + .getLoopResources()); + }); + } + + @Test + void shouldUseReactorResourceFactory() { + this.contextRunner.run((context) -> { + assertThat(context).hasSingleBean(ClientHttpConnector.class); + assertThat(context).hasSingleBean(ReactorResourceFactory.class); + ClientHttpConnector connector = context.getBean(ClientHttpConnector.class); + assertThat(connector).extracting("httpClient.config.loopResources") + .isEqualTo(context.getBean(ReactorResourceFactory.class).getLoopResources()); }); } @@ -190,7 +206,10 @@ static class CustomReactorResourceConfig { @Bean ReactorResourceFactory customReactorResourceFactory() { - return new ReactorResourceFactory(); + ReactorResourceFactory reactorResourceFactory = new ReactorResourceFactory(); + reactorResourceFactory.setUseGlobalResources(false); + reactorResourceFactory.setLoopResources(LoopResources.create("custom-loop", 1, true)); + return reactorResourceFactory; } }