diff --git a/src/main/java/org/springframework/data/web/ProjectedPayload.java b/src/main/java/org/springframework/data/web/ProjectedPayload.java index 51dbd7d3d5..84c439a139 100644 --- a/src/main/java/org/springframework/data/web/ProjectedPayload.java +++ b/src/main/java/org/springframework/data/web/ProjectedPayload.java @@ -15,11 +15,10 @@ */ package org.springframework.data.web; -import static java.lang.annotation.ElementType.*; -import static java.lang.annotation.RetentionPolicy.*; - import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; /** @@ -27,11 +26,12 @@ * response payloads to. * * @author Oliver Gierke + * @author Chris Bono * @soundtrack * @since 1.13 */ @Documented -@Retention(RUNTIME) -@Target(TYPE) +@Retention(RetentionPolicy.RUNTIME) +@Target({ ElementType.TYPE, ElementType.PARAMETER }) public @interface ProjectedPayload { } diff --git a/src/main/java/org/springframework/data/web/ProxyingHandlerMethodArgumentResolver.java b/src/main/java/org/springframework/data/web/ProxyingHandlerMethodArgumentResolver.java index 99cbe96dd1..c47881852c 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) + 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..8f9988611a 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,30 @@ 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(); + } + + @Test // GH-3258 + void doesSupportAtProjectedPayload() throws Exception { + + var parameter = getParameter("withProjectedPayload", SampleInterface.class); + + assertThat(resolver.supportsParameter(parameter)).isTrue(); + } + + @Test // GH-3258 + void doesNotSupportAtProjectedPayloadForMultipartParam() throws Exception { + + var parameter = getParameter("withProjectedPayloadMultipart", 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 +138,11 @@ interface Controller { void withForeignAnnotation(@Autowired SampleInterface param); void withModelAttribute(@ModelAttribute SampleInterface param); + + void withModelAttributeMultipart(@ModelAttribute MultipartFile file); + + void withProjectedPayload(@ProjectedPayload SampleInterface param); + + void withProjectedPayloadMultipart(@ProjectedPayload MultipartFile file); } }