Collectives™ on Stack Overflow

Find centralized, trusted content and collaborate around the technologies you use most.

Learn more about Collectives

Teams

Q&A for work

Connect and share knowledge within a single location that is structured and easy to search.

Learn more about Teams

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

Ask Question

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?

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.

Additional (and important) info: the ClientHttpRequestFactorySupplier() class exists only in Spring Boot 2.1.0 and above; thus, the solution applies to SpringBoot2.1.x+, and not to 2.x.x as stated. – gcpdev Jan 7, 2019 at 11:03 ok but what if you have 2 restTemplate which need 2 distinct "requestFactory" ? How do you chose which requestFactory get injected into which restTemplate since it's auto detected by "ClientHttpRequestFactorySupplier()" ? – Tristan May 17, 2019 at 14:13 Or even easier with Kotlin, just: `restTemplateBuilder .requestFactory { HttpComponentsClientHttpRequestFactory(httpClient)).build() } – slorinc Feb 28, 2022 at 22:01

Here is a more general solution if you have multiple restTemplates which need different requestFactories (and not an auto-injection of the first one found) :

@Configuration
public class Config {
  @Bean
  public RestTemplate restTemplate(RestTemplateBuilder builder, ApplicationContext ctx) {
    return builder.requestFactory(new MyRequestFactorySupplier()).build();
  class MyRequestFactorySupplier implements Supplier<ClientHttpRequestFactory> {
    @Override
    public ClientHttpRequestFactory get() {
      // Using Apache HTTP client.
      HttpClientBuilder clientBuilder = HttpClientBuilder.create();
      HttpClient httpClient = clientBuilder.build();
      HttpComponentsClientHttpRequestFactory requestFactory = new HttpComponentsClientHttpRequestFactory(httpClient);
      requestFactory.setBufferRequestBody(false); // When sending large amounts of data via POST or PUT, it is recommended to change this property to false, so as not to run out of memory.
      return requestFactory;
        

Thanks for contributing an answer to Stack Overflow!

  • Please be sure to answer the question. Provide details and share your research!

But avoid

  • Asking for help, clarification, or responding to other answers.
  • Making statements based on opinion; back them up with references or personal experience.

To learn more, see our tips on writing great answers.