Home > Net >  Why handleResponse(URI url, HttpMethod method, ClientHttpResponse response) method of RestTemplate.c
Why handleResponse(URI url, HttpMethod method, ClientHttpResponse response) method of RestTemplate.c

Time:06-22

I am calling an external API from my code using RestTemplate like below:

       try {

            responseEntity = restTemplate.exchange(url, HttpMethod.POST, requestEntity,
                    UploadResonse.class);
        } catch (BusinessException ex) {
            fetchErrorResponseEntity = ex.getResponseEntity();
            if (fetchErrorResponseEntity.getStatusCodeValue() == 404) {
                throw new BusinessException(ex.getMessage(), ErrorResponse.NOT_FOUND);
            } else if (fetchErrorResponseEntity.getStatusCodeValue() == 500) {
                throw new BusinessException(ex.getMessage(),
                                          ErrorResponse.INTERNAL_SERVER_ERROR);
            } else if (fetchErrorResponseEntity.getStatusCodeValue() == 400) {
                throw new BusinessException(ex.getMessage(), ErrorResponse.INVALID_REQUEST);
            }

        }

This API call is returning 200 Success but when I debug it, it still goes to handleResponse(URI url, HttpMethod method, ClientHttpResponse response) method of RestTemplate.class

And then it's coming to my RestTemplateErrorHandler.java file

    @Override
public boolean hasError(ClientHttpResponse clientHttpResponse)
        throws IOException {
    return clientHttpResponse.getStatusCode() != HttpStatus.OK;
}

@Override
public void handleError(ClientHttpResponse clientHttpResponse)
        throws IOException {
    String errMessage = getErrMessage(clientHttpResponse);
    HttpStatus status = clientHttpResponse.getStatusCode();
    switch (status) {
    case BAD_REQUEST: // 400
        throw new BusinessException(errMessage,
                ErrorResponse.INVALID_REQUEST);
    case NOT_FOUND:
      throw new BusinessException(errMessage, ErrorResponse.NOT_FOUND);
    case SERVICE_UNAVAILABLE: // 503
        throw new BusinessException(errMessage, ErrorResponse.TIME_OUT);
    case METHOD_NOT_ALLOWED: // 405
    case INTERNAL_SERVER_ERROR: // 500
    default:
        throw new BusinessException(errMessage,
                ErrorResponse.INTERNAL_SERVER_ERROR);
    }
}

Can someone lease help me to understand if it's the correct behaviour. I suspect that if the response is 200 Success it should not go to the RestTemlate.class and RestTemplateErrorHandler.class This behaviour is creating problem when API return 201 Created status, that time it goes to handleError() method and return the default case INTERNAL_SERVER_ERROR Can someone please help me here

CodePudding user response:

The following code will call the error handler every time the response is not 200 OK, event if it is successful like 201 Created.

@Override
public boolean hasError(ClientHttpResponse clientHttpResponse)
        throws IOException {
    return clientHttpResponse.getStatusCode() != HttpStatus.OK;
}

Try changing the implementation to the following:

@Override
public boolean hasError(ClientHttpResponse clientHttpResponse)
        throws IOException {
    return !clientHttpResponse.getStatusCode().is2xxSuccessful();
}

This is better suited for your needs as it will consider all 2xx status as successful requests instead of only 200 OK.

CodePudding user response:

According to documentation method handleResponse() as it name suggests will handle the given response, perform appropriate logging and invoke the ResponseErrorHandler (if needed) which is interface used by the RestTemplate to determine whether a particular response has an error or not. RestTemplateErrorHandler class implements implements ResponseErrorHandler.

If the hasError() method returns true then Spring will automatically call the handleError() method. This is the flow.

If you check implementation for handleResponse method, given below, you will see that there is a call to hasError method to check if the response has any errors. Default implementation of hasError method will return true is response code is 4XX or 5XX. If there is no errors, method will proceed execution and handleError method won't be invoked, as I explained above.

protected void handleResponse(URI url, HttpMethod method, ClientHttpResponse response) throws IOException {
        ResponseErrorHandler errorHandler = this.getErrorHandler();
        boolean hasError = errorHandler.hasError(response);
        if (this.logger.isDebugEnabled()) {
            try {
                this.logger.debug(method.name()   " request for \""   url   "\" resulted in "   response.getRawStatusCode()   " ("   response.getStatusText()   ")"   (hasError ? "; invoking error handler" : ""));
            } catch (IOException var7) {
                ;
            }
        }
        if (hasError) {
            errorHandler.handleError(url, method, response);
        }

    }

In code you posted hasError will return true for all response codes that are different from 200. That's why handleError is invoked.

  • Related