2

In my experience, after calling Spring's RestTemplate#exchange that subsequently receives '404 - Not Found' response, a RestClientException is thrown instead of returning a ResponseEntity that can have its status checked (i.e: with ResponseEntity#getStatusCode#is4xxClientError).

I don't understand why HttpStatus#is4xxClientError even exists if instead an Exception is thrown that prevents returning a ResponseEntity with HttpStatus to call #is4xxClientError on...

I'm reasonably convinced what I just described is the actual situation, because I can find other accounts on the internet that confirm that (i.e: Spring MVC - RestTemplate launch exception when http 404 happens).

How can I get to a state in Java code using RestTemplate where I can indeed check ResponseEntity#getStatusCode#is4xxClientError when RestTemplate#exchange receives 404, rather than being prevented by the RestClientException? Is it something to do with RestTemplate configuration?

Or am I correct that is not actually possible, and maybe the existence of ResponseEntity#getStatusCode#is4xxClientError is actually a 'bug'?

cellepo
  • 4,001
  • 2
  • 38
  • 57
  • 1
    Where is this method defined `ResponseEntity#is4xxClientError`. I didn't find it https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/http/ResponseEntity.html – Hemant Patel May 08 '18 at 17:55
  • Sorry you're right: It's a method on HttpStatus. So you would call like this: responseEntity.getStatusCode().is4xxClientError(); – cellepo May 08 '18 at 19:58
  • Code in question corrected now. – cellepo May 08 '18 at 20:05

1 Answers1

5

RestTemplate has a method

public void setErrorHandler(ResponseErrorHandler errorHandler);

And ResponseErrorHandler interface look like this.

public interface ResponseErrorHandler {

    boolean hasError(ClientHttpResponse response) throws IOException;

    void handleError(ClientHttpResponse response) throws IOException;
}

Whenever RestTemplate processes a response, it first call ResponseErrorHandler#hasError(), if it returns true, ResponseErrorHandler#handleError() is called which may throw exception.

If you don't set ResponseErrorHandler#setErrorHandler(), it defaults to DefaultResponseErrorHandler.java.
Default implementation treats 4xx / 5xx series status code as error and throws RestClientException (not this exception but subclasses of this exception).

You can always write your own ResponseErrorHandler and override the default behavior. So this way you can get a ResponseEntity object even in case of 4xx / 5xx (by writing your own implementation of ResponseErrorHandler and returning always false from the method hasError()).

Once you have ResponseEntity object, you can use ResponseEntity#getStatusCode()#is4xxClientError() method for the same purpose.

Hemant Patel
  • 3,160
  • 1
  • 20
  • 29
  • 1
    I haven't tried this yet, but it sounds like it makes sense - along the lines of RestTemplate configuration that I suspected. So I'm Accepting this Answer, thanks! – cellepo May 08 '18 at 20:08