Skip to content

Commit 9f71c98

Browse files
committed
Expose parameter annotations from interfaces across entire class hierarchy
Closes gh-24127
1 parent dbb0933 commit 9f71c98

File tree

2 files changed

+33
-3
lines changed

2 files changed

+33
-3
lines changed

spring-web/src/main/java/org/springframework/web/method/HandlerMethod.java

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2019 the original author or authors.
2+
* Copyright 2002-2020 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -339,7 +339,7 @@ private List<Annotation[][]> getInterfaceParameterAnnotations() {
339339
List<Annotation[][]> parameterAnnotations = this.interfaceParameterAnnotations;
340340
if (parameterAnnotations == null) {
341341
parameterAnnotations = new ArrayList<>();
342-
for (Class<?> ifc : this.method.getDeclaringClass().getInterfaces()) {
342+
for (Class<?> ifc : ClassUtils.getAllInterfacesForClassAsSet(this.method.getDeclaringClass())) {
343343
for (Method candidate : ifc.getMethods()) {
344344
if (isOverrideFor(candidate)) {
345345
parameterAnnotations.add(candidate.getParameterAnnotations());

spring-webmvc/src/test/java/org/springframework/web/servlet/mvc/method/annotation/RequestResponseBodyMethodProcessorTests.java

+31-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2018 the original author or authors.
2+
* Copyright 2002-2020 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -703,6 +703,27 @@ public void resolveArgumentTypeVariableWithGenericInterface() throws Exception {
703703

704704
RequestResponseBodyMethodProcessor processor = new RequestResponseBodyMethodProcessor(converters);
705705

706+
assertTrue(processor.supportsParameter(methodParameter));
707+
String value = (String) processor.readWithMessageConverters(
708+
this.request, methodParameter, methodParameter.getGenericParameterType());
709+
assertEquals("foo", value);
710+
}
711+
712+
@Test // gh-24127
713+
public void resolveArgumentTypeVariableWithGenericInterfaceAndSubclass() throws Exception {
714+
this.servletRequest.setContent("\"foo\"".getBytes("UTF-8"));
715+
this.servletRequest.setContentType(MediaType.APPLICATION_JSON_UTF8_VALUE);
716+
717+
Method method = SubControllerImplementingInterface.class.getMethod("handle", Object.class);
718+
HandlerMethod handlerMethod = new HandlerMethod(new SubControllerImplementingInterface(), method);
719+
MethodParameter methodParameter = handlerMethod.getMethodParameters()[0];
720+
721+
List<HttpMessageConverter<?>> converters = new ArrayList<>();
722+
converters.add(new MappingJackson2HttpMessageConverter());
723+
724+
RequestResponseBodyMethodProcessor processor = new RequestResponseBodyMethodProcessor(converters);
725+
726+
assertTrue(processor.supportsParameter(methodParameter));
706727
String value = (String) processor.readWithMessageConverters(
707728
this.request, methodParameter, methodParameter.getGenericParameterType());
708729
assertEquals("foo", value);
@@ -1055,4 +1076,13 @@ default A handle(@RequestBody A arg) {
10551076
static class MyControllerImplementingInterface implements MappingInterface<String> {
10561077
}
10571078

1079+
1080+
static class SubControllerImplementingInterface extends MyControllerImplementingInterface {
1081+
1082+
@Override
1083+
public String handle(String arg) {
1084+
return arg;
1085+
}
1086+
}
1087+
10581088
}

0 commit comments

Comments
 (0)