Search code examples
error-handlingresttemplate

How to use custom ResponseErrorHandler and ClientHttpRequestFactory at the same RestTemplate?


I'm using RestTemplate and I added a handler to process some errors:

@Configuration
public class IntegrationConfiguration {

@Bean
public RestTemplate restTemplate() {

    return new RestTemplateBuilder()
            .errorHandler(new CustomErrorHandler())
            .setConnectTimeout(4000)
            .setReadTimeout(4000)
            .build();
}

Here is CustomErrorHandler implementation:

public class CustomErrorHandler implements ResponseErrorHandler {

@Override
public boolean hasError(ClientHttpResponse response) throws IOException {
    return response.getStatusCode().is4xxClientError() || 
           response.getStatusCode().is5xxServerError();
}

@Override
public void handleError(ClientHttpResponse response) throws IOException {

    final String body = new BufferedReader(new InputStreamReader(response.getBody()))
              .lines().collect(Collectors.joining("\n"));
    // more non important code...
} 

But I get

java.net.HttpRetryException: cannot retry due to server authentication, in streaming mode
at sun.net.www.protocol.http.HttpURLConnection.getInputStream0(HttpURLConnection.java:1692)
at sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1492)

When I try to response.getBody(). I found this answer, but to implement it, how can I set a ClientHttpRequestFactory implementation (as shown above) if this answer just accept classes who extends ClientHttpRequestFactory?

ClientHttpRequestFactory is an functional interface.


Solution

  • I managed to accomplish this using a constructor with HttpRequestFactory as an argument and ErrorHandler inserted with a setter:

    @Bean
    public RestTemplate restTemplate() {
        final SimpleClientHttpRequestFactory httpRequestFactory = new SimpleClientHttpRequestFactory();
        httpRequestFactory.setOutputStreaming(false);
        httpRequestFactory.setConnectTimeout(config.getTimeOut()*1000);
        httpRequestFactory.setReadTimeout(config.getTimeOut()*1000);
    
        final RestTemplate restTemplate = new RestTemplate(httpRequestFactory);
        restTemplate.setErrorHandler(new CustomErrorHandler());
        return restTemplate;
    }