Search code examples
springerror-handlingspring-cloud-feignfeignopenfeign

Feign ErrorDecoder is not invoked - how to configure feign to use it?


As i understand the decode() method of the feign ErrorDecoder will be called when a request responds with a status code != 2xx. Through debugging my tests i found out that the decode() method of my CustomErrorDecoder is not invoked on e.g. 504 or 404. I tried two ways to configure it:

Either include it as a Bean in the client configuration:

    @Bean
    public CustomErrorDecoder customErrorDecoder() {
        return new CustomErrorDecoder();
    }

or write it into the application configuration :

feign:
  client:
    config:
      myCustomRestClientName:
        retryer: com.a.b.some.package.CustomRetryer
        errorDecoder: com.a.b.some.package.CustomErrorDecoder

Both ways don't invoke the ErrorDecoder. What am I doing wrong? The Bean is beeing instantiated and my CustomErrorDecoder looks like this:

@Component
public class CustomErrorDecoder implements ErrorDecoder {

    private final ErrorDecoder defaultErrorDecoder = new Default();

    @Override
    public Exception decode(String s, Response response) {
        Exception exception = defaultErrorDecoder.decode(s, response);

        if (exception instanceof RetryableException) {
            return exception;
        }

        if (response.status() == 504) {
            // throwing new RetryableException to retry 504s
        }
        return exception;
    }
}

Update:

I have created a minimal reproducible example in this git repo. Please look at the commit history to find 3 ways that I tried.


Solution

  • The problem is that your feign client uses feign.Response as the return type:

    import feign.Param;
    import feign.RequestLine;
    import feign.Response;
    
    public interface TestEngineRestClient {
    
        @RequestLine(value = "GET /{uuid}")
        Response getReport(@Param("uuid") String uuid);
    }
    

    In this case, Feign delegates its handling to the developer - e.g., you can retrieve HTTP status and a response body and do some stuff with it.

    If interested, you can look at the source code of feign.SynchronousMethodHandler, executeAndDecode section.

    To fix this, replace Response.class with the desired type in case of the correct response with status code = 2xx (probably some DTO class). I made a PR where I've changed it to String for simplicity.