allow feign to decode parameterized types. Added SpringDecoderTests.
fixes gh-57
This commit is contained in:
@@ -2,6 +2,7 @@ package org.springframework.cloud.netflix.feign;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.lang.reflect.ParameterizedType;
|
||||
import java.lang.reflect.Type;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
@@ -31,18 +32,17 @@ public class SpringDecoder implements Decoder {
|
||||
|
||||
@Override
|
||||
public Object decode(final Response response, Type type) throws IOException, FeignException {
|
||||
if (type instanceof Class) {
|
||||
@SuppressWarnings({ "unchecked", "rawtypes" })
|
||||
HttpMessageConverterExtractor<?> extractor = new HttpMessageConverterExtractor(
|
||||
(Class<?>) type, messageConverters.getConverters());
|
||||
if (type instanceof Class || type instanceof ParameterizedType) {
|
||||
@SuppressWarnings({ "unchecked", "rawtypes" })
|
||||
HttpMessageConverterExtractor<?> extractor = new HttpMessageConverterExtractor(
|
||||
type, messageConverters.getConverters());
|
||||
|
||||
Object data = extractor.extractData(new FeignResponseAdapter(response));
|
||||
return data;
|
||||
}
|
||||
throw new DecodeException("type is not an instance of Class: " + type);
|
||||
return extractor.extractData(new FeignResponseAdapter(response));
|
||||
}
|
||||
throw new DecodeException("type is not an instance of Class or ParameterizedType: " + type);
|
||||
}
|
||||
|
||||
private class FeignResponseAdapter implements ClientHttpResponse {
|
||||
private class FeignResponseAdapter implements ClientHttpResponse {
|
||||
private final Response response;
|
||||
|
||||
private FeignResponseAdapter(Response response) {
|
||||
|
||||
@@ -0,0 +1,111 @@
|
||||
package org.springframework.cloud.netflix.feign;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
|
||||
import org.springframework.boot.builder.SpringApplicationBuilder;
|
||||
import org.springframework.boot.test.IntegrationTest;
|
||||
import org.springframework.boot.test.SpringApplicationConfiguration;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
import org.springframework.test.context.web.WebAppConfiguration;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMethod;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author Spencer Gibb
|
||||
*/
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@SpringApplicationConfiguration(classes = SpringDecoderTests.Application.class)
|
||||
@WebAppConfiguration
|
||||
@IntegrationTest({ "server.port=0", "spring.application.name=springdecodertest", "spring.jmx.enabled=true" })
|
||||
public class SpringDecoderTests extends FeignConfigurer {
|
||||
|
||||
@Value("${local.server.port}")
|
||||
private int port = 0;
|
||||
|
||||
public TestClient testClient() {
|
||||
return feign().target(TestClient.class, "http://localhost:"+port);
|
||||
}
|
||||
|
||||
protected static interface TestClient {
|
||||
@RequestMapping(method = RequestMethod.GET, value = "/hello")
|
||||
public Hello getHello();
|
||||
|
||||
@RequestMapping(method = RequestMethod.GET, value = "/hellos")
|
||||
public List<Hello> getHellos();
|
||||
|
||||
@RequestMapping(method = RequestMethod.GET, value = "/hellostrings")
|
||||
public List<String> getHelloStrings();
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@EnableAutoConfiguration
|
||||
@RestController
|
||||
protected static class Application implements TestClient {
|
||||
|
||||
public Hello getHello() {
|
||||
return new Hello("hello world 1");
|
||||
}
|
||||
|
||||
public List<Hello> getHellos() {
|
||||
ArrayList<Hello> hellos = new ArrayList<>();
|
||||
hellos.add(new Hello("hello world 1"));
|
||||
hellos.add(new Hello("oi terra 2"));
|
||||
return hellos;
|
||||
}
|
||||
|
||||
public List<String> getHelloStrings() {
|
||||
ArrayList<String> hellos = new ArrayList<>();
|
||||
hellos.add("hello world 1");
|
||||
hellos.add("oi terra 2");
|
||||
return hellos;
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
new SpringApplicationBuilder(Application.class).properties(
|
||||
"spring.application.name=springdecodertest", "management.contextPath=/admin")
|
||||
.run(args);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSimpleType() {
|
||||
Hello hello = testClient().getHello();
|
||||
assertNotNull("hello was null", hello);
|
||||
assertEquals("first hello didn't match", new Hello("hello world 1"), hello);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUserParameterizedTypeDecode() {
|
||||
List<Hello> hellos = testClient().getHellos();
|
||||
assertNotNull("hellos was null", hellos);
|
||||
assertEquals("hellos was not the right size", 2, hellos.size());
|
||||
assertEquals("first hello didn't match", new Hello("hello world 1"), hellos.get(0));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSimpleParameterizedTypeDecode() {
|
||||
List<String> hellos = testClient().getHelloStrings();
|
||||
assertNotNull("hellos was null", hellos);
|
||||
assertEquals("hellos was not the right size", 2, hellos.size());
|
||||
assertEquals("first hello didn't match", "hello world 1", hellos.get(0));
|
||||
}
|
||||
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public static class Hello {
|
||||
private String message;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user