Spring Resttemplate exception handling
Solution 1
You want to create a class that implements ResponseErrorHandler
and then use an instance of it to set the error handling of your rest template:
public class MyErrorHandler implements ResponseErrorHandler {
@Override
public void handleError(ClientHttpResponse response) throws IOException {
// your error handling here
}
@Override
public boolean hasError(ClientHttpResponse response) throws IOException {
...
}
}
[...]
public static void main(String args[]) {
RestTemplate restTemplate = new RestTemplate();
restTemplate.setErrorHandler(new MyErrorHandler());
}
Also, Spring has the class DefaultResponseErrorHandler
, which you can extend instead of implementing the interface, in case you only want to override the handleError
method.
public class MyErrorHandler extends DefaultResponseErrorHandler {
@Override
public void handleError(ClientHttpResponse response) throws IOException {
// your error handling here
}
}
Take a look at its source code to have an idea of how Spring handles HTTP errors.
Solution 2
Spring cleverly treats http error codes as exceptions, and assumes that your exception handling code has the context to handle the error. To get exchange to function as you would expect it, do this:
try {
return restTemplate.exchange(url, httpMethod, httpEntity, String.class);
} catch(HttpStatusCodeException e) {
return ResponseEntity.status(e.getRawStatusCode()).headers(e.getResponseHeaders())
.body(e.getResponseBodyAsString());
}
This will return all the expected results from the response.
Solution 3
You should catch a HttpStatusCodeException
exception:
try {
restTemplate.exchange(...);
} catch (HttpStatusCodeException exception) {
int statusCode = exception.getStatusCode().value();
...
}
Solution 4
Another solution is the one described here at the end of this post by "enlian": http://springinpractice.com/2013/10/07/handling-json-error-object-responses-with-springs-resttemplate
try{
restTemplate.exchange(...)
} catch(HttpStatusCodeException e){
String errorpayload = e.getResponseBodyAsString();
//do whatever you want
} catch(RestClientException e){
//no response payload, tell the user sth else
}
Solution 5
Spring abstracts you from the very very very large list of http status code. That is the idea of the exceptions. Take a look into org.springframework.web.client.RestClientException hierarchy:
You have a bunch of classes to map the most common situations when dealing with http responses. The http codes list is really large, you won't want write code to handle each situation. But for example, take a look into the HttpClientErrorException sub-hierarchy. You have a single exception to map any 4xx kind of error. If you need to go deep, then you can. But with just catching HttpClientErrorException, you can handle any situation where bad data was provided to the service.
The DefaultResponseErrorHandler is really simple and solid. If the response status code is not from the family of 2xx, it just returns true for the hasError method.
Related videos on Youtube
vaibhav
Updated on April 12, 2022Comments
-
vaibhav about 2 years
Below is the code snippet; basically, I am trying to propagate the exception when the error code is anything other than 200.
ResponseEntity<Object> response = restTemplate.exchange(url.toString().replace("{version}", version), HttpMethod.POST, entity, Object.class); if(response.getStatusCode().value()!= 200){ logger.debug("Encountered Error while Calling API"); throw new ApplicationException(); }
However in the case of a 500 response from the server I am getting the exception
org.springframework.web.client.HttpServerErrorException: 500 Internal Server Error at org.springframework.web.client.DefaultResponseErrorHandler.handleError(DefaultResponseErrorHandler.java:94) ~[spring-web-4.2.3.RELEASE.jar:4.2.3.RELEASE]
Do I really need to wrap the rest template exchange method in try? What would then be the purpose of codes?
-
Mudassar almost 8 yearsKindly share the code of ApplicationException()
-
-
vaibhav almost 8 yearsIMO the response should always come with an appropriate status code, otherwise whats the purpose of codes.
-
Stefano Scarpanti over 6 yearsI am not sure to understand @vaibhav objection: catching HttpStatusCodeException is not for a wrong code, but because in many cases an exception is always thrown and so your if(code==value) can never be executed.
-
Agoston Horvath over 6 yearsExceptions are very costly in Java. It's OK for the occasional, unexpected causes (hence the name), but over that, you should look for other solutions instead.
-
IcedDante about 6 years"Very costly"? More costly than, say, making an HTTP call?
-
Raffael Bechara Rameh about 6 yearsHow can we get response body from the exception? Is it possible?
-
Dave about 6 years@AgostonHorvath - rubbish. In this case you've paid the price of the exception already anyway. The point here is to transform it from an otherwise useless HttpClientException into a more meaningful application specific exception using the returned JSON error object.
-
Dave about 6 years@RaffaelBecharaRameh - HttpStatusCodeException .getResponseBodyAsString() or HttpStatusCodeException.getResponseBodyAsByteArray().
-
Agoston Horvath about 6 years@Dave there is no exception created if you process the error via a handler, like the answer above.
-
Dave almost 6 years@AgostonHorvath - the cost of the exception includes the context setup for exception handling that the JVM does whenever it encounters a try block - this is the cost already paid to which I referred. The cost of generating the stack trace is relatively minor although not completely insignificant. Your assertion that "Exceptions are very costly in Java" within a context where some form of error handling must happen, is false.
-
Dave almost 6 yearsFWIW I personally use the custom ResponseErrorHandler approach, but not because I am trying to avoid using Java exception handling. My reason is because the response body in such cases is the serialized exception.
-
Agoston Horvath almost 6 years@Dave The try-catch block is practically free. It's new()'ing and throw'ing the exception that is expensive. See stackoverflow.com/questions/17966265/…
-
mvmn almost 6 yearsI have 1 instance of RestTemplate that I reuse for different calls. I need to handle errors from different calls differently - apparently there is no way to do that with global handler - I need to provide a handler per request.
-
Federico Bellucci almost 6 yearsWith this error handler I always get a
ResourceAccessException
becauseRestTemplate.doExecute
catchesIOException
s and throws aResourceAccessException
. What am I doing wrong? -
Agoston Horvath over 5 yearsLike I said like 6 comments earlier, "@Dave there is no exception created if you process the error via a handler, like the answer above. "
-
Crenguta S over 5 yearsI was able to solve this by extending DefaultResponseErrorHandler.
-
razor over 5 yearsyou need to use different HttpClient than default SDK, to get response body for errors
-
razor over 5 yearsyou need to use different HttpClient than default SDK, to get response body for errors (for example apache commons HttpClient)
-
razor over 5 yearsyou need to use different HttpClient than default SDK, to get response body for errors (for example apache commons HttpClient)
-
razor over 5 yearsyou need to use different HttpClient than default SDK, to get response body for errors (for example apache commons HttpClient)
-
The-Proton-Resurgence about 5 years'org.springframework.web.client.HttpClientErrorException' is a subclass of 'org.springframework.web.client.HttpStatusCodeException'. You don't need to catch HttpClientErrorException if you are already catching HttpStatusCodeException and doing nothing different in handling the above two exceptions.
-
chill appreciator about 4 yearsDude, thanks for the explanation. How did you build this tree with exception hierarchy?
-
Perimosh about 4 yearsHey man, I used Eclipse. Just press control+shift+T to open the type searcher, and type RestClientException. Double click on RestClientException from the results, Eclipse will open that class for you. Then, put the mouse cursor over the class name (where it says "public class RestClientException...", and press control+T. You will see that hierarchy.
-
Perimosh almost 4 yearsdid you try it?
-
chill appreciator almost 4 yearsBtw in Intellij it is: click on the class in project tree and Ctrl + Alt + U, or right mouse click -> Build diagram
-
lorrainebatol over 3 yearsthis is helpful, thanks, though I would disagree that assuming things is a clever thing to do
-
Raphael over 3 years"cleverly" -- citation needed
-
austin cherlo over 3 yearsClever aka en.wikipedia.org/wiki/Kludge as opposed to KISS principles-wiki.net/principles:keep_it_simple_stupid. Some developers do not like to use exception handling as a method of process control.
-
Manoj Majumdar almost 3 years@CrengutaS the DefaultResponseErrorHandler's handleError method is called, but ultimately the HttpClientErrorException gets propagated to the client. How have you handled that in your handler?