Skip to content

Commit 5619b7d

Browse files
committed
ProxyHandlerMethodArgumentResolver now avoids matching parameters annotated with Spring annotation.
We now explicitly do not match handler method parameters that are annotated with anything but @ModelAttribute or @ProjectedPayload. This prevents us accidentally opting into parameter handling for annotated parameters that use interfaces for their declaration and are supposed to be handled by some other infrastructure. Fixes GH-2937.
1 parent d50d9b6 commit 5619b7d

File tree

3 files changed

+47
-2
lines changed

3 files changed

+47
-2
lines changed

Diff for: src/main/java/org/springframework/data/web/ProxyingHandlerMethodArgumentResolver.java

+13-1
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
*/
1616
package org.springframework.data.web;
1717

18+
import java.lang.annotation.Annotation;
1819
import java.util.Arrays;
1920
import java.util.List;
2021

@@ -30,6 +31,7 @@
3031
import org.springframework.data.projection.SpelAwareProxyProjectionFactory;
3132
import org.springframework.util.ClassUtils;
3233
import org.springframework.web.bind.WebDataBinder;
34+
import org.springframework.web.bind.annotation.ModelAttribute;
3335
import org.springframework.web.bind.support.WebDataBinderFactory;
3436
import org.springframework.web.context.request.NativeWebRequest;
3537
import org.springframework.web.method.annotation.ModelAttributeMethodProcessor;
@@ -87,7 +89,8 @@ public boolean supportsParameter(MethodParameter parameter) {
8789
}
8890

8991
// Annotated parameter
90-
if (parameter.getParameterAnnotation(ProjectedPayload.class) != null) {
92+
if (parameter.getParameterAnnotation(ProjectedPayload.class) != null
93+
|| parameter.getParameterAnnotation(ModelAttribute.class) != null) {
9194
return true;
9295
}
9396

@@ -96,6 +99,15 @@ public boolean supportsParameter(MethodParameter parameter) {
9699
return true;
97100
}
98101

102+
// Exclude parameters annotated with Spring annotation
103+
if (Arrays.stream(parameter.getParameterAnnotations())
104+
.map(Annotation::annotationType)
105+
.map(Class::getPackageName)
106+
.anyMatch(it -> it.startsWith("org.springframework"))) {
107+
108+
return false;
109+
}
110+
99111
// Fallback for only user defined interfaces
100112
String packageName = ClassUtils.getPackageName(type);
101113

Diff for: src/test/java/SampleInterface.java renamed to src/test/java/example/SampleInterface.java

+3
Original file line numberDiff line numberDiff line change
@@ -18,4 +18,7 @@
1818
* @author Oliver Gierke
1919
* @see org.springframework.data.web.ProxyingHandlerMethodArgumentResolverUnitTests
2020
*/
21+
package example;
22+
23+
2124
public interface SampleInterface {}

Diff for: src/test/java/org/springframework/data/web/ProxyingHandlerMethodArgumentResolverUnitTests.java

+31-1
Original file line numberDiff line numberDiff line change
@@ -17,12 +17,16 @@
1717

1818
import static org.assertj.core.api.Assertions.*;
1919

20+
import example.SampleInterface;
21+
2022
import java.util.List;
2123

2224
import org.junit.jupiter.api.Test;
25+
import org.springframework.beans.factory.annotation.Autowired;
2326
import org.springframework.core.MethodParameter;
2427
import org.springframework.core.convert.support.DefaultConversionService;
25-
import org.springframework.data.web.ProjectingJackson2HttpMessageConverterUnitTests.SampleInterface;
28+
import org.springframework.util.ReflectionUtils;
29+
import org.springframework.web.bind.annotation.ModelAttribute;
2630

2731
/**
2832
* Unit tests for {@link ProxyingHandlerMethodArgumentResolver}.
@@ -72,6 +76,28 @@ void doesNotSupportCoreJavaType() throws Exception {
7276
assertThat(resolver.supportsParameter(parameter)).isFalse();
7377
}
7478

79+
@Test // GH-2937
80+
void doesNotSupportForeignSpringAnnotations() throws Exception {
81+
82+
var parameter = getParameter("withForeignAnnotation", SampleInterface.class);
83+
84+
assertThat(resolver.supportsParameter(parameter)).isFalse();
85+
}
86+
87+
@Test // GH-2937
88+
void doesSupportAtModelAttribute() throws Exception {
89+
90+
var parameter = getParameter("withModelAttribute", SampleInterface.class);
91+
92+
assertThat(resolver.supportsParameter(parameter)).isTrue();
93+
}
94+
95+
private static MethodParameter getParameter(String methodName, Class<?> parameterType) {
96+
97+
var method = ReflectionUtils.findMethod(Controller.class, methodName, parameterType);
98+
return new MethodParameter(method, 0);
99+
}
100+
75101
@ProjectedPayload
76102
interface AnnotatedInterface {}
77103

@@ -86,5 +112,9 @@ interface Controller {
86112
void with(SampleInterface param);
87113

88114
void with(List<Object> param);
115+
116+
void withForeignAnnotation(@Autowired SampleInterface param);
117+
118+
void withModelAttribute(@ModelAttribute SampleInterface param);
89119
}
90120
}

0 commit comments

Comments
 (0)