Retrieve Original Message From Feign ErrorDecoder – 从伪装的错误解码器中检索原始信息

最后修改: 2022年 3月 9日

1. Overview


A RESTful service can fail for any number of reasons. In this tutorial, we’ll look at how to retrieve the original message from the Feign client if the integrated REST service throws an error.


2. Feign Client


Feign is a pluggable and declarative web service client that makes writing web service clients easier. In addition, to Feign annotations, it also supports JAX-RS, and it supports encoders and decoders to provide more customization.


3. Retrieving Message From ErrorDecoder


When errors occur, the Feign client suppresses the original message, and to retrieve it, we require to write a custom ErrorDecoder. In the absence of such customization, we’ll get the following error:


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( ~[feign-core-11.7.jar:na]
	at feign.FeignException.errorStatus( ~[feign-core-11.7.jar:na]

To handle this error, we’ll create a simple ExceptionMessage Java bean representing the error message:

为了处理这个错误,我们将创建一个简单的ExceptionMessage Java Bean,代表错误信息。

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

Let’s retrieve the original message by extracting it in our customized implementation of ErrorDecoder:


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

    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");
            return errorDecoder.decode(methodKey, response);

In our implementation, we’ve added the logic based on possible errors, and hence we can customize them to meet our requirements. In our switch block’s default case, we’re using Default implementation of ErrorDecoder.


Default implementation decodes the HTTP response when the status is not in the 2xx range. When throwable is retryable, it should be a subtype of RetryableException, and we should raise application-specific exceptions whenever possible.


To configure our customized ErrorDecoder, we’ll add our implementation as a bean in the Feign configuration:

为了配置我们定制的 ErrorDecoder,我们将把我们的实现作为一个bean添加到Feign配置中。

public ErrorDecoder errorDecoder() {
    return new RetreiveMessageErrorDecoder();

Now, let’s see the exception with the original message:

现在,让我们看看原始信息的例外情况。 Page Not found
	at ~[classes/:na]
	at feign.AsyncResponseHandler.handleResponse( ~[feign-core-11.7.jar:na]

4. Conclusion


In this article, we’ve demonstrated how to customize ErrorDecoder so we can catch Feign errors to fetch the original message.


As usual, all code samples used in this tutorial are available over on GitHub.