From 57afd733461e2fc1eb1b9766b2fb587f2882a3ce Mon Sep 17 00:00:00 2001 From: Krzysztof Krason Date: Thu, 12 Nov 2020 21:39:34 +0100 Subject: [PATCH] Allows @Param value in default contract to be taken from param names. JEP 118 introduced javac option `-parameters` that adds to bytecode method parameter names, so if code is compiled with that option and @Param value is empty we can get that template parameter name from method parameter name. Fixes #1297. --- core/src/main/java/feign/Contract.java | 9 +++++++- core/src/main/java/feign/Param.java | 2 +- .../test/java/feign/DefaultContractTest.java | 21 +++++++++++++++++++ pom.xml | 15 +++++++++++++ 4 files changed, 45 insertions(+), 2 deletions(-) diff --git a/core/src/main/java/feign/Contract.java b/core/src/main/java/feign/Contract.java index aff6a3b28..6c2741d65 100644 --- a/core/src/main/java/feign/Contract.java +++ b/core/src/main/java/feign/Contract.java @@ -271,7 +271,14 @@ public Default() { data.template().headers(toMap(headersOnMethod)); }); super.registerParameterAnnotation(Param.class, (paramAnnotation, data, paramIndex) -> { - final String name = paramAnnotation.value(); + final String annotationName = paramAnnotation.value(); + final Parameter parameter = data.method().getParameters()[paramIndex]; + final String name; + if (emptyToNull(annotationName) == null && parameter.isNamePresent()){ + name = parameter.getName(); + } else { + name = annotationName; + } checkState(emptyToNull(name) != null, "Param annotation was empty on param %s.", paramIndex); nameParam(data, name, paramIndex); diff --git a/core/src/main/java/feign/Param.java b/core/src/main/java/feign/Param.java index 27e968e8f..7501cc29f 100644 --- a/core/src/main/java/feign/Param.java +++ b/core/src/main/java/feign/Param.java @@ -28,7 +28,7 @@ /** * The name of the template parameter. */ - String value(); + String value() default ""; /** * How to expand the value of this parameter, if {@link ToStringExpander} isn't adequate. diff --git a/core/src/test/java/feign/DefaultContractTest.java b/core/src/test/java/feign/DefaultContractTest.java index 33d1599fd..77c5d20ab 100644 --- a/core/src/test/java/feign/DefaultContractTest.java +++ b/core/src/test/java/feign/DefaultContractTest.java @@ -200,6 +200,21 @@ public void pathAndQueryParams() throws Exception { entry(2, asList("type"))); } + @Test + public void autoDiscoverParamNames() throws Exception { + final MethodMetadata md = parseAndValidateMetadata(AutoDiscoverParamNames.class, + "recordsByNameAndType", int.class, String.class, + String.class); + + assertThat(md.template()) + .hasQueries(entry("name", asList("{name}")), entry("type", asList("{type}"))); + + assertThat(md.indexToName()).containsExactly( + entry(0, asList("domainId")), + entry(1, asList("name")), + entry(2, asList("type"))); + } + @Test public void bodyWithTemplate() throws Exception { final MethodMetadata md = parseAndValidateMetadata(FormParams.class, @@ -517,6 +532,12 @@ Response recordsByNameAndType(@Param("domainId") int id, @Param("type") String typeFilter); } + interface AutoDiscoverParamNames { + + @RequestLine("GET /domains/{domainId}/records?name={name}&type={type}") + Response recordsByNameAndType(@Param int domainId, @Param String name, @Param() String type); +} + interface FormParams { @RequestLine("POST /") diff --git a/pom.xml b/pom.xml index 1432b121f..2f33d70a6 100644 --- a/pom.xml +++ b/pom.xml @@ -417,6 +417,21 @@ ${main.java.version} + + default-test-compile + test-compile + + testCompile + + + true + + -parameters + + ${main.java.version} + ${main.java.version} + +