From 50ed5785594e725a3a836d3aa58de46dfe4f5e2f Mon Sep 17 00:00:00 2001 From: Chris Bono Date: Thu, 24 Apr 2025 10:49:46 -0500 Subject: [PATCH] Avoid matching multipart parameters annotated with @ModelAttribute The ProxyHandlerMethodArgumentResolver now avoids matching multipart parameters annotated with @ModelAttribute. This allows multipart parameters to be handled by RequestParamMethodArgumentResolver which properly handles multipart arguments. Fixes #3258 Related tickets #2937 Signed-off-by: Chris Bono --- .../web/ProxyingHandlerMethodArgumentResolver.java | 8 +++++--- ...oxyingHandlerMethodArgumentResolverUnitTests.java | 12 ++++++++++++ 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/src/main/java/org/springframework/data/web/ProxyingHandlerMethodArgumentResolver.java b/src/main/java/org/springframework/data/web/ProxyingHandlerMethodArgumentResolver.java index e5bf588c6f..6f0a733366 100644 --- a/src/main/java/org/springframework/data/web/ProxyingHandlerMethodArgumentResolver.java +++ b/src/main/java/org/springframework/data/web/ProxyingHandlerMethodArgumentResolver.java @@ -36,11 +36,13 @@ import org.springframework.web.context.request.NativeWebRequest; import org.springframework.web.method.annotation.ModelAttributeMethodProcessor; import org.springframework.web.method.support.HandlerMethodArgumentResolver; +import org.springframework.web.multipart.support.MultipartResolutionDelegate; /** * {@link HandlerMethodArgumentResolver} to create Proxy instances for interface based controller method parameters. * * @author Oliver Gierke + * @author Chris Bono * @since 1.10 */ public class ProxyingHandlerMethodArgumentResolver extends ModelAttributeMethodProcessor @@ -88,9 +90,9 @@ public boolean supportsParameter(MethodParameter parameter) { return false; } - // Annotated parameter - if (parameter.getParameterAnnotation(ProjectedPayload.class) != null - || parameter.getParameterAnnotation(ModelAttribute.class) != null) { + // Annotated parameter (excluding multipart @ModelAttribute) + if (parameter.hasParameterAnnotation(ProjectedPayload.class) || + (parameter.hasParameterAnnotation(ModelAttribute.class) && !MultipartResolutionDelegate.isMultipartArgument(parameter))) { return true; } diff --git a/src/test/java/org/springframework/data/web/ProxyingHandlerMethodArgumentResolverUnitTests.java b/src/test/java/org/springframework/data/web/ProxyingHandlerMethodArgumentResolverUnitTests.java index 85f14ea2f3..c7a1bdc274 100755 --- a/src/test/java/org/springframework/data/web/ProxyingHandlerMethodArgumentResolverUnitTests.java +++ b/src/test/java/org/springframework/data/web/ProxyingHandlerMethodArgumentResolverUnitTests.java @@ -27,11 +27,13 @@ import org.springframework.core.convert.support.DefaultConversionService; import org.springframework.util.ReflectionUtils; import org.springframework.web.bind.annotation.ModelAttribute; +import org.springframework.web.multipart.MultipartFile; /** * Unit tests for {@link ProxyingHandlerMethodArgumentResolver}. * * @author Oliver Gierke + * @author Chris Bono * @soundtrack Karlijn Langendijk & Sönke Meinen - Englishman In New York (Sting, * https://www.youtube.com/watch?v=O7LZsqrnaaA) */ @@ -88,6 +90,14 @@ void doesSupportAtModelAttribute() throws Exception { assertThat(resolver.supportsParameter(parameter)).isTrue(); } + @Test // GH-3258 + void doesNotSupportAtModelAttributeForMultipartParam() throws Exception { + + var parameter = getParameter("withModelAttributeMultipart", MultipartFile.class); + + assertThat(resolver.supportsParameter(parameter)).isFalse(); + } + private static MethodParameter getParameter(String methodName, Class parameterType) { var method = ReflectionUtils.findMethod(Controller.class, methodName, parameterType); @@ -112,5 +122,7 @@ interface Controller { void withForeignAnnotation(@Autowired SampleInterface param); void withModelAttribute(@ModelAttribute SampleInterface param); + + void withModelAttributeMultipart(@ModelAttribute MultipartFile file); } }