Search code examples
javaspring-bootresttemplatespring-resttemplateapache-httpclient-5.x

Pooling RestTemplante setReadTimeout


I need to create a pool of connectors using apache.httpcomponents.client5:httpclient5:5.2.1* and SpringBoot(ver 3.1.5) RestTemplate.

This code works correctly:

private static RestTemplate pooledRestTemplate() {
        PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager();
        connectionManager.setMaxTotal(2000);
        connectionManager.setDefaultMaxPerRoute(2000);
    
        HttpClient httpClient =
            HttpClientBuilder.create().setConnectionManager(connectionManager).build();
    
        return new RestTemplateBuilder()
            .requestFactory(() -> new HttpComponentsClientHttpRequestFactory(httpClient))
            .setConnectTimeout(Duration.ofMinutes(5))
            .build();
      }

But if I add .setReadTimeout() to the builder:

 return new RestTemplateBuilder()
            .requestFactory(() -> new HttpComponentsClientHttpRequestFactory(httpClient))
            .setConnectTimeout(Duration.ofMinutes(5))
            .setReadTimeout(Duration.ofMinutes(5))
            .build();

When the application starts, an error message appears:

java.lang.IllegalStateException: Request factory org.springframework.http.client.HttpComponentsClientHttpRequestFactory has the setReadTimeout method marked as deprecated

I read about this moment when updating the version https://github.com/spring-projects/spring-boot/issues/35658. But I didn't understand how to combine the pool of connectors and RestTemplateBuilder.


Solution

  • A solution came up in https://github.com/spring-projects/spring-framework/issues/32121 HttpComponentsClientHttpRequestFactory no longer supports the setReadTimeout method.

    You must configure the HttpClient completely and pass it to the build of RestTemplat. And use setConnectionRequestTimeout along with setReadTimeout:

    PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager();
        connectionManager.setMaxTotal(2000);
        connectionManager.setDefaultMaxPerRoute(2000);
        
        RequestConfig config =
            RequestConfig.custom()
                .setResponseTimeout(Timeout.ofMinutes(1))
                .setConnectionRequestTimeout(Timeout.ofMinutes(1))
                .build();
        
        HttpClient httpClient =
            HttpClientBuilder.create()
                .setConnectionManager(connectionManager)
                .setDefaultRequestConfig(config)
                .build();
        
        return new RestTemplateBuilder()
            .requestFactory(() -> new HttpComponentsClientHttpRequestFactory(httpClient))
            .basicAuthentication(
                SecurityUtils.getUsername(credential), SecurityUtils.getPassword(credential))
            .build();