Describe the bug When returning an empty org.springframework.core.io.Resource response (e.g. FileSystemResource pointing to an empty file) SpringDecoder converts it to a null instead of an empty Resource.

Version: org.springframework.cloud:spring-cloud-openfeign-core:2.1.3.RELEASE

Source of the problem Line 59 in SpringDecoder uses HttpMessageConverterExtractor to extract the data from the HTTP response using the assigned MessageConverter. Unfortunately Line 89 in the HttpMessageConverterExtractor class has an early return when the body is empty. This is the case when returning an empty Resource.

Comment From: spencergibb

Why are you returning a Resource from feign?

Comment From: czocher

I'm returning a FileSystemResource from a controller because I need file-download functionality. I am aware Feign is not the best fit for this kind of functionality, but I'm constrained by the environment.

Comment From: czocher

For the people searching for a quick-fix: this issue can be bypassed by creating a new delegating Decoder implementation and decorating the SpringDecoder as follows:

public class EmptyResourceDecoder implements Decoder {

    public static final ByteArrayResource EMPTY_RESPONSE = new ByteArrayResource("".getBytes(StandardCharsets.UTF_8));
    private final Decoder delegate;

    public EmptyResourceDecoder(final Decoder delegate) {
        Objects.requireNonNull(delegate, "Decoder must not be null. ");
        this.delegate = delegate;
    }

    @Override
    public Object decode(final Response response, final Type type) throws IOException, FeignException {
        final Object result = delegate.decode(response, type);

        if (type instanceof Class && ((Class<?>) type).isAssignableFrom(Resource.class) && result == null) {
            return EMPTY_RESPONSE;
        }

        return result;
    }
}
       @Bean
    public Decoder feignDecoder(final ObjectFactory<HttpMessageConverters> messageConverters) {
        return new OptionalDecoder(
            new ResponseEntityDecoder(new EmptyResourceDecoder(new SpringDecoder(messageConverters))));
    }

Comment From: spencergibb

Why can't the feign client just return a byte array?

Comment From: czocher

The return type must be the same as the one in the Type argument otherwise a ClassCastException occurs due to the fact the return of this method is later casted to the Resource type expected by the Feign client interface (java.lang.ClassCastException: [B cannot be cast to org.springframework.core.io.Resource to be exact).

EDIT: Ah you mean the Feign client interface? It is taken from the Controller interface which should support streaming responses. I believe Resource actually provides that, although not in the Feign Client case. Also it simplifies the implementation on the backend side.

Comment From: spencergibb

Yes, this is a problem when you share an interface between a client and server. I'm going decline this as we don't want to support everything you can do on a server on a client.