Commit cff20c5a by Jakub Narloch Committed by Spencer Gibb

Feign handling unparameterized ResponseEntity

fixes gh-612
parent b001fea3
...@@ -5,8 +5,6 @@ import java.lang.reflect.ParameterizedType; ...@@ -5,8 +5,6 @@ import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type; import java.lang.reflect.Type;
import java.util.LinkedList; import java.util.LinkedList;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus; import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity; import org.springframework.http.ResponseEntity;
import org.springframework.util.LinkedMultiValueMap; import org.springframework.util.LinkedMultiValueMap;
...@@ -15,6 +13,7 @@ import org.springframework.util.MultiValueMap; ...@@ -15,6 +13,7 @@ import org.springframework.util.MultiValueMap;
import feign.FeignException; import feign.FeignException;
import feign.Response; import feign.Response;
import feign.codec.Decoder; import feign.codec.Decoder;
import lombok.extern.slf4j.Slf4j;
/** /**
* Decoder adds compatibility for Spring MVC's ResponseEntity to any other decoder via * Decoder adds compatibility for Spring MVC's ResponseEntity to any other decoder via
...@@ -34,19 +33,30 @@ public class ResponseEntityDecoder implements Decoder { ...@@ -34,19 +33,30 @@ public class ResponseEntityDecoder implements Decoder {
public Object decode(final Response response, Type type) throws IOException, public Object decode(final Response response, Type type) throws IOException,
FeignException { FeignException {
if (type instanceof ParameterizedType if (isParameterizeResponseEntity(type)) {
&& ((ParameterizedType) type).getRawType().equals(ResponseEntity.class)) {
type = ((ParameterizedType) type).getActualTypeArguments()[0]; type = ((ParameterizedType) type).getActualTypeArguments()[0];
Object decodedObject = decoder.decode(response, type); Object decodedObject = decoder.decode(response, type);
return createResponse(decodedObject, response); return createResponse(decodedObject, response);
} }
else if (isResponseEntity(type)) {
return createResponse(null, response);
}
else { else {
return decoder.decode(response, type); return decoder.decode(response, type);
} }
} }
private boolean isParameterizeResponseEntity(Type type) {
return type instanceof ParameterizedType
&& ((ParameterizedType) type).getRawType().equals(ResponseEntity.class);
}
private boolean isResponseEntity(Type type) {
return type instanceof Class && type.equals(ResponseEntity.class);
}
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
private <T> ResponseEntity<T> createResponse(Object instance, Response response) { private <T> ResponseEntity<T> createResponse(Object instance, Response response) {
......
...@@ -48,6 +48,8 @@ import org.springframework.cloud.netflix.ribbon.RibbonClient; ...@@ -48,6 +48,8 @@ import org.springframework.cloud.netflix.ribbon.RibbonClient;
import org.springframework.cloud.netflix.ribbon.StaticServerList; import org.springframework.cloud.netflix.ribbon.StaticServerList;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.test.annotation.DirtiesContext; import org.springframework.test.annotation.DirtiesContext;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.web.bind.annotation.RequestHeader; import org.springframework.web.bind.annotation.RequestHeader;
...@@ -110,6 +112,12 @@ public class FeignClientTests { ...@@ -110,6 +112,12 @@ public class FeignClientTests {
@RequestMapping(method = RequestMethod.GET, value = "/hellos") @RequestMapping(method = RequestMethod.GET, value = "/hellos")
HystrixCommand<List<Hello>> getHellosHystrix(); HystrixCommand<List<Hello>> getHellosHystrix();
@RequestMapping(method = RequestMethod.GET, value = "/noContent")
ResponseEntity noContent();
@RequestMapping(method = RequestMethod.HEAD, value = "/head")
ResponseEntity head();
} }
@FeignClient(serviceId = "localapp") @FeignClient(serviceId = "localapp")
...@@ -179,6 +187,16 @@ public class FeignClientTests { ...@@ -179,6 +187,16 @@ public class FeignClientTests {
return params; return params;
} }
@RequestMapping(method = RequestMethod.GET, value = "/noContent")
ResponseEntity noContent() {
return ResponseEntity.noContent().build();
}
@RequestMapping(method = RequestMethod.HEAD, value = "/head")
ResponseEntity head() {
return ResponseEntity.ok().build();
}
public static void main(String[] args) { public static void main(String[] args) {
new SpringApplicationBuilder(Application.class).properties( new SpringApplicationBuilder(Application.class).properties(
"spring.application.name=feignclienttest", "spring.application.name=feignclienttest",
...@@ -259,6 +277,20 @@ public class FeignClientTests { ...@@ -259,6 +277,20 @@ public class FeignClientTests {
assertEquals("hellos didn't match", hellos, getHelloList()); assertEquals("hellos didn't match", hellos, getHelloList());
} }
@Test
public void testNoContentResponse() {
ResponseEntity response = testClient.noContent();
assertNotNull("response was null", response);
assertEquals("status code was wrong", HttpStatus.NO_CONTENT, response.getStatusCode());
}
@Test
public void testHeadResponse() {
ResponseEntity response = testClient.head();
assertNotNull("response was null", response);
assertEquals("status code was wrong", HttpStatus.OK, response.getStatusCode());
}
@Data @Data
@AllArgsConstructor @AllArgsConstructor
@NoArgsConstructor @NoArgsConstructor
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment