Reputation: 161
I am calling a ReST
service through RestTemplate
and trying to override ResponseErrorHandler
in Spring 3.2
to handle custom error codes.
CustomResponseErrroHandler
public class MyResponseErrorHandler implements ResponseErrorHandler {
@Override
public boolean hasError(ClientHttpResponse response) throws IOException {
boolean hasError = false;
int rawStatusCode = response.getRawStatusCode();
if (rawStatusCode != 200){
hasError = true;
}
return hasError;
}
@Override
public void handleError(ClientHttpResponse response) throws IOException {
//String body = IOUtils.toString(response.getBody());
throw new CustomServiceException(response.getRawStatusCode() , "custom Error");
}
}
Spring
framework invokes hasError
method but not handleError
, so I couldn't throw my custom exception. After delving into Spring
RestTemplate
source code, I realized that the code in handleResponseError
method is causing the issue - It is looking for response.getStatusCode
or response.getStatusText
and throwing exception (as statusCode/statusText is null when Rest
service throws exception) and it never calls either custom implemented or default handleError
method in the next line.
Spring
RestTemplate
source code for handleResponse
method:
private void handleResponseError(HttpMethod method, URI url, ClientHttpResponse response) throws IOException {
if (logger.isWarnEnabled()) {
try {
logger.warn(method.name() + " request for \"" + url + "\" resulted in " +
response.getStatusCode() + " (" + response.getStatusText() + "); invoking error handler");
}
catch (IOException e) {
// ignore
}
}
getErrorHandler().handleError(response);
}
FYI, while service throws exception, I can read rawstatuscode but not statuscode from response
How to bypass this framework code and make call my custom handler? Thanks for your help in advance.
Upvotes: 16
Views: 62898
Reputation: 14307
I don't see your RestTemplate
code, but I assume you to set your ResponseErrorHandler
for RestTemplate
to use like:
RestTemplate restClient = new RestTemplate();
restClient.setErrorHandler(new MyResponseErrorHandler());
The exception is indeed thrown in handleError
method. You can find how to throw CustomException
using CustomResponseHandler
from one of my previous answers.
Upvotes: 4
Reputation: 8771
Following link has useful information about Exception Flow for Spring ResponseErrorHandler .
Adding code here, just in-case the blog is down:
Code for ErrorHandler:
public class MyResponseErrorHandler implements ResponseErrorHandler {
private static final Log logger = LogFactory.getLog(MyResponseErrorHandler.class);
@Override
public void handleError(ClientHttpResponse clienthttpresponse) throws IOException {
if (clienthttpresponse.getStatusCode() == HttpStatus.FORBIDDEN) {
logger.debug(HttpStatus.FORBIDDEN + " response. Throwing authentication exception");
throw new AuthenticationException();
}
}
@Override
public boolean hasError(ClientHttpResponse clienthttpresponse) throws IOException {
if (clienthttpresponse.getStatusCode() != HttpStatus.OK) {
logger.debug("Status code: " + clienthttpresponse.getStatusCode());
logger.debug("Response" + clienthttpresponse.getStatusText());
logger.debug(clienthttpresponse.getBody());
if (clienthttpresponse.getStatusCode() == HttpStatus.FORBIDDEN) {
logger.debug("Call returned a error 403 forbidden resposne ");
return true;
}
}
return false;
}
}
Code for using it in RestTemplate:
RestTemplate restclient = new RestTemplate();
restclient.setErrorHandler(new MyResponseErrorHandler());
ResponseEntity<String> responseEntity = clientRestTemplate.exchange(
URI,
HttpMethod.GET,
requestEntity,
String.class);
response = responseEntity.getBody();
Upvotes: 17