Restore use of ReactorResourceFactory

This commit configures ReactorClientHttpConnectorBuilder with the
ReactorResourceFactory bean from the context.

See gh-46673

Signed-off-by: Dmytro Nosan <dimanosan@gmail.com>
This commit is contained in:
Dmytro Nosan
2025-08-06 16:33:09 +02:00
committed by Stéphane Nicoll
parent b209bc1df4
commit b57b6c4e27
3 changed files with 30 additions and 6 deletions
@@ -31,6 +31,7 @@ import org.springframework.boot.autoconfigure.ssl.SslAutoConfiguration;
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.Conditional;
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 @@ public class ClientHttpConnectorAutoConfiguration implements BeanClassLoaderAwar
@Import(ReactorNettyConfigurations.ReactorResourceFactoryConfiguration.class)
static class ReactorNetty {
@Bean
@Order(0)
ClientHttpConnectorBuilderCustomizer<ReactorClientHttpConnectorBuilder> reactorResourceFactoryClientHttpConnectorBuilderCustomizer(
ReactorResourceFactory reactorResourceFactory) {
return (builder) -> builder.withReactorResourceFactory(reactorResourceFactory);
}
}
}
@@ -25,13 +25,10 @@ import org.springframework.boot.autoconfigure.AutoConfiguration;
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<ReactorClientHttpConnectorBuilder> reactorNettyHttpClientMapperClientHttpConnectorBuilderCustomizer(
ReactorResourceFactory reactorResourceFactory,
ObjectProvider<ReactorNettyHttpClientMapper> mapperProvider) {
return applyMappers(mapperProvider.orderedStream().toList());
}
@@ -23,6 +23,7 @@ import java.util.List;
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 @@ class ClientHttpConnectorAutoConfigurationTests {
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 @@ class ClientHttpConnectorAutoConfigurationTests {
@Bean
ReactorResourceFactory customReactorResourceFactory() {
return new ReactorResourceFactory();
ReactorResourceFactory reactorResourceFactory = new ReactorResourceFactory();
reactorResourceFactory.setUseGlobalResources(false);
reactorResourceFactory.setLoopResources(LoopResources.create("custom-loop", 1, true));
return reactorResourceFactory;
}
}