Search code examples
javaspringrestspring-bootresttemplate

Spring RestTemplate configuration strategies to call multiple rest services from a single API


I have a scenario where there is an aggregate endpoint to call multiple downstream systems which are RESTful and gives back the consolidated response from all these systems.

I am currently using a rest template that is configured as a singleton bean and injects it to the corresponding services to make the rest call. The RestTemplate is using the default CloseableHttpClient as the HttpClient, which will close the connections once the request is successful.

Would this be a good approach or would it be better if the rest template is configured per service that is calling its RESTful service?


Solution

  • RestTemplate is thread safe. You could use a pooling connection manager:

      @Bean
      public PoolingHttpClientConnectionManager poolingHttpClientConnectionManager() {
        PoolingHttpClientConnectionManager result = new PoolingHttpClientConnectionManager();
        result.setMaxTotal(20);  // FIXME Consider making this value configurable
        return result;
      }
    
      @Bean
      public RequestConfig requestConfig() {
        RequestConfig result = RequestConfig.custom()
          // FIXME Consider making these values configurable
          .setConnectionRequestTimeout(2000)
          .setConnectTimeout(2000)
          .setSocketTimeout(2000)
          .build();
        return result;
      }
    
      @Bean
      public CloseableHttpClient httpClient(PoolingHttpClientConnectionManager poolingHttpClientConnectionManager, RequestConfig requestConfig) {
        CloseableHttpClient result = HttpClientBuilder
          .create()
          .setConnectionManager(poolingHttpClientConnectionManager)
          .setDefaultRequestConfig(requestConfig)
          .build();
        return result;
      }
    
      @Bean
      public RestTemplate restTemplate(HttpClient httpClient) {
        HttpComponentsClientHttpRequestFactory requestFactory = new HttpComponentsClientHttpRequestFactory();
        requestFactory.setHttpClient(httpClient);
        return new RestTemplate(requestFactory);
      }
    

    And also important, you might need to change RestTemplate's default settings based on observation / load tests, RestTemplate doesn't necessary use the whole pool to prevent a host from hijacking it.

    You can read more at my blog Troubleshooting Spring's RestTemplate Requests Timeout