From 5a67f5707eef5f41807a091b3ea3d612e239c151 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phane=20Nicoll?= Date: Mon, 10 Nov 2025 15:19:14 +0100 Subject: [PATCH] Replace calls to deprecated setConnectionTimeout method Replace calls to the recently deprecated `setConnectionTimeout` method of `HttpComponentsClientHttpRequestFactoryBuilder`. This commit also introduces a `withConnectionConfigCustomizer` and allows connection timeouts settings to be used. Closes gh-48031 --- .../HttpClientAutoConfigurationTests.java | 14 +++++ .../test/web/client/TestRestTemplate.java | 32 +++++----- ...onentsClientHttpRequestFactoryBuilder.java | 62 ++++++++++++++----- ...sClientHttpRequestFactoryBuilderTests.java | 23 ++++--- ...tpRequestFactoriesHttpComponentsTests.java | 42 +++++++------ .../web/client/RestTemplateBuilderTests.java | 16 ++++- 6 files changed, 128 insertions(+), 61 deletions(-) diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/http/client/HttpClientAutoConfigurationTests.java b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/http/client/HttpClientAutoConfigurationTests.java index 64f3c51bc1e..894b6bcc981 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/http/client/HttpClientAutoConfigurationTests.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/http/client/HttpClientAutoConfigurationTests.java @@ -72,6 +72,20 @@ class HttpClientAutoConfigurationTests { }); } + @Test + void configuresClientHttpRequestFactorySettingsUsingDeprecatedProperties() { + this.contextRunner.withPropertyValues(sslPropertyValues().toArray(String[]::new)) + .withPropertyValues("spring.http.client.redirects=dont-follow", "spring.http.client.connect-timeout=10s", + "spring.http.client.read-timeout=20s", "spring.http.client.ssl.bundle=test") + .run((context) -> { + ClientHttpRequestFactorySettings settings = context.getBean(ClientHttpRequestFactorySettings.class); + assertThat(settings.redirects()).isEqualTo(Redirects.DONT_FOLLOW); + assertThat(settings.connectTimeout()).isEqualTo(Duration.ofSeconds(10)); + assertThat(settings.readTimeout()).isEqualTo(Duration.ofSeconds(20)); + assertThat(settings.sslBundle().getKey().getAlias()).isEqualTo("alias1"); + }); + } + private List sslPropertyValues() { List propertyValues = new ArrayList<>(); String location = "classpath:org/springframework/boot/autoconfigure/ssl/"; diff --git a/spring-boot-project/spring-boot-test/src/main/java/org/springframework/boot/test/web/client/TestRestTemplate.java b/spring-boot-project/spring-boot-test/src/main/java/org/springframework/boot/test/web/client/TestRestTemplate.java index 6b7a3a0ad04..c0e33321573 100644 --- a/spring-boot-project/spring-boot-test/src/main/java/org/springframework/boot/test/web/client/TestRestTemplate.java +++ b/spring-boot-project/spring-boot-test/src/main/java/org/springframework/boot/test/web/client/TestRestTemplate.java @@ -30,6 +30,7 @@ import java.util.function.UnaryOperator; import javax.net.ssl.SSLContext; import org.apache.hc.client5.http.classic.HttpClient; +import org.apache.hc.client5.http.config.ConnectionConfig; import org.apache.hc.client5.http.config.RequestConfig; import org.apache.hc.client5.http.cookie.StandardCookieSpec; import org.apache.hc.client5.http.impl.classic.HttpClientBuilder; @@ -39,7 +40,6 @@ import org.apache.hc.client5.http.impl.io.PoolingHttpClientConnectionManagerBuil import org.apache.hc.client5.http.protocol.HttpClientContext; import org.apache.hc.client5.http.ssl.DefaultClientTlsStrategy; import org.apache.hc.client5.http.ssl.TlsSocketStrategy; -import org.apache.hc.core5.http.io.SocketConfig; import org.apache.hc.core5.http.protocol.HttpContext; import org.apache.hc.core5.http.ssl.TLS; import org.apache.hc.core5.ssl.SSLContextBuilder; @@ -1082,18 +1082,15 @@ public class TestRestTemplate { : StandardCookieSpec.IGNORE); this.enableRedirects = settings.redirects() != Redirects.DONT_FOLLOW; boolean ssl = HttpClientOption.SSL.isPresent(httpClientOptions); - if (settings.readTimeout() != null || ssl) { - setHttpClient(createHttpClient(settings.readTimeout(), ssl)); - } - if (settings.connectTimeout() != null) { - setConnectTimeout((int) settings.connectTimeout().toMillis()); + if (settings.connectTimeout() != null || settings.readTimeout() != null || ssl) { + setHttpClient(createHttpClient(settings.connectTimeout(), settings.readTimeout(), ssl)); } } - private HttpClient createHttpClient(Duration readTimeout, boolean ssl) { + private HttpClient createHttpClient(Duration connectTimeout, Duration readTimeout, boolean ssl) { try { HttpClientBuilder builder = HttpClients.custom(); - builder.setConnectionManager(createConnectionManager(readTimeout, ssl)); + builder.setConnectionManager(createConnectionManager(connectTimeout, readTimeout, ssl)); builder.setDefaultRequestConfig(createRequestConfig()); return builder.build(); } @@ -1102,18 +1099,23 @@ public class TestRestTemplate { } } - private PoolingHttpClientConnectionManager createConnectionManager(Duration readTimeout, boolean ssl) + private PoolingHttpClientConnectionManager createConnectionManager(Duration connectTimeout, + Duration readTimeout, boolean ssl) throws NoSuchAlgorithmException, KeyManagementException, KeyStoreException { PoolingHttpClientConnectionManagerBuilder builder = PoolingHttpClientConnectionManagerBuilder.create(); + if (connectTimeout != null || readTimeout != null) { + ConnectionConfig.Builder connectionConfig = ConnectionConfig.custom(); + if (connectTimeout != null) { + connectionConfig.setConnectTimeout(connectTimeout.toMillis(), TimeUnit.MILLISECONDS); + } + if (readTimeout != null) { + connectionConfig.setSocketTimeout((int) readTimeout.toMillis(), TimeUnit.MILLISECONDS); + } + builder.setDefaultConnectionConfig(connectionConfig.build()); + } if (ssl) { builder.setTlsSocketStrategy(createTlsSocketStrategy()); } - if (readTimeout != null) { - SocketConfig socketConfig = SocketConfig.custom() - .setSoTimeout((int) readTimeout.toMillis(), TimeUnit.MILLISECONDS) - .build(); - builder.setDefaultSocketConfig(socketConfig); - } return builder.build(); } diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/http/client/HttpComponentsClientHttpRequestFactoryBuilder.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/http/client/HttpComponentsClientHttpRequestFactoryBuilder.java index 9626c2b4520..1018d5d1b96 100644 --- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/http/client/HttpComponentsClientHttpRequestFactoryBuilder.java +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/http/client/HttpComponentsClientHttpRequestFactoryBuilder.java @@ -26,6 +26,7 @@ import java.util.function.Consumer; import java.util.function.Function; import org.apache.hc.client5.http.classic.HttpClient; +import org.apache.hc.client5.http.config.ConnectionConfig; import org.apache.hc.client5.http.config.RequestConfig; import org.apache.hc.client5.http.impl.DefaultRedirectStrategy; import org.apache.hc.client5.http.impl.classic.HttpClientBuilder; @@ -65,13 +66,15 @@ public final class HttpComponentsClientHttpRequestFactoryBuilder private final Consumer socketConfigCustomizer; + private final Consumer connectionConfigCustomizer; + private final Consumer defaultRequestConfigCustomizer; private final Function tlsSocketStrategyFactory; HttpComponentsClientHttpRequestFactoryBuilder() { this(Collections.emptyList(), emptyCustomizer(), emptyCustomizer(), emptyCustomizer(), emptyCustomizer(), - HttpComponentsClientHttpRequestFactoryBuilder::createTlsSocketStrategy); + emptyCustomizer(), HttpComponentsClientHttpRequestFactoryBuilder::createTlsSocketStrategy); } private static TlsSocketStrategy createTlsSocketStrategy(SslBundle sslBundle) { @@ -85,12 +88,14 @@ public final class HttpComponentsClientHttpRequestFactoryBuilder Consumer httpClientCustomizer, Consumer connectionManagerCustomizer, Consumer socketConfigCustomizer, + Consumer connectionConfigCustomizer, Consumer defaultRequestConfigCustomizer, Function tlsSocketStrategyFactory) { super(customizers); this.httpClientCustomizer = httpClientCustomizer; this.connectionManagerCustomizer = connectionManagerCustomizer; this.socketConfigCustomizer = socketConfigCustomizer; + this.connectionConfigCustomizer = connectionConfigCustomizer; this.defaultRequestConfigCustomizer = defaultRequestConfigCustomizer; this.tlsSocketStrategyFactory = tlsSocketStrategyFactory; } @@ -100,7 +105,7 @@ public final class HttpComponentsClientHttpRequestFactoryBuilder Consumer customizer) { return new HttpComponentsClientHttpRequestFactoryBuilder(mergedCustomizers(customizer), this.httpClientCustomizer, this.connectionManagerCustomizer, this.socketConfigCustomizer, - this.defaultRequestConfigCustomizer, this.tlsSocketStrategyFactory); + this.connectionConfigCustomizer, this.defaultRequestConfigCustomizer, this.tlsSocketStrategyFactory); } @Override @@ -108,7 +113,7 @@ public final class HttpComponentsClientHttpRequestFactoryBuilder Collection> customizers) { return new HttpComponentsClientHttpRequestFactoryBuilder(mergedCustomizers(customizers), this.httpClientCustomizer, this.connectionManagerCustomizer, this.socketConfigCustomizer, - this.defaultRequestConfigCustomizer, this.tlsSocketStrategyFactory); + this.connectionConfigCustomizer, this.defaultRequestConfigCustomizer, this.tlsSocketStrategyFactory); } /** @@ -122,7 +127,8 @@ public final class HttpComponentsClientHttpRequestFactoryBuilder Assert.notNull(httpClientCustomizer, "'httpClientCustomizer' must not be null"); return new HttpComponentsClientHttpRequestFactoryBuilder(getCustomizers(), this.httpClientCustomizer.andThen(httpClientCustomizer), this.connectionManagerCustomizer, - this.socketConfigCustomizer, this.defaultRequestConfigCustomizer, this.tlsSocketStrategyFactory); + this.socketConfigCustomizer, this.connectionConfigCustomizer, this.defaultRequestConfigCustomizer, + this.tlsSocketStrategyFactory); } /** @@ -137,7 +143,7 @@ public final class HttpComponentsClientHttpRequestFactoryBuilder Assert.notNull(connectionManagerCustomizer, "'connectionManagerCustomizer' must not be null"); return new HttpComponentsClientHttpRequestFactoryBuilder(getCustomizers(), this.httpClientCustomizer, this.connectionManagerCustomizer.andThen(connectionManagerCustomizer), this.socketConfigCustomizer, - this.defaultRequestConfigCustomizer, this.tlsSocketStrategyFactory); + this.connectionConfigCustomizer, this.defaultRequestConfigCustomizer, this.tlsSocketStrategyFactory); } /** @@ -152,6 +158,23 @@ public final class HttpComponentsClientHttpRequestFactoryBuilder Assert.notNull(socketConfigCustomizer, "'socketConfigCustomizer' must not be null"); return new HttpComponentsClientHttpRequestFactoryBuilder(getCustomizers(), this.httpClientCustomizer, this.connectionManagerCustomizer, this.socketConfigCustomizer.andThen(socketConfigCustomizer), + this.connectionConfigCustomizer, this.defaultRequestConfigCustomizer, this.tlsSocketStrategyFactory); + } + + /** + * Return a new {@link HttpComponentsClientHttpRequestFactoryBuilder} that applies + * additional customization to the underlying + * {@link org.apache.hc.client5.http.config.ConnectionConfig.Builder}. + * @param connectionConfigCustomizer the customizer to apply + * @return a new {@link HttpComponentsClientHttpRequestFactoryBuilder} instance + * @since 3.4.12 + */ + public HttpComponentsClientHttpRequestFactoryBuilder withConnectionConfigCustomizer( + Consumer connectionConfigCustomizer) { + Assert.notNull(connectionConfigCustomizer, "'connectionConfigCustomizer' must not be null"); + return new HttpComponentsClientHttpRequestFactoryBuilder(getCustomizers(), this.httpClientCustomizer, + this.connectionManagerCustomizer, this.socketConfigCustomizer, + this.connectionConfigCustomizer.andThen(connectionConfigCustomizer), this.defaultRequestConfigCustomizer, this.tlsSocketStrategyFactory); } @@ -166,8 +189,8 @@ public final class HttpComponentsClientHttpRequestFactoryBuilder Function tlsSocketStrategyFactory) { Assert.notNull(tlsSocketStrategyFactory, "'tlsSocketStrategyFactory' must not be null"); return new HttpComponentsClientHttpRequestFactoryBuilder(getCustomizers(), this.httpClientCustomizer, - this.connectionManagerCustomizer, this.socketConfigCustomizer, this.defaultRequestConfigCustomizer, - tlsSocketStrategyFactory); + this.connectionManagerCustomizer, this.socketConfigCustomizer, this.connectionConfigCustomizer, + this.defaultRequestConfigCustomizer, tlsSocketStrategyFactory); } /** @@ -182,7 +205,7 @@ public final class HttpComponentsClientHttpRequestFactoryBuilder Consumer defaultRequestConfigCustomizer) { Assert.notNull(defaultRequestConfigCustomizer, "'defaultRequestConfigCustomizer' must not be null"); return new HttpComponentsClientHttpRequestFactoryBuilder(getCustomizers(), this.httpClientCustomizer, - this.connectionManagerCustomizer, this.socketConfigCustomizer, + this.connectionManagerCustomizer, this.socketConfigCustomizer, this.connectionConfigCustomizer, this.defaultRequestConfigCustomizer.andThen(defaultRequestConfigCustomizer), this.tlsSocketStrategyFactory); } @@ -191,10 +214,7 @@ public final class HttpComponentsClientHttpRequestFactoryBuilder protected HttpComponentsClientHttpRequestFactory createClientHttpRequestFactory( ClientHttpRequestFactorySettings settings) { HttpClient httpClient = createHttpClient(settings); - HttpComponentsClientHttpRequestFactory factory = new HttpComponentsClientHttpRequestFactory(httpClient); - PropertyMapper map = PropertyMapper.get().alwaysApplyingWhenNonNull(); - map.from(settings::connectTimeout).asInt(Duration::toMillis).to(factory::setConnectTimeout); - return factory; + return new HttpComponentsClientHttpRequestFactory(httpClient); } private HttpClient createHttpClient(ClientHttpRequestFactorySettings settings) { @@ -218,19 +238,29 @@ public final class HttpComponentsClientHttpRequestFactoryBuilder PoolingHttpClientConnectionManagerBuilder builder = PoolingHttpClientConnectionManagerBuilder.create() .useSystemProperties(); PropertyMapper map = PropertyMapper.get().alwaysApplyingWhenNonNull(); - builder.setDefaultSocketConfig(createSocketConfig(settings)); + builder.setDefaultSocketConfig(createSocketConfig()); + builder.setDefaultConnectionConfig(createConnectionConfig(settings)); map.from(settings::sslBundle).as(this.tlsSocketStrategyFactory).to(builder::setTlsSocketStrategy); this.connectionManagerCustomizer.accept(builder); return builder.build(); } - private SocketConfig createSocketConfig(ClientHttpRequestFactorySettings settings) { + private SocketConfig createSocketConfig() { SocketConfig.Builder builder = SocketConfig.custom(); + this.socketConfigCustomizer.accept(builder); + return builder.build(); + } + + private ConnectionConfig createConnectionConfig(ClientHttpRequestFactorySettings settings) { + ConnectionConfig.Builder builder = ConnectionConfig.custom(); PropertyMapper map = PropertyMapper.get().alwaysApplyingWhenNonNull(); + map.from(settings::connectTimeout) + .as(Duration::toMillis) + .to((timeout) -> builder.setConnectTimeout(timeout, TimeUnit.MILLISECONDS)); map.from(settings::readTimeout) .asInt(Duration::toMillis) - .to((timeout) -> builder.setSoTimeout(timeout, TimeUnit.MILLISECONDS)); - this.socketConfigCustomizer.accept(builder); + .to((timeout) -> builder.setSocketTimeout(timeout, TimeUnit.MILLISECONDS)); + this.connectionConfigCustomizer.accept(builder); return builder.build(); } diff --git a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/http/client/HttpComponentsClientHttpRequestFactoryBuilderTests.java b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/http/client/HttpComponentsClientHttpRequestFactoryBuilderTests.java index 7d7001b58f8..58aba1c4403 100644 --- a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/http/client/HttpComponentsClientHttpRequestFactoryBuilderTests.java +++ b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/http/client/HttpComponentsClientHttpRequestFactoryBuilderTests.java @@ -21,8 +21,9 @@ import java.util.List; import java.util.function.Function; import org.apache.hc.client5.http.HttpRoute; -import org.apache.hc.client5.http.classic.HttpClient; +import org.apache.hc.client5.http.config.ConnectionConfig; import org.apache.hc.client5.http.config.RequestConfig; +import org.apache.hc.client5.http.impl.classic.CloseableHttpClient; import org.apache.hc.client5.http.impl.classic.HttpClientBuilder; import org.apache.hc.client5.http.impl.io.PoolingHttpClientConnectionManagerBuilder; import org.apache.hc.client5.http.ssl.TlsSocketStrategy; @@ -94,18 +95,22 @@ class HttpComponentsClientHttpRequestFactoryBuilderTests @Override protected long connectTimeout(HttpComponentsClientHttpRequestFactory requestFactory) { - return (long) ReflectionTestUtils.getField(requestFactory, "connectTimeout"); + return getConnectorConfig(requestFactory).getConnectTimeout().toMilliseconds(); } @Override - @SuppressWarnings("unchecked") protected long readTimeout(HttpComponentsClientHttpRequestFactory requestFactory) { - HttpClient httpClient = requestFactory.getHttpClient(); - Object connectionManager = ReflectionTestUtils.getField(httpClient, "connManager"); - SocketConfig socketConfig = ((Resolver) ReflectionTestUtils.getField(connectionManager, - "socketConfigResolver")) - .resolve(null); - return socketConfig.getSoTimeout().toMilliseconds(); + return getConnectorConfig(requestFactory).getSocketTimeout().toMilliseconds(); + } + + @SuppressWarnings("unchecked") + private ConnectionConfig getConnectorConfig(HttpComponentsClientHttpRequestFactory requestFactory) { + CloseableHttpClient httpClient = (CloseableHttpClient) ReflectionTestUtils.getField(requestFactory, + "httpClient"); + Object manager = ReflectionTestUtils.getField(httpClient, "connManager"); + ConnectionConfig connectorConfig = ((Resolver) ReflectionTestUtils + .getField(manager, "connectionConfigResolver")).resolve(null); + return connectorConfig; } } diff --git a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/client/ClientHttpRequestFactoriesHttpComponentsTests.java b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/client/ClientHttpRequestFactoriesHttpComponentsTests.java index 336e1286b7b..0e682b9073b 100644 --- a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/client/ClientHttpRequestFactoriesHttpComponentsTests.java +++ b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/client/ClientHttpRequestFactoriesHttpComponentsTests.java @@ -17,9 +17,9 @@ package org.springframework.boot.web.client; import org.apache.hc.client5.http.HttpRoute; -import org.apache.hc.client5.http.classic.HttpClient; +import org.apache.hc.client5.http.config.ConnectionConfig; +import org.apache.hc.client5.http.impl.classic.CloseableHttpClient; import org.apache.hc.core5.function.Resolver; -import org.apache.hc.core5.http.io.SocketConfig; import org.springframework.http.client.HttpComponentsClientHttpRequestFactory; import org.springframework.test.util.ReflectionTestUtils; @@ -38,22 +38,6 @@ class ClientHttpRequestFactoriesHttpComponentsTests super(HttpComponentsClientHttpRequestFactory.class); } - @Override - protected long connectTimeout(HttpComponentsClientHttpRequestFactory requestFactory) { - return (long) ReflectionTestUtils.getField(requestFactory, "connectTimeout"); - } - - @Override - @SuppressWarnings("unchecked") - protected long readTimeout(HttpComponentsClientHttpRequestFactory requestFactory) { - HttpClient httpClient = requestFactory.getHttpClient(); - Object connectionManager = ReflectionTestUtils.getField(httpClient, "connManager"); - SocketConfig socketConfig = ((Resolver) ReflectionTestUtils.getField(connectionManager, - "socketConfigResolver")) - .resolve(null); - return socketConfig.getSoTimeout().toMilliseconds(); - } - @Override protected boolean supportsSettingConnectTimeout() { return true; @@ -61,7 +45,27 @@ class ClientHttpRequestFactoriesHttpComponentsTests @Override protected boolean supportsSettingReadTimeout() { - return false; + return true; + } + + @Override + protected long connectTimeout(HttpComponentsClientHttpRequestFactory requestFactory) { + return getConnectorConfig(requestFactory).getConnectTimeout().toMilliseconds(); + } + + @Override + protected long readTimeout(HttpComponentsClientHttpRequestFactory requestFactory) { + return getConnectorConfig(requestFactory).getSocketTimeout().toMilliseconds(); + } + + @SuppressWarnings("unchecked") + private ConnectionConfig getConnectorConfig(HttpComponentsClientHttpRequestFactory requestFactory) { + CloseableHttpClient httpClient = (CloseableHttpClient) ReflectionTestUtils.getField(requestFactory, + "httpClient"); + Object manager = ReflectionTestUtils.getField(httpClient, "connManager"); + ConnectionConfig connectorConfig = ((Resolver) ReflectionTestUtils + .getField(manager, "connectionConfigResolver")).resolve(null); + return connectorConfig; } } diff --git a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/client/RestTemplateBuilderTests.java b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/client/RestTemplateBuilderTests.java index 28a7515136c..0cf53d3a1af 100644 --- a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/client/RestTemplateBuilderTests.java +++ b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/client/RestTemplateBuilderTests.java @@ -25,6 +25,11 @@ import java.util.Set; import java.util.function.Function; import java.util.function.Supplier; +import org.apache.hc.client5.http.HttpRoute; +import org.apache.hc.client5.http.config.ConnectionConfig; +import org.apache.hc.core5.function.Resolver; +import org.apache.hc.core5.util.Timeout; +import org.assertj.core.extractor.Extractors; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.InOrder; @@ -348,11 +353,18 @@ class RestTemplateBuilderTests { } @Test + @SuppressWarnings("unchecked") void requestFactorySettingsAppliesSettings() { ClientHttpRequestFactorySettings settings = ClientHttpRequestFactorySettings.defaults() - .withConnectTimeout(Duration.ofSeconds(1)); + .withConnectTimeout(Duration.ofSeconds(1)) + .withReadTimeout(Duration.ofSeconds(2)); RestTemplate template = this.builder.requestFactorySettings(settings).build(); - assertThat(template.getRequestFactory()).extracting("connectTimeout").isEqualTo(1000L); + Resolver resolver = (Resolver) Extractors + .byName("httpClient.connManager.connectionConfigResolver") + .apply(template.getRequestFactory()); + ConnectionConfig config = resolver.resolve(mock()); + assertThat(config.getConnectTimeout()).isEqualTo(Timeout.of(Duration.ofSeconds(1))); + assertThat(config.getSocketTimeout()).isEqualTo(Timeout.of(Duration.ofSeconds(2))); } @Test