Skip to content

Commit a91d8f5

Browse files
authored
Do not warn if first parameter of GetMapping is of type URL. Fixes #1326 (#1327)
1 parent 3f6cd2e commit a91d8f5

File tree

2 files changed

+85
-3
lines changed

2 files changed

+85
-3
lines changed

spring-cloud-openfeign-core/src/main/java/org/springframework/cloud/openfeign/support/SpringMvcContract.java

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
import java.lang.reflect.Method;
2121
import java.lang.reflect.Parameter;
2222
import java.lang.reflect.Type;
23+
import java.net.URI;
2324
import java.util.ArrayList;
2425
import java.util.Arrays;
2526
import java.util.Collection;
@@ -239,7 +240,8 @@ public MethodMetadata parseAndValidateMetadata(Class<?> targetType, Method metho
239240
processedMethods.put(Feign.configKey(targetType, method), method);
240241
MethodMetadata metadata = super.parseAndValidateMetadata(targetType, method);
241242

242-
if (isGetMethod(metadata) && method.getParameterCount() > 0 && !hasHttpAnnotations(method)) {
243+
if (isGetMethod(metadata) && method.getParameterCount() > 0
244+
&& shouldWarnAboutUnannotatedGetParameters(method)) {
243245
if (LOG.isWarnEnabled()) {
244246
LOG.warn(String
245247
.format("[OpenFeign Warning] Feign method '%s' is declared as GET with parameters, but none of the parameters are annotated "
@@ -255,8 +257,19 @@ private boolean isGetMethod(MethodMetadata metadata) {
255257
return "GET".equalsIgnoreCase(metadata.template().method());
256258
}
257259

258-
private boolean hasHttpAnnotations(Method method) {
259-
for (Parameter parameter : method.getParameters()) {
260+
private boolean shouldWarnAboutUnannotatedGetParameters(Method method) {
261+
Parameter[] params = method.getParameters();
262+
if (params.length == 1 && params[0].getType() == URI.class) {
263+
return false;
264+
}
265+
int fromIndex = (params.length > 0 && params[0].getType() == URI.class) ? 1 : 0;
266+
return !hasHttpAnnotations(method, fromIndex);
267+
}
268+
269+
private boolean hasHttpAnnotations(Method method, int fromIndex) {
270+
Parameter[] parameters = method.getParameters();
271+
for (int i = fromIndex; i < parameters.length; i++) {
272+
Parameter parameter = parameters[i];
260273
for (Annotation annotation : parameter.getAnnotations()) {
261274
Class<? extends Annotation> annotationType = annotation.annotationType();
262275
if (annotationType == RequestParam.class || annotationType == RequestHeader.class

spring-cloud-openfeign-core/src/test/java/org/springframework/cloud/openfeign/support/SpringMvcContractTests.java

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
import java.lang.reflect.InvocationTargetException;
2020
import java.lang.reflect.Method;
2121
import java.math.BigDecimal;
22+
import java.net.URI;
2223
import java.time.LocalDateTime;
2324
import java.time.format.DateTimeFormatter;
2425
import java.util.Collection;
@@ -34,7 +35,10 @@
3435
import feign.Param;
3536
import org.junit.jupiter.api.BeforeEach;
3637
import org.junit.jupiter.api.Test;
38+
import org.junit.jupiter.api.extension.ExtendWith;
3739

40+
import org.springframework.boot.test.system.CapturedOutput;
41+
import org.springframework.boot.test.system.OutputCaptureExtension;
3842
import org.springframework.cloud.openfeign.CollectionFormat;
3943
import org.springframework.cloud.openfeign.FeignClientProperties;
4044
import org.springframework.cloud.openfeign.SpringQueryMap;
@@ -87,6 +91,7 @@
8791
* @author Tang Xiong
8892
**/
8993

94+
@ExtendWith(OutputCaptureExtension.class)
9095
class SpringMvcContractTests {
9196

9297
private static final Class<?> EXECUTABLE_TYPE;
@@ -216,6 +221,42 @@ void testProcessAnnotations_SimplePathIsOnlyASlashWithParamWithTrailingSlashRemo
216221
.isEqualTo(MediaType.APPLICATION_JSON_VALUE);
217222
}
218223

224+
@Test
225+
void getWithSingleUriParameterShouldNotWarn(CapturedOutput output) throws Exception {
226+
Method method = GetWithUriParameter.class.getDeclaredMethod("getValue", URI.class);
227+
MethodMetadata data = contract.parseAndValidateMetadata(method.getDeclaringClass(), method);
228+
229+
assertThat(data.template().method()).isEqualTo("GET");
230+
assertThat(output).doesNotContain("OpenFeign Warning");
231+
}
232+
233+
@Test
234+
void getWithUnannotatedNonUriParameterShouldWarn(CapturedOutput output) throws Exception {
235+
Method method = GetWithUnannotatedParam.class.getDeclaredMethod("getValue", String.class);
236+
contract.parseAndValidateMetadata(method.getDeclaringClass(), method);
237+
238+
assertThat(output).contains("OpenFeign Warning",
239+
"is declared as GET with parameters, but none of the parameters are annotated");
240+
}
241+
242+
@Test
243+
void getWithUriAndUnannotatedParameterShouldWarn(CapturedOutput output) throws Exception {
244+
Method method = GetWithUriAndUnannotatedParam.class.getDeclaredMethod("getValue", URI.class, String.class);
245+
contract.parseAndValidateMetadata(method.getDeclaringClass(), method);
246+
247+
assertThat(output).contains("OpenFeign Warning",
248+
"is declared as GET with parameters, but none of the parameters are annotated");
249+
}
250+
251+
@Test
252+
void getWithUriAndAnnotatedParameterShouldNotWarn(CapturedOutput output) throws Exception {
253+
Method method = GetWithUriAndAnnotatedParam.class.getDeclaredMethod("getValue", URI.class, String.class);
254+
MethodMetadata data = contract.parseAndValidateMetadata(method.getDeclaringClass(), method);
255+
256+
assertThat(data.template().method()).isEqualTo("GET");
257+
assertThat(output).doesNotContain("OpenFeign Warning");
258+
}
259+
219260
@Test
220261
void testProcessAnnotations_MissingLeadingSlashInPath() throws Exception {
221262
Method method = TestTemplate_Simple.class.getDeclaredMethod("getTestNoLeadingSlash", String.class);
@@ -810,6 +851,34 @@ public interface TestTemplate_Simple {
810851

811852
}
812853

854+
interface GetWithUriParameter {
855+
856+
@GetMapping("/sample/receive")
857+
String getValue(URI baseUri);
858+
859+
}
860+
861+
interface GetWithUnannotatedParam {
862+
863+
@GetMapping("/test")
864+
String getValue(String id);
865+
866+
}
867+
868+
interface GetWithUriAndUnannotatedParam {
869+
870+
@GetMapping("/sample/receive")
871+
String getValue(URI baseUri, String unannotated);
872+
873+
}
874+
875+
interface GetWithUriAndAnnotatedParam {
876+
877+
@GetMapping("/sample/receive")
878+
String getValue(URI baseUri, @RequestParam("id") String id);
879+
880+
}
881+
813882
@RequestMapping("/prepend/{classId}")
814883
public interface TestTemplate_Class_RequestMapping {
815884

0 commit comments

Comments
 (0)