diff --git a/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/feign/support/SpringDecoder.java b/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/feign/support/SpringDecoder.java index 6651283c..a82a17ad 100644 --- a/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/feign/support/SpringDecoder.java +++ b/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/feign/support/SpringDecoder.java @@ -16,13 +16,10 @@ package org.springframework.cloud.netflix.feign.support; -import static org.springframework.cloud.netflix.feign.support.FeignUtils.getHttpHeaders; - -import java.io.IOException; -import java.io.InputStream; -import java.lang.reflect.ParameterizedType; -import java.lang.reflect.Type; - +import feign.FeignException; +import feign.Response; +import feign.codec.DecodeException; +import feign.codec.Decoder; import org.springframework.beans.factory.ObjectFactory; import org.springframework.boot.autoconfigure.web.HttpMessageConverters; import org.springframework.http.HttpHeaders; @@ -30,10 +27,13 @@ import org.springframework.http.HttpStatus; import org.springframework.http.client.ClientHttpResponse; import org.springframework.web.client.HttpMessageConverterExtractor; -import feign.FeignException; -import feign.Response; -import feign.codec.DecodeException; -import feign.codec.Decoder; +import java.io.IOException; +import java.io.InputStream; +import java.lang.reflect.ParameterizedType; +import java.lang.reflect.Type; +import java.lang.reflect.WildcardType; + +import static org.springframework.cloud.netflix.feign.support.FeignUtils.getHttpHeaders; /** * @author Spencer Gibb @@ -49,7 +49,7 @@ public class SpringDecoder implements Decoder { @Override public Object decode(final Response response, Type type) throws IOException, FeignException { - if (type instanceof Class || type instanceof ParameterizedType) { + if (type instanceof Class || type instanceof ParameterizedType || type instanceof WildcardType) { @SuppressWarnings({ "unchecked", "rawtypes" }) HttpMessageConverterExtractor extractor = new HttpMessageConverterExtractor( type, this.messageConverters.getObject().getConverters()); diff --git a/spring-cloud-netflix-core/src/test/java/org/springframework/cloud/netflix/feign/SpringDecoderTests.java b/spring-cloud-netflix-core/src/test/java/org/springframework/cloud/netflix/feign/SpringDecoderTests.java index 949864da..13221bc2 100644 --- a/spring-cloud-netflix-core/src/test/java/org/springframework/cloud/netflix/feign/SpringDecoderTests.java +++ b/spring-cloud-netflix-core/src/test/java/org/springframework/cloud/netflix/feign/SpringDecoderTests.java @@ -16,13 +16,9 @@ package org.springframework.cloud.netflix.feign; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertNull; - -import java.util.ArrayList; -import java.util.List; - +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; @@ -36,13 +32,16 @@ import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.test.annotation.DirtiesContext; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RestController; -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.NoArgsConstructor; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +import static org.junit.Assert.*; /** * @author Spencer Gibb @@ -108,6 +107,19 @@ public class SpringDecoderTests extends FeignClientFactoryBean { assertEquals("first hello didn't match", "hello world 1", hellos.get(0)); } + @Test + @SuppressWarnings("unchecked") + public void testWildcardTypeDecode() { + ResponseEntity wildcard = testClient().getWildcard(); + assertNotNull("wildcard was null", wildcard); + assertEquals("wrong status code", HttpStatus.OK, wildcard.getStatusCode()); + Object wildcardBody = wildcard.getBody(); + assertNotNull("wildcardBody was null", wildcardBody); + assertTrue("wildcard not an instance of Map", wildcardBody instanceof Map); + Map hello = (Map) wildcardBody; + assertEquals("first hello didn't match", "wildcard", hello.get("message")); + } + @Test public void testResponseEntityVoid() { ResponseEntity response = testClient().getHelloVoid(); @@ -156,6 +168,9 @@ public class SpringDecoderTests extends FeignClientFactoryBean { @RequestMapping(method = RequestMethod.GET, value = "/hellonotfound") ResponseEntity getNotFound(); + + @GetMapping("/helloWildcard") + ResponseEntity getWildcard(); } @Configuration @@ -199,6 +214,11 @@ public class SpringDecoderTests extends FeignClientFactoryBean { return ResponseEntity.status(HttpStatus.NOT_FOUND).body((String) null); } + @Override + public ResponseEntity getWildcard() { + return ResponseEntity.ok(new Hello("wildcard")); + } + public static void main(String[] args) { new SpringApplicationBuilder(Application.class) .properties("spring.application.name=springdecodertest",