Перейти к основному содержимому

Получить исходное сообщение от Feign ErrorDecoder

· 3 мин. чтения

1. Обзор

Служба RESTful может выйти из строя по ряду причин. В этом руководстве мы рассмотрим, как получить исходное сообщение от клиента Feign , если интегрированная служба REST выдает ошибку.

2. Притвориться клиентом

Feign — это подключаемый и декларативный клиент веб-службы, упрощающий написание клиентов веб-службы. В дополнение к аннотациям Feign он также поддерживает JAX-RS и поддерживает кодировщики и декодеры для обеспечения большей настройки .

3. Получение сообщения от ErrorDecoder

При возникновении ошибок клиент Feign подавляет исходное сообщение, и для его извлечения нам требуется написать собственный ErrorDecoder . При отсутствии такой настройки мы получим следующую ошибку:

feign.FeignException$NotFound: [404] during [POST] to [http://localhost:8080/upload-error-1] [UploadClient#fileUploadError(MultipartFile)]: [{"timestamp":"2022-02-18T13:25:22.083+00:00","status":404,"error":"Not Found","path":"/upload-error-1"}]
at feign.FeignException.clientErrorStatus(FeignException.java:219) ~[feign-core-11.7.jar:na]
at feign.FeignException.errorStatus(FeignException.java:194) ~[feign-core-11.7.jar:na]

Чтобы обработать эту ошибку, мы создадим простой Java-бин ExceptionMessage , представляющий сообщение об ошибке:

public class ExceptionMessage {
private String timestamp;
private int status;
private String error;
private String message;
private String path;
// standard getters and setters
}

Давайте извлечем исходное сообщение, извлекая его в нашей настраиваемой реализации ErrorDecoder :

public class RetreiveMessageErrorDecoder implements ErrorDecoder {
private ErrorDecoder errorDecoder = new Default();

@Override
public Exception decode(String methodKey, Response response) {
ExceptionMessage message = null;
try (InputStream bodyIs = response.body()
.asInputStream()) {
ObjectMapper mapper = new ObjectMapper();
message = mapper.readValue(bodyIs, ExceptionMessage.class);
} catch (IOException e) {
return new Exception(e.getMessage());
}
switch (response.status()) {
case 400:
return new BadRequestException(message.getMessage() != null ? message.getMessage() : "Bad Request");
case 404:
return new NotFoundException(message.getMessage() != null ? message.getMessage() : "Not found");
default:
return errorDecoder.decode(methodKey, response);
}
}
}

В нашей реализации мы добавили логику, основанную на возможных ошибках, и, следовательно, мы можем настроить их в соответствии с нашими требованиями. В случае нашего блока переключателей по умолчанию мы используем реализацию ErrorDecoder по умолчанию.

Реализация по умолчанию декодирует ответ HTTP, когда статус не находится в диапазоне 2xx. Когда throwable является retryable , он должен быть подтипом RetryableException, и мы должны по возможности вызывать исключения для конкретного приложения.

Чтобы настроить наш настроенный ErrorDecoder , мы добавим нашу реализацию в виде bean-компонента в конфигурацию Feign:

@Bean
public ErrorDecoder errorDecoder() {
return new RetreiveMessageErrorDecoder();
}

Теперь давайте посмотрим на исключение с исходным сообщением:

com.foreach.cloud.openfeign.exception.NotFoundException: Page Not found
at com.foreach.cloud.openfeign.fileupload.config.RetreiveMessageErrorDecoder.decode(RetreiveMessageErrorDecoder.java:30) ~[classes/:na]
at feign.AsyncResponseHandler.handleResponse(AsyncResponseHandler.java:96) ~[feign-core-11.7.jar:na]

4. Вывод

В этой статье мы продемонстрировали, как настроить ErrorDecoder , чтобы мы могли перехватывать ошибки Feign для извлечения исходного сообщения.

Как обычно, все примеры кода, использованные в этом руководстве, доступны на GitHub .