javaspringspring-boothttpapache-httpclient-5.x

Spring Boot 2.7 to SprintBoot3 Migration Issue with HttpClient


I am facing issue when I try to migrate to SpringBoot 3 from Spring Boot 2.

import java.net.InetSocketAddress;
import java.net.Proxy;
import java.net.Proxy.Type;
import java.util.concurrent.TimeUnit;
import org.apache.http.HttpHost;
import org.apache.http.client.HttpClient;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.config.SocketConfig;
import org.apache.http.impl.client.DefaultHttpRequestRetryHandler;
import org.apache.http.impl.client.HttpClients; 
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.client.ClientHttpRequestFactory;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.web.client.RestTemplate; 

@Configuration
@RefreshScope
public class RestTemplateConfig{

int timeout=10000;
int readTimeout=10000;
int retryCount=3;
int timeToLive=5000;
String rProxy=proxy.test.com;
String rPort=80;

public RestTemplate restTemplate() {
return new RestTemplate(getClientHttpRequestFactory());
}

private ClientHttpRequestFactory getClientHttpRequestFactory() {

Httphost proxy new HttpHost(rProxy, Integer.parseInt(rPort));

SocketConfig socketConfig=SocketConfig.custom()
                          .setSoTimeout(timeout)
                          .build();

RequestConfig requestConfig=RequestConfig.custom()
                            .setConnectionRequestTimeout(timeout)
                            .setConnectTimeout(timeout)
                            .setSocketTimeout(timeout)
                            .build(); 

HttpClient httpClient=HttpClients.custom().setProxy(proxy)
                                          .setDefaultSocketConfig(socketConfig)
                                          .setDefaultRequestConfig(requestConfig)
                                          .setRetryHandler(new DefaultHttpRequestRetryHandler(retryCount, true))
                                          .setConnectionTimeToLive(timeToLive, TimeUnit.MILLISECONDS)
                                          .build(); 

HttpComponentsClientHttpRequestFactory rf=new HttpComponentsClientHttpRequestFactory(httpClient):
rf.setConnectTimeout(timeout); rf.setReadTimeout(readTimeout);
rf.setConnectionRequestTimeout(timeout);

return rf;
}

I am getting error:

The constructor HttpComponsentsClientHttpRequestFactory(HttpClient) is undefined.

It seems in SpringBoot3 HttpComponsentsClientHttpRequestFactory constructor only takes org.apache.hc.client5.http.classic.HttpClient

I made the following changes [Changed the classes to httpClient5]:

import org.apache.hc.client5.http.classic.HttpClient;
import org.apache.hc.client5.http.HttpHost;
import org.apache.hc.client5.http.impl.classic.HttpClients;

But getting error:

The method setDefaultSocketConfig(SocketConfig) is undefined for the type HttpClientBuilder

HttpClient httpClient=HttpClients.custom().setProxy(proxy)
              .setDefaultSocketConfig(socketConfig)
              .setDefaultRequestConfig(requestConfig)
              .setRetryHandler(new DefaultHttpRequestRetryHandler(retryCount, true))
              .setConnectionTimeToLive(timeToLive, TimeUnit.MILLISECONDS)
              .build(); 

Is there any equivalent method to setDefaultSocketConfig or any other way I can attain same functionality?


Solution

  • You can create a ConnectionManager with the SocketConfig and pass that ConnectionManager to the HttpClientBuilder you are using. For example,

    PoolingHttpClientConnectionManager connectionManager = PoolingHttpClientConnectionManagerBuilder.create()
                  .setDefaultSocketConfig(socketConfig)
                  .build();
    

    and then,

    HttpClient httpClient=HttpClients.custom().setProxy(proxy)
              .setConnectionManager(connectionManager)
              .build()
    

    You can also set the timeToLive in a ConnectionConfig and pass that to ConnectionManager as well, like

    final ConnectionConfig connectionConfig = ConnectionConfig
              .custom()
              .setTimeToLive(TimeValue.ofMilliseconds(...))
              .build();
    

    Then,

      PoolingHttpClientConnectionManager connectionManager = PoolingHttpClientConnectionManagerBuilder.create()
                  .setDefaultSocketConfig(socketConfig)
                  .setDefaultConnectionConfig(connectionConfig)
                  .build();
    

    You can pass this ConnectionManager to the HttpClientBuilder, the same way as we did before.