diff --git a/src/main/java/org/springframework/data/web/ProxyingHandlerMethodArgumentResolver.java b/src/main/java/org/springframework/data/web/ProxyingHandlerMethodArgumentResolver.java index a21117aac8..0d4313b4a8 100644 --- a/src/main/java/org/springframework/data/web/ProxyingHandlerMethodArgumentResolver.java +++ b/src/main/java/org/springframework/data/web/ProxyingHandlerMethodArgumentResolver.java @@ -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.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 boolean supportsParameter(MethodParameter parameter) { } // 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 boolean supportsParameter(MethodParameter parameter) { 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); diff --git a/src/test/java/SampleInterface.java b/src/test/java/example/SampleInterface.java similarity index 97% rename from src/test/java/SampleInterface.java rename to src/test/java/example/SampleInterface.java index 63cd44993c..df4670612e 100644 --- a/src/test/java/SampleInterface.java +++ b/src/test/java/example/SampleInterface.java @@ -18,4 +18,7 @@ * @author Oliver Gierke * @see org.springframework.data.web.ProxyingHandlerMethodArgumentResolverUnitTests */ +package example; + + public interface SampleInterface {} diff --git a/src/test/java/org/springframework/data/web/ProxyingHandlerMethodArgumentResolverUnitTests.java b/src/test/java/org/springframework/data/web/ProxyingHandlerMethodArgumentResolverUnitTests.java index ef24f46e24..602efd22fa 100755 --- a/src/test/java/org/springframework/data/web/ProxyingHandlerMethodArgumentResolverUnitTests.java +++ b/src/test/java/org/springframework/data/web/ProxyingHandlerMethodArgumentResolverUnitTests.java @@ -17,12 +17,16 @@ 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 @@ void doesNotSupportCoreJavaType() throws Exception { 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 @@ interface Controller { void with(SampleInterface param); void with(List param); + + void withForeignAnnotation(@Autowired SampleInterface param); + + void withModelAttribute(@ModelAttribute SampleInterface param); } }