Search code examples
javaspring-bootspring-rest

Add Custom ClientHttpRequestInterceptor in RestTemplateBuilder with HttpComponentsClientHttpRequestFactory


I need to add a Custom Header in all my RestTemplate Client requests. So I implemented ClientHttpRequestInterceptor. And I add the interceptor in my RestTemplateBuilder config like shown below. The problem is that when the RestTemplate makes the HTTP call it throws following exception:

java.lang.ClassCastException: org.springframework.http.client.InterceptingClientHttpRequestFactory cannot be cast to org.springframework.http.client.HttpComponentsClientHttpRequestFactory

RestTemplate Bean Creation :

@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();
    ClientHttpRequestFactory clientHttpRequestFactory = new HttpComponentsClientHttpRequestFactory(client);
    restTemplateBuilder = restTemplateBuilder.additionalInterceptors(new MyClientHttpRequestInterceptor());
    return restTemplateBuilder.requestFactory(clientHttpRequestFactory).build();
  }

Also, I am updating the timeouts later in below code:

  protected void setRestTemplateTimeouts() {

    HttpComponentsClientHttpRequestFactory rf =
        (HttpComponentsClientHttpRequestFactory) restTemplate.getRequestFactory();
    rf.setConnectTimeout(restTemplateProps.getConnectionTimeout());
    rf.setReadTimeout(restTemplateProps.getSocketTimeout());
  }

Can anyone help me fix this?


Solution

  • The problem was, I was trying to set the connect and read timeouts after setting the ClientHttpRequestInterceptor.

    In my setRestTemplateTimeouts() method when I try to fetch & typecast requestFactory to HttpComponentsClientHttpRequestFactory, I get the ClassCastException exception because restTemplate.getRequestFactory() returns InterceptingClientHttpRequestFactory instead of HttpComponentsClientHttpRequestFactory. This is because I added an interceptor in my restTemplate object.

    Solution is to set the timeouts before setting interceptor because you can't set timeouts after setting an interceptor. Refer the code 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());
        restTemplateBuilder = restTemplateBuilder.additionalInterceptors(new MyClientHttpRequestInterceptor());
        return restTemplateBuilder.requestFactory(clientHttpRequestFactory).build();
      }