I'm building an Application using Spring Boot. This application is distributed, which means I have multiple API's that call each others.
One of my underlying services interacts with a database and responds with the requested data. If a request to an unexisting ID is made, I response with a 404 HttpStatus:
return new ResponseEntity<>(HttpStatus.NOT_FOUND);
(Same with 400 error on certain operations, or 204 for deleting an entry etc).
The problem is that I have some other Spring Boot applications that call these API's, throw an org.springframework.web.client.HttpClientErrorException: 404 Not Found
Exception when they request, in this example, an unexisting entry. But the 404 status code is intended and should not return this exception (causing my Hystrix circuit breaker to call its fallback function).
How can I solve this problem?
The call to the service is implemented like this in my code: ResponseEntity<Object> data = restTemplate.getForEntity(url, Object.class);
My RestTemplate is set up like this:
private RestTemplate restTemplate = new RestTemplate();
Spring's RestTemplate
uses a ResponseErrorHandler
to handle errors in responses. This interface provides both a way to determine if the response has an error (ResponseErrorHandler#hasError(ClientHttpResponse)
) and how to handle it (ResponseErrorHandler#handleError(ClientHttpResponse)
).
You can set the RestTemplate
's ResponseErrorHandler
with RestTemplate#setErrorHandler(ResponseErrorHandler)
whose javadoc states
By default,
RestTemplate
uses aDefaultResponseErrorHandler
.
This default implementation
[...] checks for the status code on the
ClientHttpResponse
: any code with seriesHttpStatus.Series.CLIENT_ERROR
orHttpStatus.Series.SERVER_ERROR
is considered to be an error. This behavior can be changed by overriding thehasError(HttpStatus)
method.
In case of an error, it throws the exception you are seeing.
If you want to change this behavior, you can provide your own ResponseErrorHandler
implementation (maybe by overriding DefaultResponseErrorHandler
) which doesn't consider 4xx as an error or that doesn't throw an exception.
For example
restTemplate.setErrorHandler(new ResponseErrorHandler() {
@Override
public boolean hasError(ClientHttpResponse response) throws IOException {
return false; // or whatever you consider an error
}
@Override
public void handleError(ClientHttpResponse response) throws IOException {
// do nothing, or something
}
});
You can then check the status code of the ResponseEntity
returned by getForEntity
and handle it yourself.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With