Как передать ответ об ошибке восходящего потока в нисходящий сервис, используя RestTemplate - PullRequest
0 голосов
/ 18 апреля 2020

Я не могу обработать ответ об ошибке от одного микросервиса к другому. Предположим, что служба A вызывает службу B. B возвращает:

{
  "timestamp": "2020-04-18T13:02:30.543+0000",
  "status": 404,
  "error": "Not Found",
  "message": "Cannot find product with productId = 1",
  "path": "/products/quantity/1"
}

как тело в ResponseEntity. Мне нужно получить то же ответное сообщение, состояние и ошибку в A. Я использую RestTemplate для вызова B из A.

Я пытался

public class RestTemplateResponseErrorHandler implements ResponseErrorHandler {

@Override
public boolean hasError(ClientHttpResponse clientHttpResponse) throws IOException {
    return (clientHttpResponse.getStatusCode().series() == CLIENT_ERROR ||
            clientHttpResponse.getStatusCode().series() == SERVER_ERROR
            );
}

@Override
public void handleError(ClientHttpResponse clientHttpResponse) throws IOException {
    if(clientHttpResponse.getStatusCode().series() == CLIENT_ERROR) {
        HttpStatus httpStatus = clientHttpResponse.getStatusCode();

    }
    else if(clientHttpResponse.getStatusCode().series() == SERVER_ERROR) {
        throw new RecordNotFoundException("Record Not found");
    }
}

Но здесь я могу только чтобы получить ResponseCode, а не весь ResponseBody, содержащий ошибку и сообщение.

1 Ответ

0 голосов
/ 19 апреля 2020

Ваш обработчик ошибок должен выглядеть следующим образом:

public class RestTemplateResponseErrorHandler implements ResponseErrorHandler {

    @Override
    public boolean hasError(ClientHttpResponse clientHttpResponse) throws IOException {
        return (clientHttpResponse.getStatusCode().series() == HttpStatus.Series.CLIENT_ERROR
                || clientHttpResponse.getStatusCode().series() == HttpStatus.Series.SERVER_ERROR);
    }

    @Override
    public void handleError(ClientHttpResponse clientHttpResponse) throws IOException {
        HttpStatus statusCode = clientHttpResponse.getStatusCode();
        switch (statusCode.series()) {
            // handle client errors. Throw HttpClientErrorException
            // ex.getResponseBodyAsString();
            case CLIENT_ERROR:
                HttpClientErrorException ex = new HttpClientErrorException(statusCode,
                        clientHttpResponse.getStatusText(), clientHttpResponse.getHeaders(),
                        this.getResponseBody(clientHttpResponse), this.getCharset(clientHttpResponse));

                throw ex;
            case SERVER_ERROR:
                // handle server errors, may be the same as client errors, by throwing
                // HttpServerErrorException
                break;
            default:
                // default behavior for other errors
                throw new RestClientException("Some Exception message");
        }
    }

    private Charset getCharset(ClientHttpResponse response) {
        HttpHeaders headers = response.getHeaders();
        MediaType contentType = headers.getContentType();
        return contentType != null ? contentType.getCharset() : null;
    }

    private byte[] getResponseBody(ClientHttpResponse response) {
        byte[] result = new byte[0];
        try {
            // this is org.springframework.util.FileCopyUtils class
            result = FileCopyUtils.copyToByteArray(response.getBody());
        } catch (IOException var3) {
            // Handle I/O exception
        }

        return result;
    }
}

Затем перехватить исключение и получить ответ методом getResponseBodyAsString ().

Но если вы не опубликовали c REST Служба, вы можете, я думаю, вернуть логики приложения c ошибки с кодом состояния 200. Создайте базовый класс для всех ответов с полями: errorCode, errorMessage, errorCause (например). Расширяет его вашими ответными классами REST. И если все в порядке - вернуть обычный ответ с errorCode 0. Но если вы получили ошибку при обработке запросов, верните ответ с некоторым errorCode (не 0) и заполните поля errorMessage и errorCause. Это не «Лучшая практика», но иногда может быть всеобъемлющим для вас.

...