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.
This commit is contained in:
@@ -15,6 +15,7 @@
|
||||
*/
|
||||
package org.springframework.data.web;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
@@ -30,6 +31,7 @@ import org.springframework.core.convert.ConversionService;
|
||||
import org.springframework.data.projection.SpelAwareProxyProjectionFactory;
|
||||
import org.springframework.util.ClassUtils;
|
||||
import org.springframework.web.bind.WebDataBinder;
|
||||
import org.springframework.web.bind.annotation.ModelAttribute;
|
||||
import org.springframework.web.bind.support.WebDataBinderFactory;
|
||||
import org.springframework.web.context.request.NativeWebRequest;
|
||||
import org.springframework.web.method.annotation.ModelAttributeMethodProcessor;
|
||||
@@ -87,7 +89,8 @@ public class ProxyingHandlerMethodArgumentResolver extends ModelAttributeMethodP
|
||||
}
|
||||
|
||||
// Annotated parameter
|
||||
if (parameter.getParameterAnnotation(ProjectedPayload.class) != null) {
|
||||
if (parameter.getParameterAnnotation(ProjectedPayload.class) != null
|
||||
|| parameter.getParameterAnnotation(ModelAttribute.class) != null) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -96,6 +99,15 @@ public class ProxyingHandlerMethodArgumentResolver extends ModelAttributeMethodP
|
||||
return true;
|
||||
}
|
||||
|
||||
// Exclude parameters annotated with Spring annotation
|
||||
if (Arrays.stream(parameter.getParameterAnnotations())
|
||||
.map(Annotation::annotationType)
|
||||
.map(Class::getPackageName)
|
||||
.anyMatch(it -> it.startsWith("org.springframework"))) {
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Fallback for only user defined interfaces
|
||||
String packageName = ClassUtils.getPackageName(type);
|
||||
|
||||
|
||||
@@ -18,4 +18,7 @@
|
||||
* @author Oliver Gierke
|
||||
* @see org.springframework.data.web.ProxyingHandlerMethodArgumentResolverUnitTests
|
||||
*/
|
||||
package example;
|
||||
|
||||
|
||||
public interface SampleInterface {}
|
||||
@@ -17,12 +17,16 @@ package org.springframework.data.web;
|
||||
|
||||
import static org.assertj.core.api.Assertions.*;
|
||||
|
||||
import example.SampleInterface;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.core.MethodParameter;
|
||||
import org.springframework.core.convert.support.DefaultConversionService;
|
||||
import org.springframework.data.web.ProjectingJackson2HttpMessageConverterUnitTests.SampleInterface;
|
||||
import org.springframework.util.ReflectionUtils;
|
||||
import org.springframework.web.bind.annotation.ModelAttribute;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link ProxyingHandlerMethodArgumentResolver}.
|
||||
@@ -72,6 +76,28 @@ public class ProxyingHandlerMethodArgumentResolverUnitTests {
|
||||
assertThat(resolver.supportsParameter(parameter)).isFalse();
|
||||
}
|
||||
|
||||
@Test // GH-2937
|
||||
void doesNotSupportForeignSpringAnnotations() throws Exception {
|
||||
|
||||
var parameter = getParameter("withForeignAnnotation", SampleInterface.class);
|
||||
|
||||
assertThat(resolver.supportsParameter(parameter)).isFalse();
|
||||
}
|
||||
|
||||
@Test // GH-2937
|
||||
void doesSupportAtModelAttribute() throws Exception {
|
||||
|
||||
var parameter = getParameter("withModelAttribute", SampleInterface.class);
|
||||
|
||||
assertThat(resolver.supportsParameter(parameter)).isTrue();
|
||||
}
|
||||
|
||||
private static MethodParameter getParameter(String methodName, Class<?> parameterType) {
|
||||
|
||||
var method = ReflectionUtils.findMethod(Controller.class, methodName, parameterType);
|
||||
return new MethodParameter(method, 0);
|
||||
}
|
||||
|
||||
@ProjectedPayload
|
||||
interface AnnotatedInterface {}
|
||||
|
||||
@@ -86,5 +112,9 @@ public class ProxyingHandlerMethodArgumentResolverUnitTests {
|
||||
void with(SampleInterface param);
|
||||
|
||||
void with(List<Object> param);
|
||||
|
||||
void withForeignAnnotation(@Autowired SampleInterface param);
|
||||
|
||||
void withModelAttribute(@ModelAttribute SampleInterface param);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user