From 1e12b7456e430d075d53a38e05e265c8ef8c277e Mon Sep 17 00:00:00 2001 From: Spencer Gibb Date: Mon, 20 Oct 2014 18:07:56 -0600 Subject: [PATCH] Add Feign support for Spring MVC parameter and header annotations. Specifically RequestParam, PathVariable and RequestHeader fixes gh-36 --- .../netflix/feign/SpringMvcContract.java | 55 +++++++++++++++++++ 1 file changed, 55 insertions(+) diff --git a/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/feign/SpringMvcContract.java b/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/feign/SpringMvcContract.java index 232d6503..1ad2a183 100644 --- a/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/feign/SpringMvcContract.java +++ b/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/feign/SpringMvcContract.java @@ -6,11 +6,16 @@ import static feign.Util.emptyToNull; import java.lang.annotation.Annotation; import java.lang.reflect.Method; import java.util.Arrays; +import java.util.Collection; +import java.util.Map; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestHeader; import org.springframework.web.bind.annotation.RequestMapping; import feign.Contract; import feign.MethodMetadata; +import org.springframework.web.bind.annotation.RequestParam; /** * @author Spencer Gibb @@ -78,7 +83,57 @@ public class SpringMvcContract extends Contract.BaseContract { @Override protected boolean processAnnotationsOnParameter(MethodMetadata data, Annotation[] annotations, int paramIndex) { + boolean isHttpAnnotation = false; //TODO: support spring parameter annotations? + for (Annotation parameterAnnotation : annotations) { + Class annotationType = parameterAnnotation.annotationType(); + if (annotationType == PathVariable.class) { + String name = PathVariable.class.cast(parameterAnnotation).value(); + checkState(emptyToNull(name) != null, "PathVariable annotation was empty on param %s.", paramIndex); + nameParam(data, name, paramIndex); + isHttpAnnotation = true; + String varName = '{' + name + '}'; + if (data.template().url().indexOf(varName) == -1 && + !searchMapValues(data.template().queries(), varName) && + !searchMapValues(data.template().headers(), varName)) { + data.formParams().add(name); + } + } else if (annotationType == RequestParam.class) { + String name = RequestParam.class.cast(parameterAnnotation).value(); + checkState(emptyToNull(name) != null, "QueryParam.value() was empty on parameter %s", paramIndex); + Collection query = addTemplatedParam(data.template().queries().get(name), name); + data.template().query(name, query); + nameParam(data, name, paramIndex); + isHttpAnnotation = true; + } else if (annotationType == RequestHeader.class) { + String name = RequestHeader.class.cast(parameterAnnotation).value(); + checkState(emptyToNull(name) != null, "HeaderParam.value() was empty on parameter %s", paramIndex); + Collection header = addTemplatedParam(data.template().headers().get(name), name); + data.template().header(name, header); + nameParam(data, name, paramIndex); + isHttpAnnotation = true; + }/* else if (annotationType == FormParam.class) { + String name = FormParam.class.cast(parameterAnnotation).value(); + checkState(emptyToNull(name) != null, "FormParam.value() was empty on parameter %s", paramIndex); + data.formParams().add(name); + nameParam(data, name, paramIndex); + isHttpAnnotation = true; + }*/ + + } + return isHttpAnnotation; + } + + private boolean searchMapValues(Map> map, V search) { + Collection> values = map.values(); + if (values == null) + return false; + + for (Collection entry : values) { + if (entry.contains(search)) + return true; + } + return false; } }