Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Custom RestTemplate using requestFactory of RestTemplateBuilder in SpringBoot 2.1.x is not backward compatible with version 1.5.x

In Spring Boot 1.5.x, I was creating a custom RestTemplate like below:

@Bean
  public RestTemplate restTemplate(RestTemplateBuilder restTemplateBuilder) {
    PoolingHttpClientConnectionManager poolingConnectionManager = new PoolingHttpClientConnectionManager();
    poolingConnectionManager.setMaxTotal(restTemplateProps.getMaxConnectionsPerPool());
    poolingConnectionManager.setDefaultMaxPerRoute(restTemplateProps.getMaxDefaultConnectionPerRoute());
    CloseableHttpClient client = HttpClientBuilder.create().setConnectionManager(poolingConnectionManager).build();
    HttpComponentsClientHttpRequestFactory clientHttpRequestFactory =
        new HttpComponentsClientHttpRequestFactory(client);
    clientHttpRequestFactory.setConnectTimeout(restTemplateProps.getConnectionTimeout());
    clientHttpRequestFactory.setReadTimeout(restTemplateProps.getSocketTimeout());
    return restTemplateBuilder.requestFactory(clientHttpRequestFactory).build();
  }

But, after migrating to Spring Boot 2.1.x, the above code doesn't compile. Looks like requestFactory doesn't take HttpComponentsClientHttpRequestFactory as an input parameter.

Can anyone suggest how can I make the above code work in Spring Boot 2.1.x?

like image 302
Sahil Chhabra Avatar asked Nov 28 '18 03:11

Sahil Chhabra


People also ask

What is spring boot RestTemplateBuilder?

public class RestTemplateBuilder extends Object. Builder that can be used to configure and create a RestTemplate . Provides convenience methods to register converters , error handlers and UriTemplateHandlers .

How do you bypass RestTemplate in spring boot?

Set a @Qualifier on restTemplate in my @Configuration class. Remove the bean restTemplate in my @Configuration class.

How do you instantiate RestTemplate in spring boot?

Creating a RestTemplate Bean In any Controller, we can directly instantiate a local instance of a RestTemplate by simply instantiating the class into an object: private RestTemplate restTemplate = new RestTemplate();

What is the difference between RestTemplate and WebClient?

RestTemplate uses Java Servlet API and is therefore synchronous and blocking. Conversely, WebClient is asynchronous and will not block the executing thread while waiting for the response to come back. The notification will be produced only when the response is ready. RestTemplate will still be used.


2 Answers

After digging deeper into the source code of RestTemplateBuilder of Spring Boot 2.1.x, I found that they have removed the method requestFactory(ClientHttpRequestFactory requestFactory). That means you can no longer inject the ClientHttpRequestFactory object into requestFactory method.

But, it accept a Supplier<ClientHttpRequestFactory> as the input now. So if you have only one restTemplate and one requestFactory, all you need to do is register a HttpComponentsClientHttpRequestFactory bean in Spring context and pass a ClientHttpRequestFactorySupplier to requestFactory method. The supplier will automatically detect your HttpComponentsClientHttpRequestFactory and return you the required RestTemplate.

Refer the below code for that:

@Bean
  public HttpComponentsClientHttpRequestFactory httpComponentsClientHttpRequestFactory() {
    PoolingHttpClientConnectionManager poolingConnectionManager = new PoolingHttpClientConnectionManager();
    poolingConnectionManager.setMaxTotal(restTemplateProps.getMaxConnectionsPerPool());
    poolingConnectionManager.setDefaultMaxPerRoute(restTemplateProps.getMaxDefaultConnectionPerRoute());
    CloseableHttpClient client = HttpClientBuilder.create().setConnectionManager(poolingConnectionManager).build();
    HttpComponentsClientHttpRequestFactory clientHttpRequestFactory =
        new HttpComponentsClientHttpRequestFactory(client);
    clientHttpRequestFactory.setConnectTimeout(restTemplateProps.getConnectionTimeout());
    clientHttpRequestFactory.setReadTimeout(restTemplateProps.getSocketTimeout());
    return clientHttpRequestFactory;
  }

  @Bean
  public RestTemplate authRestTemplate(RestTemplateBuilder restTemplateBuilder) {
    return restTemplateBuilder.requestFactory(new ClientHttpRequestFactorySupplier()).build();
  }

For those who are interested in all the changes made to RestTemplateBuilder in SpringBoot 2.1.x, please refer this.

like image 115
Sahil Chhabra Avatar answered Sep 19 '22 14:09

Sahil Chhabra


Or even easier, just:

 restTemplatebuilder.requestFactory(() -> new 
    HttpComponentsClientHttpRequestFactory(httpClient)).build();
like image 40
Dariusz Urbanek Avatar answered Sep 22 '22 14:09

Dariusz Urbanek