uriVariables, ConversionService conversionService) {
- Class> paramType = parameter.getParameterType();
+ Class> paramType = parameter.getNestedParameterType();
if (Map.class.isAssignableFrom(paramType) || MultipartFile.class == paramType ||
"javax.servlet.http.Part".equals(paramType.getName())) {
return;
}
RequestParam requestParam = parameter.getParameterAnnotation(RequestParam.class);
- String name = (requestParam == null || StringUtils.isEmpty(requestParam.name()) ? parameter.getParameterName() : requestParam.name());
+ String name = (requestParam == null || StringUtils.isEmpty(requestParam.name()) ?
+ parameter.getParameterName() : requestParam.name());
if (value == null) {
builder.queryParam(name);
@@ -305,12 +251,4 @@ public class RequestParamMethodArgumentResolver extends AbstractNamedValueMethod
}
}
-
- private static class RequestPartResolver {
-
- public static Object resolvePart(HttpServletRequest servletRequest) throws Exception {
- return servletRequest.getParts().toArray(new Part[servletRequest.getParts().size()]);
- }
- }
-
}
diff --git a/spring-web/src/main/java/org/springframework/web/multipart/support/MissingServletRequestPartException.java b/spring-web/src/main/java/org/springframework/web/multipart/support/MissingServletRequestPartException.java
index 422517bd63d..905525b0392 100644
--- a/spring-web/src/main/java/org/springframework/web/multipart/support/MissingServletRequestPartException.java
+++ b/spring-web/src/main/java/org/springframework/web/multipart/support/MissingServletRequestPartException.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2011 the original author or authors.
+ * Copyright 2002-2016 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -24,27 +24,28 @@ import org.springframework.web.multipart.MultipartResolver;
* Raised when the part of a "multipart/form-data" request identified by its
* name cannot be found.
*
- * This may be because the request is not a multipart/form-data
- *
- * either because the part is not present in the request, or
- * because the web application is not configured correctly for processing
- * multipart requests -- e.g. no {@link MultipartResolver}.
+ *
This may be because the request is not a multipart/form-data request,
+ * because the part is not present in the request, or because the web
+ * application is not configured correctly for processing multipart requests,
+ * e.g. no {@link MultipartResolver}.
*
* @author Rossen Stoyanchev
* @since 3.1
*/
+@SuppressWarnings("serial")
public class MissingServletRequestPartException extends ServletException {
- private static final long serialVersionUID = -1255077391966870705L;
-
private final String partName;
+
public MissingServletRequestPartException(String partName) {
- super("Required request part '" + partName + "' is not present.");
+ super("Required request part '" + partName + "' is not present");
this.partName = partName;
}
+
public String getRequestPartName() {
return this.partName;
}
+
}
diff --git a/spring-web/src/main/java/org/springframework/web/multipart/support/MultipartResolutionDelegate.java b/spring-web/src/main/java/org/springframework/web/multipart/support/MultipartResolutionDelegate.java
new file mode 100644
index 00000000000..6d6116f6b18
--- /dev/null
+++ b/spring-web/src/main/java/org/springframework/web/multipart/support/MultipartResolutionDelegate.java
@@ -0,0 +1,197 @@
+/*
+ * Copyright 2002-2016 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.web.multipart.support;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.Part;
+
+import org.springframework.core.GenericCollectionTypeResolver;
+import org.springframework.core.MethodParameter;
+import org.springframework.util.ClassUtils;
+import org.springframework.web.multipart.MultipartException;
+import org.springframework.web.multipart.MultipartFile;
+import org.springframework.web.multipart.MultipartHttpServletRequest;
+import org.springframework.web.util.WebUtils;
+
+/**
+ * A common delegate for {@code HandlerMethodArgumentResolver} implementations
+ * which need to resolve {@link MultipartFile} and {@link Part} arguments.
+ *
+ * @author Juergen Hoeller
+ * @since 4.3
+ */
+public abstract class MultipartResolutionDelegate {
+
+ public static final Object UNRESOLVABLE = new Object();
+
+
+ private static Class> servletPartClass = null;
+
+ static {
+ try {
+ servletPartClass = ClassUtils.forName(
+ "javax.servlet.http.Part", MultipartResolutionDelegate.class.getClassLoader());
+ }
+ catch (ClassNotFoundException ex) {
+ // Servlet 3.0 Part type not available - Part references simply not supported then.
+ }
+ }
+
+
+ public static boolean isMultipartRequest(HttpServletRequest request) {
+ return (WebUtils.getNativeRequest(request, MultipartHttpServletRequest.class) != null ||
+ isMultipartContent(request));
+ }
+
+ private static boolean isMultipartContent(HttpServletRequest request) {
+ String contentType = request.getContentType();
+ return (contentType != null && contentType.toLowerCase().startsWith("multipart/"));
+ }
+
+ static MultipartHttpServletRequest asMultipartHttpServletRequest(HttpServletRequest request) {
+ MultipartHttpServletRequest unwrapped = WebUtils.getNativeRequest(request, MultipartHttpServletRequest.class);
+ if (unwrapped != null) {
+ return unwrapped;
+ }
+ return adaptToMultipartHttpServletRequest(request);
+ }
+
+ private static MultipartHttpServletRequest adaptToMultipartHttpServletRequest(HttpServletRequest request) {
+ if (servletPartClass != null) {
+ // Servlet 3.0 available ..
+ return new StandardMultipartHttpServletRequest(request);
+ }
+ throw new MultipartException("Expected MultipartHttpServletRequest: is a MultipartResolver configured?");
+ }
+
+
+ public static boolean isMultipartArgument(MethodParameter parameter) {
+ Class> paramType = parameter.getNestedParameterType();
+ return (MultipartFile.class == paramType || isMultipartFileCollection(parameter) ||
+ isMultipartFileArray(parameter) || servletPartClass == paramType ||
+ isPartCollection(parameter) || isPartArray(parameter));
+ }
+
+ public static Object resolveMultipartArgument(String name, MethodParameter parameter, HttpServletRequest request)
+ throws Exception {
+
+ MultipartHttpServletRequest multipartRequest =
+ WebUtils.getNativeRequest(request, MultipartHttpServletRequest.class);
+ boolean isMultipart = (multipartRequest != null || isMultipartContent(request));
+
+ if (MultipartFile.class == parameter.getNestedParameterType()) {
+ if (multipartRequest == null && isMultipart) {
+ multipartRequest = adaptToMultipartHttpServletRequest(request);
+ }
+ return (multipartRequest != null ? multipartRequest.getFile(name) : null);
+ }
+ else if (isMultipartFileCollection(parameter)) {
+ if (multipartRequest == null && isMultipart) {
+ multipartRequest = adaptToMultipartHttpServletRequest(request);
+ }
+ return (multipartRequest != null ? multipartRequest.getFiles(name) : null);
+ }
+ else if (isMultipartFileArray(parameter)) {
+ if (multipartRequest == null && isMultipart) {
+ multipartRequest = adaptToMultipartHttpServletRequest(request);
+ }
+ if (multipartRequest != null) {
+ List multipartFiles = multipartRequest.getFiles(name);
+ return multipartFiles.toArray(new MultipartFile[multipartFiles.size()]);
+ }
+ else {
+ return null;
+ }
+ }
+ else if (parameter.getNestedParameterType() == servletPartClass) {
+ return (isMultipart ? RequestPartResolver.resolvePart(request, name) : null);
+ }
+ else if (isPartCollection(parameter)) {
+ return (isMultipart ? RequestPartResolver.resolvePartList(request, name) : null);
+ }
+ else if (isPartArray(parameter)) {
+ return (isMultipart ? RequestPartResolver.resolvePartArray(request, name) : null);
+ }
+ else {
+ return UNRESOLVABLE;
+ }
+ }
+
+ private static boolean isMultipartFileCollection(MethodParameter methodParam) {
+ return (MultipartFile.class == getCollectionParameterType(methodParam));
+ }
+
+ private static boolean isMultipartFileArray(MethodParameter methodParam) {
+ return (MultipartFile.class == methodParam.getNestedParameterType().getComponentType());
+ }
+
+ private static boolean isPartCollection(MethodParameter methodParam) {
+ return (servletPartClass == getCollectionParameterType(methodParam));
+ }
+
+ private static boolean isPartArray(MethodParameter methodParam) {
+ return (servletPartClass == methodParam.getNestedParameterType().getComponentType());
+ }
+
+ private static Class> getCollectionParameterType(MethodParameter methodParam) {
+ Class> paramType = methodParam.getNestedParameterType();
+ if (Collection.class == paramType || List.class.isAssignableFrom(paramType)){
+ Class> valueType = GenericCollectionTypeResolver.getCollectionParameterType(methodParam);
+ if (valueType != null) {
+ return valueType;
+ }
+ }
+ return null;
+ }
+
+
+ /**
+ * Inner class to avoid hard-coded dependency on Servlet 3.0 Part type...
+ */
+ private static class RequestPartResolver {
+
+ public static Object resolvePart(HttpServletRequest servletRequest, String name) throws Exception {
+ return servletRequest.getPart(name);
+ }
+
+ public static Object resolvePartList(HttpServletRequest servletRequest, String name) throws Exception {
+ Collection parts = servletRequest.getParts();
+ List result = new ArrayList(parts.size());
+ for (Part part : parts) {
+ if (part.getName().equals(name)) {
+ result.add(part);
+ }
+ }
+ return result;
+ }
+
+ public static Object resolvePartArray(HttpServletRequest servletRequest, String name) throws Exception {
+ Collection parts = servletRequest.getParts();
+ List result = new ArrayList(parts.size());
+ for (Part part : parts) {
+ if (part.getName().equals(name)) {
+ result.add(part);
+ }
+ }
+ return result.toArray(new Part[result.size()]);
+ }
+ }
+
+}
diff --git a/spring-web/src/main/java/org/springframework/web/multipart/support/RequestPartServletServerHttpRequest.java b/spring-web/src/main/java/org/springframework/web/multipart/support/RequestPartServletServerHttpRequest.java
index b26637e632f..b69e2fa2305 100644
--- a/spring-web/src/main/java/org/springframework/web/multipart/support/RequestPartServletServerHttpRequest.java
+++ b/spring-web/src/main/java/org/springframework/web/multipart/support/RequestPartServletServerHttpRequest.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2015 the original author or authors.
+ * Copyright 2002-2016 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -26,13 +26,10 @@ import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServletServerHttpRequest;
-import org.springframework.util.ClassUtils;
import org.springframework.web.multipart.MultipartException;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;
import org.springframework.web.multipart.MultipartResolver;
-import org.springframework.web.util.WebUtils;
-
/**
* {@link ServerHttpRequest} implementation that accesses one part of a multipart
@@ -54,46 +51,26 @@ public class RequestPartServletServerHttpRequest extends ServletServerHttpReques
/**
- * Create a new instance.
- * @param request the current request
+ * Create a new {@code RequestPartServletServerHttpRequest} instance.
+ * @param request the current servlet request
* @param partName the name of the part to adapt to the {@link ServerHttpRequest} contract
* @throws MissingServletRequestPartException if the request part cannot be found
- * @throws IllegalArgumentException if MultipartHttpServletRequest cannot be initialized
+ * @throws MultipartException if MultipartHttpServletRequest cannot be initialized
*/
public RequestPartServletServerHttpRequest(HttpServletRequest request, String partName)
throws MissingServletRequestPartException {
super(request);
- this.multipartRequest = asMultipartRequest(request);
+ this.multipartRequest = MultipartResolutionDelegate.asMultipartHttpServletRequest(request);
this.partName = partName;
this.headers = this.multipartRequest.getMultipartHeaders(this.partName);
if (this.headers == null) {
- if (request instanceof MultipartHttpServletRequest) {
- throw new MissingServletRequestPartException(partName);
- }
- else {
- throw new IllegalArgumentException(
- "Failed to obtain request part: " + partName + ". " +
- "The part is missing or multipart processing is not configured. " +
- "Check for a MultipartResolver bean or if Servlet 3.0 multipart processing is enabled.");
- }
+ throw new MissingServletRequestPartException(partName);
}
}
- private static MultipartHttpServletRequest asMultipartRequest(HttpServletRequest request) {
- MultipartHttpServletRequest unwrapped = WebUtils.getNativeRequest(request, MultipartHttpServletRequest.class);
- if (unwrapped != null) {
- return unwrapped;
- }
- else if (ClassUtils.hasMethod(HttpServletRequest.class, "getParts")) {
- // Servlet 3.0 available ..
- return new StandardMultipartHttpServletRequest(request);
- }
- throw new IllegalArgumentException("Expected MultipartHttpServletRequest: is a MultipartResolver configured?");
- }
-
@Override
public HttpHeaders getHeaders() {
diff --git a/spring-web/src/test/java/org/springframework/web/method/annotation/RequestParamMethodArgumentResolverTests.java b/spring-web/src/test/java/org/springframework/web/method/annotation/RequestParamMethodArgumentResolverTests.java
index 4617715a8ca..6636c13945a 100644
--- a/spring-web/src/test/java/org/springframework/web/method/annotation/RequestParamMethodArgumentResolverTests.java
+++ b/spring-web/src/test/java/org/springframework/web/method/annotation/RequestParamMethodArgumentResolverTests.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2015 the original author or authors.
+ * Copyright 2002-2016 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -37,6 +37,7 @@ import org.springframework.mock.web.test.MockHttpServletResponse;
import org.springframework.mock.web.test.MockMultipartFile;
import org.springframework.mock.web.test.MockMultipartHttpServletRequest;
import org.springframework.mock.web.test.MockPart;
+import org.springframework.util.ReflectionUtils;
import org.springframework.web.bind.MissingServletRequestParameterException;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.RequestParam;
@@ -49,6 +50,7 @@ import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.context.request.ServletWebRequest;
import org.springframework.web.multipart.MultipartException;
import org.springframework.web.multipart.MultipartFile;
+import org.springframework.web.multipart.support.MissingServletRequestPartException;
import static org.junit.Assert.*;
import static org.mockito.BDDMockito.*;
@@ -82,22 +84,18 @@ public class RequestParamMethodArgumentResolverTests {
private MethodParameter paramRequired;
private MethodParameter paramNotRequired;
private MethodParameter paramOptional;
+ private MethodParameter multipartFileOptional;
private NativeWebRequest webRequest;
private MockHttpServletRequest request;
+
@Before
public void setUp() throws Exception {
resolver = new RequestParamMethodArgumentResolver(null, true);
-
ParameterNameDiscoverer paramNameDiscoverer = new LocalVariableTableParameterNameDiscoverer();
-
- Method method = getClass().getMethod("params", String.class, String[].class,
- Map.class, MultipartFile.class, List.class, MultipartFile[].class,
- Part.class, List.class, Part[].class, Map.class,
- String.class, MultipartFile.class, List.class, Part.class,
- MultipartFile.class, String.class, String.class, Optional.class);
+ Method method = ReflectionUtils.findMethod(getClass(), "handle", (Class>[]) null);
paramNamedDefaultValueString = new SynthesizingMethodParameter(method, 0);
paramNamedStringArray = new SynthesizingMethodParameter(method, 1);
@@ -121,27 +119,35 @@ public class RequestParamMethodArgumentResolverTests {
paramRequired = new SynthesizingMethodParameter(method, 15);
paramNotRequired = new SynthesizingMethodParameter(method, 16);
paramOptional = new SynthesizingMethodParameter(method, 17);
+ multipartFileOptional = new SynthesizingMethodParameter(method, 18);
request = new MockHttpServletRequest();
webRequest = new ServletWebRequest(request, new MockHttpServletResponse());
}
+
@Test
public void supportsParameter() {
resolver = new RequestParamMethodArgumentResolver(null, true);
- assertTrue("String parameter not supported", resolver.supportsParameter(paramNamedDefaultValueString));
- assertTrue("String array parameter not supported", resolver.supportsParameter(paramNamedStringArray));
- assertTrue("Named map not parameter supported", resolver.supportsParameter(paramNamedMap));
- assertTrue("MultipartFile parameter not supported", resolver.supportsParameter(paramMultipartFile));
- assertTrue("List parameter not supported", resolver.supportsParameter(paramMultipartFileList));
- assertTrue("MultipartFile[] parameter not supported", resolver.supportsParameter(paramMultipartFileArray));
- assertTrue("Part parameter not supported", resolver.supportsParameter(paramPart));
- assertTrue("List parameter not supported", resolver.supportsParameter(paramPartList));
- assertTrue("Part[] parameter not supported", resolver.supportsParameter(paramPartArray));
- assertFalse("non-@RequestParam parameter supported", resolver.supportsParameter(paramMap));
- assertTrue("Simple type params supported w/o annotations", resolver.supportsParameter(paramStringNotAnnot));
- assertTrue("MultipartFile parameter not supported", resolver.supportsParameter(paramMultipartFileNotAnnot));
- assertTrue("Part parameter not supported", resolver.supportsParameter(paramPartNotAnnot));
+ assertTrue(resolver.supportsParameter(paramNamedDefaultValueString));
+ assertTrue(resolver.supportsParameter(paramNamedStringArray));
+ assertTrue(resolver.supportsParameter(paramNamedMap));
+ assertTrue(resolver.supportsParameter(paramMultipartFile));
+ assertTrue(resolver.supportsParameter(paramMultipartFileList));
+ assertTrue(resolver.supportsParameter(paramMultipartFileArray));
+ assertTrue(resolver.supportsParameter(paramPart));
+ assertTrue(resolver.supportsParameter(paramPartList));
+ assertTrue(resolver.supportsParameter(paramPartArray));
+ assertFalse(resolver.supportsParameter(paramMap));
+ assertTrue(resolver.supportsParameter(paramStringNotAnnot));
+ assertTrue(resolver.supportsParameter(paramMultipartFileNotAnnot));
+ assertTrue(resolver.supportsParameter(paramMultipartFileListNotAnnot));
+ assertTrue(resolver.supportsParameter(paramPartNotAnnot));
+ assertFalse(resolver.supportsParameter(paramRequestPartAnnot));
+ assertTrue(resolver.supportsParameter(paramRequired));
+ assertTrue(resolver.supportsParameter(paramNotRequired));
+ assertTrue(resolver.supportsParameter(paramOptional));
+ assertTrue(resolver.supportsParameter(multipartFileOptional));
resolver = new RequestParamMethodArgumentResolver(null, false);
assertFalse(resolver.supportsParameter(paramStringNotAnnot));
@@ -154,18 +160,16 @@ public class RequestParamMethodArgumentResolverTests {
request.addParameter("name", expected);
Object result = resolver.resolveArgument(paramNamedDefaultValueString, null, webRequest, null);
-
assertTrue(result instanceof String);
assertEquals("Invalid result", expected, result);
}
@Test
public void resolveStringArray() throws Exception {
- String[] expected = new String[]{"foo", "bar"};
+ String[] expected = new String[] {"foo", "bar"};
request.addParameter("name", expected);
Object result = resolver.resolveArgument(paramNamedStringArray, null, webRequest, null);
-
assertTrue(result instanceof String[]);
assertArrayEquals("Invalid result", expected, (String[]) result);
}
@@ -178,7 +182,6 @@ public class RequestParamMethodArgumentResolverTests {
webRequest = new ServletWebRequest(request);
Object result = resolver.resolveArgument(paramMultipartFile, null, webRequest, null);
-
assertTrue(result instanceof MultipartFile);
assertEquals("Invalid result", expected, result);
}
@@ -190,10 +193,10 @@ public class RequestParamMethodArgumentResolverTests {
MultipartFile expected2 = new MockMultipartFile("mfilelist", "Hello World 2".getBytes());
request.addFile(expected1);
request.addFile(expected2);
+ request.addFile(new MockMultipartFile("other", "Hello World 3".getBytes()));
webRequest = new ServletWebRequest(request);
Object result = resolver.resolveArgument(paramMultipartFileList, null, webRequest, null);
-
assertTrue(result instanceof List);
assertEquals(Arrays.asList(expected1, expected2), result);
}
@@ -205,12 +208,13 @@ public class RequestParamMethodArgumentResolverTests {
MultipartFile expected2 = new MockMultipartFile("mfilearray", "Hello World 2".getBytes());
request.addFile(expected1);
request.addFile(expected2);
+ request.addFile(new MockMultipartFile("other", "Hello World 3".getBytes()));
webRequest = new ServletWebRequest(request);
Object result = resolver.resolveArgument(paramMultipartFileArray, null, webRequest, null);
-
assertTrue(result instanceof MultipartFile[]);
MultipartFile[] parts = (MultipartFile[]) result;
+ assertEquals(2, parts.length);
assertEquals(parts[0], expected1);
assertEquals(parts[1], expected2);
}
@@ -225,7 +229,6 @@ public class RequestParamMethodArgumentResolverTests {
webRequest = new ServletWebRequest(request);
Object result = resolver.resolveArgument(paramPart, null, webRequest, null);
-
assertTrue(result instanceof Part);
assertEquals("Invalid result", expected, result);
}
@@ -233,16 +236,16 @@ public class RequestParamMethodArgumentResolverTests {
@Test
public void resolvePartList() throws Exception {
MockHttpServletRequest request = new MockHttpServletRequest();
- MockPart expected1 = new MockPart("pfilelist", "Hello World 1".getBytes());
- MockPart expected2 = new MockPart("pfilelist", "Hello World 2".getBytes());
request.setMethod("POST");
request.setContentType("multipart/form-data");
+ MockPart expected1 = new MockPart("pfilelist", "Hello World 1".getBytes());
+ MockPart expected2 = new MockPart("pfilelist", "Hello World 2".getBytes());
request.addPart(expected1);
request.addPart(expected2);
+ request.addPart(new MockPart("other", "Hello World 3".getBytes()));
webRequest = new ServletWebRequest(request);
Object result = resolver.resolveArgument(paramPartList, null, webRequest, null);
-
assertTrue(result instanceof List);
assertEquals(Arrays.asList(expected1, expected2), result);
}
@@ -256,12 +259,13 @@ public class RequestParamMethodArgumentResolverTests {
request.setContentType("multipart/form-data");
request.addPart(expected1);
request.addPart(expected2);
+ request.addPart(new MockPart("other", "Hello World 3".getBytes()));
webRequest = new ServletWebRequest(request);
Object result = resolver.resolveArgument(paramPartArray, null, webRequest, null);
-
assertTrue(result instanceof Part[]);
Part[] parts = (Part[]) result;
+ assertEquals(2, parts.length);
assertEquals(parts[0], expected1);
assertEquals(parts[1], expected2);
}
@@ -274,7 +278,6 @@ public class RequestParamMethodArgumentResolverTests {
webRequest = new ServletWebRequest(request);
Object result = resolver.resolveArgument(paramMultipartFileNotAnnot, null, webRequest, null);
-
assertTrue(result instanceof MultipartFile);
assertEquals("Invalid result", expected, result);
}
@@ -289,7 +292,6 @@ public class RequestParamMethodArgumentResolverTests {
webRequest = new ServletWebRequest(request);
Object result = resolver.resolveArgument(paramMultipartFileListNotAnnot, null, webRequest, null);
-
assertTrue(result instanceof List);
assertEquals(Arrays.asList(expected1, expected2), result);
}
@@ -300,9 +302,7 @@ public class RequestParamMethodArgumentResolverTests {
fail("Expected exception: request is not a multipart request");
}
- // SPR-9079
-
- @Test
+ @Test // SPR-9079
public void isMultipartRequestHttpPut() throws Exception {
MockMultipartHttpServletRequest request = new MockMultipartHttpServletRequest();
MultipartFile expected = new MockMultipartFile("multipartFileList", "Hello World".getBytes());
@@ -311,17 +311,23 @@ public class RequestParamMethodArgumentResolverTests {
webRequest = new ServletWebRequest(request);
Object actual = resolver.resolveArgument(paramMultipartFileListNotAnnot, null, webRequest, null);
-
assertTrue(actual instanceof List);
assertEquals(expected, ((List>) actual).get(0));
}
- @Test(expected = IllegalArgumentException.class)
+ @Test(expected = MultipartException.class)
+ public void noMultipartContent() throws Exception {
+ request.setMethod("POST");
+ resolver.resolveArgument(paramMultipartFile, null, webRequest, null);
+ fail("Expected exception: no multipart content");
+ }
+
+ @Test(expected = MissingServletRequestPartException.class)
public void missingMultipartFile() throws Exception {
request.setMethod("POST");
request.setContentType("multipart/form-data");
resolver.resolveArgument(paramMultipartFile, null, webRequest, null);
- fail("Expected exception: request is not MultiPartHttpServletRequest but param is MultipartFile");
+ fail("Expected exception: no such part found");
}
@Test
@@ -334,7 +340,6 @@ public class RequestParamMethodArgumentResolverTests {
webRequest = new ServletWebRequest(request);
Object result = resolver.resolveArgument(paramPartNotAnnot, null, webRequest, null);
-
assertTrue(result instanceof Part);
assertEquals("Invalid result", expected, result);
}
@@ -342,7 +347,6 @@ public class RequestParamMethodArgumentResolverTests {
@Test
public void resolveDefaultValue() throws Exception {
Object result = resolver.resolveArgument(paramNamedDefaultValueString, null, webRequest, null);
-
assertTrue(result instanceof String);
assertEquals("Invalid result", "bar", result);
}
@@ -353,11 +357,8 @@ public class RequestParamMethodArgumentResolverTests {
fail("Expected exception");
}
- // SPR-10578
-
- @Test
+ @Test // SPR-10578
public void missingRequestParamEmptyValueConvertedToNull() throws Exception {
-
WebDataBinder binder = new WebRequestDataBinder(null);
binder.registerCustomEditor(String.class, new StringTrimmerEditor(true));
@@ -367,13 +368,11 @@ public class RequestParamMethodArgumentResolverTests {
this.request.addParameter("stringNotAnnot", "");
Object arg = resolver.resolveArgument(paramStringNotAnnot, null, webRequest, binderFactory);
-
assertNull(arg);
}
@Test
public void missingRequestParamEmptyValueNotRequired() throws Exception {
-
WebDataBinder binder = new WebRequestDataBinder(null);
binder.registerCustomEditor(String.class, new StringTrimmerEditor(true));
@@ -383,7 +382,6 @@ public class RequestParamMethodArgumentResolverTests {
this.request.addParameter("name", "");
Object arg = resolver.resolveArgument(paramNotRequired, null, webRequest, binderFactory);
-
assertNull(arg);
}
@@ -396,17 +394,13 @@ public class RequestParamMethodArgumentResolverTests {
assertEquals("plainValue", result);
}
- // SPR-8561
-
- @Test
+ @Test // SPR-8561
public void resolveSimpleTypeParamToNull() throws Exception {
Object result = resolver.resolveArgument(paramStringNotAnnot, null, webRequest, null);
assertNull(result);
}
- // SPR-10180
-
- @Test
+ @Test // SPR-10180
public void resolveEmptyValueToDefault() throws Exception {
this.request.addParameter("name", "");
Object result = resolver.resolveArgument(paramNamedDefaultValueString, null, webRequest, null);
@@ -429,13 +423,12 @@ public class RequestParamMethodArgumentResolverTests {
@Test
@SuppressWarnings("rawtypes")
- public void resolveOptional() throws Exception {
+ public void resolveOptionalParamValue() throws Exception {
ConfigurableWebBindingInitializer initializer = new ConfigurableWebBindingInitializer();
initializer.setConversionService(new DefaultConversionService());
WebDataBinderFactory binderFactory = new DefaultDataBinderFactory(initializer);
Object result = resolver.resolveArgument(paramOptional, null, webRequest, binderFactory);
- assertEquals(Optional.class, result.getClass());
assertEquals(Optional.empty(), result);
this.request.addParameter("name", "123");
@@ -444,8 +437,46 @@ public class RequestParamMethodArgumentResolverTests {
assertEquals(123, ((Optional) result).get());
}
+ @Test
+ public void resolveOptionalMultipartFile() throws Exception {
+ ConfigurableWebBindingInitializer initializer = new ConfigurableWebBindingInitializer();
+ initializer.setConversionService(new DefaultConversionService());
+ WebDataBinderFactory binderFactory = new DefaultDataBinderFactory(initializer);
- public void params(@RequestParam(name = "name", defaultValue = "bar") String param1,
+ MockMultipartHttpServletRequest request = new MockMultipartHttpServletRequest();
+ MultipartFile expected = new MockMultipartFile("mfile", "Hello World".getBytes());
+ request.addFile(expected);
+ webRequest = new ServletWebRequest(request);
+
+ Object result = resolver.resolveArgument(multipartFileOptional, null, webRequest, binderFactory);
+ assertTrue(result instanceof Optional);
+ assertEquals("Invalid result", expected, ((Optional>) result).get());
+ }
+
+ @Test
+ public void missingOptionalMultipartFile() throws Exception {
+ ConfigurableWebBindingInitializer initializer = new ConfigurableWebBindingInitializer();
+ initializer.setConversionService(new DefaultConversionService());
+ WebDataBinderFactory binderFactory = new DefaultDataBinderFactory(initializer);
+
+ request.setMethod("POST");
+ request.setContentType("multipart/form-data");
+ assertEquals(Optional.empty(), resolver.resolveArgument(multipartFileOptional, null, webRequest, binderFactory));
+ }
+
+ @Test
+ public void optionalMultipartFileWithoutMultipartRequest() throws Exception {
+ ConfigurableWebBindingInitializer initializer = new ConfigurableWebBindingInitializer();
+ initializer.setConversionService(new DefaultConversionService());
+ WebDataBinderFactory binderFactory = new DefaultDataBinderFactory(initializer);
+
+ assertEquals(Optional.empty(), resolver.resolveArgument(multipartFileOptional, null, webRequest, binderFactory));
+ }
+
+
+ @SuppressWarnings("unused")
+ public void handle(
+ @RequestParam(name = "name", defaultValue = "bar") String param1,
@RequestParam("name") String[] param2,
@RequestParam("name") Map, ?> param3,
@RequestParam("mfile") MultipartFile param4,
@@ -462,7 +493,8 @@ public class RequestParamMethodArgumentResolverTests {
@RequestPart MultipartFile requestPartAnnot,
@RequestParam("name") String paramRequired,
@RequestParam(name = "name", required = false) String paramNotRequired,
- @RequestParam("name") Optional paramOptional) {
+ @RequestParam("name") Optional paramOptional,
+ @RequestParam("mfile") Optional multipartFileOptional) {
}
}
diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/MatrixVariableMethodArgumentResolver.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/MatrixVariableMethodArgumentResolver.java
index 31f44a6e64a..1dd9c354a15 100644
--- a/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/MatrixVariableMethodArgumentResolver.java
+++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/MatrixVariableMethodArgumentResolver.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2015 the original author or authors.
+ * Copyright 2002-2016 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -48,12 +48,13 @@ public class MatrixVariableMethodArgumentResolver extends AbstractNamedValueMeth
super(null);
}
+
@Override
public boolean supportsParameter(MethodParameter parameter) {
if (!parameter.hasParameterAnnotation(MatrixVariable.class)) {
return false;
}
- if (Map.class.isAssignableFrom(parameter.getParameterType())) {
+ if (Map.class.isAssignableFrom(parameter.nestedIfOptional().getNestedParameterType())) {
String variableName = parameter.getParameterAnnotation(MatrixVariable.class).name();
return StringUtils.hasText(variableName);
}
@@ -67,13 +68,10 @@ public class MatrixVariableMethodArgumentResolver extends AbstractNamedValueMeth
}
@Override
+ @SuppressWarnings("unchecked")
protected Object resolveName(String name, MethodParameter parameter, NativeWebRequest request) throws Exception {
-
- @SuppressWarnings("unchecked")
- Map> pathParameters =
- (Map>) request.getAttribute(
- HandlerMapping.MATRIX_VARIABLES_ATTRIBUTE, RequestAttributes.SCOPE_REQUEST);
-
+ Map> pathParameters = (Map>)
+ request.getAttribute(HandlerMapping.MATRIX_VARIABLES_ATTRIBUTE, RequestAttributes.SCOPE_REQUEST);
if (CollectionUtils.isEmpty(pathParameters)) {
return null;
}
@@ -92,10 +90,10 @@ public class MatrixVariableMethodArgumentResolver extends AbstractNamedValueMeth
for (MultiValueMap params : pathParameters.values()) {
if (params.containsKey(name)) {
if (found) {
- String paramType = parameter.getParameterType().getName();
+ String paramType = parameter.getNestedParameterType().getName();
throw new ServletRequestBindingException(
"Found more than one match for URI path parameter '" + name +
- "' for parameter type [" + paramType + "]. Use pathVar attribute to disambiguate.");
+ "' for parameter type [" + paramType + "]. Use 'pathVar' attribute to disambiguate.");
}
paramValues.addAll(params.get(name));
found = true;
@@ -117,7 +115,7 @@ public class MatrixVariableMethodArgumentResolver extends AbstractNamedValueMeth
@Override
protected void handleMissingValue(String name, MethodParameter parameter) throws ServletRequestBindingException {
throw new ServletRequestBindingException("Missing matrix variable '" + name +
- "' for method parameter of type " + parameter.getParameterType().getSimpleName());
+ "' for method parameter of type " + parameter.getNestedParameterType().getSimpleName());
}
@@ -127,4 +125,5 @@ public class MatrixVariableMethodArgumentResolver extends AbstractNamedValueMeth
super(annotation.name(), annotation.required(), annotation.defaultValue());
}
}
-}
\ No newline at end of file
+
+}
diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/PathVariableMethodArgumentResolver.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/PathVariableMethodArgumentResolver.java
index ec3c7e24318..e2e30c447c4 100644
--- a/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/PathVariableMethodArgumentResolver.java
+++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/PathVariableMethodArgumentResolver.java
@@ -79,7 +79,7 @@ public class PathVariableMethodArgumentResolver extends AbstractNamedValueMethod
if (!parameter.hasParameterAnnotation(PathVariable.class)) {
return false;
}
- if (Map.class.isAssignableFrom(parameter.getParameterType())) {
+ if (Map.class.isAssignableFrom(parameter.nestedIfOptional().getNestedParameterType())) {
String paramName = parameter.getParameterAnnotation(PathVariable.class).value();
return StringUtils.hasText(paramName);
}
@@ -95,10 +95,9 @@ public class PathVariableMethodArgumentResolver extends AbstractNamedValueMethod
@Override
@SuppressWarnings("unchecked")
protected Object resolveName(String name, MethodParameter parameter, NativeWebRequest request) throws Exception {
- Map uriTemplateVars =
- (Map) request.getAttribute(
- HandlerMapping.URI_TEMPLATE_VARIABLES_ATTRIBUTE, RequestAttributes.SCOPE_REQUEST);
- return (uriTemplateVars != null) ? uriTemplateVars.get(name) : null;
+ Map uriTemplateVars = (Map) request.getAttribute(
+ HandlerMapping.URI_TEMPLATE_VARIABLES_ATTRIBUTE, RequestAttributes.SCOPE_REQUEST);
+ return (uriTemplateVars != null ? uriTemplateVars.get(name) : null);
}
@Override
@@ -127,7 +126,7 @@ public class PathVariableMethodArgumentResolver extends AbstractNamedValueMethod
public void contributeMethodArgument(MethodParameter parameter, Object value,
UriComponentsBuilder builder, Map uriVariables, ConversionService conversionService) {
- if (Map.class.isAssignableFrom(parameter.getParameterType())) {
+ if (Map.class.isAssignableFrom(parameter.getNestedParameterType())) {
return;
}
diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/RequestPartMethodArgumentResolver.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/RequestPartMethodArgumentResolver.java
index 59d59d8f998..1c8af84a656 100644
--- a/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/RequestPartMethodArgumentResolver.java
+++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/RequestPartMethodArgumentResolver.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2015 the original author or authors.
+ * Copyright 2002-2016 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -16,20 +16,15 @@
package org.springframework.web.servlet.mvc.method.annotation;
-import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Optional;
-
import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.Part;
-import org.springframework.core.GenericCollectionTypeResolver;
import org.springframework.core.MethodParameter;
import org.springframework.http.HttpInputMessage;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.lang.UsesJava8;
-import org.springframework.util.Assert;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.WebDataBinder;
@@ -41,12 +36,10 @@ import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.method.support.ModelAndViewContainer;
import org.springframework.web.multipart.MultipartException;
import org.springframework.web.multipart.MultipartFile;
-import org.springframework.web.multipart.MultipartHttpServletRequest;
import org.springframework.web.multipart.MultipartResolver;
import org.springframework.web.multipart.support.MissingServletRequestPartException;
+import org.springframework.web.multipart.support.MultipartResolutionDelegate;
import org.springframework.web.multipart.support.RequestPartServletServerHttpRequest;
-import org.springframework.web.servlet.mvc.support.DefaultHandlerExceptionResolver;
-import org.springframework.web.util.WebUtils;
/**
* Resolves the following method arguments:
@@ -65,12 +58,13 @@ import org.springframework.web.util.WebUtils;
* it is derived from the name of the method argument.
*
* Automatic validation may be applied if the argument is annotated with
- * {@code @javax.validation.Valid}. In case of validation failure, a
- * {@link MethodArgumentNotValidException} is raised and a 400 response status
- * code returned if {@link DefaultHandlerExceptionResolver} is configured.
+ * {@code @javax.validation.Valid}. In case of validation failure, a {@link MethodArgumentNotValidException}
+ * is raised and a 400 response status code returned if
+ * {@link org.springframework.web.servlet.mvc.support.DefaultHandlerExceptionResolver} is configured.
*
* @author Rossen Stoyanchev
* @author Brian Clozel
+ * @author Juergen Hoeller
* @since 3.1
*/
public class RequestPartMethodArgumentResolver extends AbstractMessageConverterMethodArgumentResolver {
@@ -107,18 +101,10 @@ public class RequestPartMethodArgumentResolver extends AbstractMessageConverterM
return true;
}
else {
- if (parameter.hasParameterAnnotation(RequestParam.class)){
- return false;
- }
- else if (MultipartFile.class == parameter.getParameterType()) {
- return true;
- }
- else if ("javax.servlet.http.Part".equals(parameter.getParameterType().getName())) {
- return true;
- }
- else {
+ if (parameter.hasParameterAnnotation(RequestParam.class)) {
return false;
}
+ return MultipartResolutionDelegate.isMultipartArgument(parameter.nestedIfOptional());
}
}
@@ -128,87 +114,58 @@ public class RequestPartMethodArgumentResolver extends AbstractMessageConverterM
NativeWebRequest request, WebDataBinderFactory binderFactory) throws Exception {
HttpServletRequest servletRequest = request.getNativeRequest(HttpServletRequest.class);
- assertIsMultipartRequest(servletRequest);
+ RequestPart requestPart = parameter.getParameterAnnotation(RequestPart.class);
+ boolean isRequired = ((requestPart == null || requestPart.required()) && !parameter.isOptional());
- MultipartHttpServletRequest multipartRequest =
- WebUtils.getNativeRequest(servletRequest, MultipartHttpServletRequest.class);
+ String name = getPartName(parameter, requestPart);
+ parameter = parameter.nestedIfOptional();
+ Object arg = null;
- Class> paramType = parameter.getParameterType();
- boolean optional = paramType.getName().equals("java.util.Optional");
- if (optional) {
- parameter.increaseNestingLevel();
- paramType = parameter.getNestedParameterType();
- }
-
- String partName = getPartName(parameter);
- Object arg;
-
- if (MultipartFile.class == paramType) {
- Assert.notNull(multipartRequest, "Expected MultipartHttpServletRequest: is a MultipartResolver configured?");
- arg = multipartRequest.getFile(partName);
- }
- else if (isMultipartFileCollection(parameter)) {
- Assert.notNull(multipartRequest, "Expected MultipartHttpServletRequest: is a MultipartResolver configured?");
- arg = multipartRequest.getFiles(partName);
- }
- else if (isMultipartFileArray(parameter)) {
- Assert.notNull(multipartRequest, "Expected MultipartHttpServletRequest: is a MultipartResolver configured?");
- List files = multipartRequest.getFiles(partName);
- arg = files.toArray(new MultipartFile[files.size()]);
- }
- else if ("javax.servlet.http.Part".equals(paramType.getName())) {
- assertIsMultipartRequest(servletRequest);
- arg = servletRequest.getPart(partName);
- }
- else if (isPartCollection(parameter)) {
- assertIsMultipartRequest(servletRequest);
- arg = new ArrayList(servletRequest.getParts());
- }
- else if (isPartArray(parameter)) {
- assertIsMultipartRequest(servletRequest);
- arg = RequestPartResolver.resolvePart(servletRequest);
+ Object mpArg = MultipartResolutionDelegate.resolveMultipartArgument(name, parameter, servletRequest);
+ if (mpArg != MultipartResolutionDelegate.UNRESOLVABLE) {
+ arg = mpArg;
}
else {
try {
- HttpInputMessage inputMessage = new RequestPartServletServerHttpRequest(servletRequest, partName);
+ HttpInputMessage inputMessage = new RequestPartServletServerHttpRequest(servletRequest, name);
arg = readWithMessageConverters(inputMessage, parameter, parameter.getNestedGenericParameterType());
- WebDataBinder binder = binderFactory.createBinder(request, arg, partName);
+ WebDataBinder binder = binderFactory.createBinder(request, arg, name);
if (arg != null) {
validateIfApplicable(binder, parameter);
if (binder.getBindingResult().hasErrors() && isBindExceptionRequired(binder, parameter)) {
throw new MethodArgumentNotValidException(parameter, binder.getBindingResult());
}
}
- mavContainer.addAttribute(BindingResult.MODEL_KEY_PREFIX + partName, binder.getBindingResult());
+ mavContainer.addAttribute(BindingResult.MODEL_KEY_PREFIX + name, binder.getBindingResult());
}
catch (MissingServletRequestPartException ex) {
- // handled below
- arg = null;
+ if (isRequired) {
+ throw ex;
+ }
+ }
+ catch (MultipartException ex) {
+ if (isRequired) {
+ throw ex;
+ }
}
}
- RequestPart requestPart = parameter.getParameterAnnotation(RequestPart.class);
- boolean isRequired = ((requestPart == null || requestPart.required()) && !optional);
-
if (arg == null && isRequired) {
- throw new MissingServletRequestPartException(partName);
+ if (!MultipartResolutionDelegate.isMultipartRequest(servletRequest)) {
+ throw new MultipartException("Current request is not a multipart request");
+ }
+ else {
+ throw new MissingServletRequestPartException(name);
+ }
}
- if (optional) {
- arg = Optional.ofNullable(arg);
+ if (parameter.isOptional()) {
+ arg = OptionalResolver.resolveValue(arg);
}
return arg;
}
- private static void assertIsMultipartRequest(HttpServletRequest request) {
- String contentType = request.getContentType();
- if (contentType == null || !contentType.toLowerCase().startsWith("multipart/")) {
- throw new MultipartException("The current request is not a multipart request");
- }
- }
-
- private String getPartName(MethodParameter methodParam) {
- RequestPart requestPart = methodParam.getParameterAnnotation(RequestPart.class);
+ private String getPartName(MethodParameter methodParam, RequestPart requestPart) {
String partName = (requestPart != null ? requestPart.name() : "");
if (partName.length() == 0) {
partName = methodParam.getParameterName();
@@ -221,46 +178,18 @@ public class RequestPartMethodArgumentResolver extends AbstractMessageConverterM
return partName;
}
- private boolean isMultipartFileCollection(MethodParameter methodParam) {
- Class> collectionType = getCollectionParameterType(methodParam);
- return MultipartFile.class == collectionType;
- }
-
- private boolean isMultipartFileArray(MethodParameter methodParam) {
- Class> paramType = methodParam.getNestedParameterType().getComponentType();
- return MultipartFile.class == paramType;
- }
-
- private boolean isPartCollection(MethodParameter methodParam) {
- Class> collectionType = getCollectionParameterType(methodParam);
- return (collectionType != null && "javax.servlet.http.Part".equals(collectionType.getName()));
- }
-
- private boolean isPartArray(MethodParameter methodParam) {
- Class> paramType = methodParam.getNestedParameterType().getComponentType();
- return (paramType != null && "javax.servlet.http.Part".equals(paramType.getName()));
- }
-
- private Class> getCollectionParameterType(MethodParameter methodParam) {
- Class> paramType = methodParam.getNestedParameterType();
- if (Collection.class == paramType || List.class.isAssignableFrom(paramType)){
- Class> valueType = GenericCollectionTypeResolver.getCollectionParameterType(methodParam);
- if (valueType != null) {
- return valueType;
- }
- }
- return null;
- }
-
/**
- * Inner class to avoid hard-coded dependency on Servlet 3.0 Part type...
+ * Inner class to avoid hard-coded dependency on Java 8 Optional type...
*/
- private static class RequestPartResolver {
+ private static class OptionalResolver {
- public static Object resolvePart(HttpServletRequest servletRequest) throws Exception {
- Collection parts = servletRequest.getParts();
- return parts.toArray(new Part[parts.size()]);
+ public static Object resolveValue(Object value) {
+ if (value == null || (value instanceof Collection && ((Collection) value).isEmpty()) ||
+ (value instanceof Object[] && ((Object[]) value).length == 0)) {
+ return Optional.empty();
+ }
+ return Optional.of(value);
}
}
diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/ServletCookieValueMethodArgumentResolver.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/ServletCookieValueMethodArgumentResolver.java
index 8c51d5d8d2a..cf174ea1346 100644
--- a/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/ServletCookieValueMethodArgumentResolver.java
+++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/ServletCookieValueMethodArgumentResolver.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2014 the original author or authors.
+ * Copyright 2002-2016 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -52,7 +52,7 @@ public class ServletCookieValueMethodArgumentResolver extends AbstractCookieValu
protected Object resolveName(String cookieName, MethodParameter parameter, NativeWebRequest webRequest) throws Exception {
HttpServletRequest servletRequest = webRequest.getNativeRequest(HttpServletRequest.class);
Cookie cookieValue = WebUtils.getCookie(servletRequest, cookieName);
- if (Cookie.class.isAssignableFrom(parameter.getParameterType())) {
+ if (Cookie.class.isAssignableFrom(parameter.getNestedParameterType())) {
return cookieValue;
}
else if (cookieValue != null) {
diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/ServletInvocableHandlerMethod.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/ServletInvocableHandlerMethod.java
index 8044d66412a..3eb84cbe6a9 100644
--- a/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/ServletInvocableHandlerMethod.java
+++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/ServletInvocableHandlerMethod.java
@@ -262,6 +262,12 @@ public class ServletInvocableHandlerMethod extends InvocableHandlerMethod {
this.returnType = ResolvableType.forType(super.getGenericParameterType()).getGeneric(0);
}
+ public ConcurrentResultMethodParameter(ConcurrentResultMethodParameter original) {
+ super(original);
+ this.returnValue = original.returnValue;
+ this.returnType = original.returnType;
+ }
+
@Override
public Class> getParameterType() {
if (this.returnValue != null) {
@@ -283,6 +289,11 @@ public class ServletInvocableHandlerMethod extends InvocableHandlerMethod {
public Type getGenericParameterType() {
return this.returnType.getType();
}
+
+ @Override
+ public ConcurrentResultMethodParameter clone() {
+ return new ConcurrentResultMethodParameter(this);
+ }
}
}
diff --git a/spring-webmvc/src/test/java/org/springframework/web/servlet/mvc/method/annotation/RequestPartMethodArgumentResolverTests.java b/spring-webmvc/src/test/java/org/springframework/web/servlet/mvc/method/annotation/RequestPartMethodArgumentResolverTests.java
index 5b443ff7fdb..716acda541a 100644
--- a/spring-webmvc/src/test/java/org/springframework/web/servlet/mvc/method/annotation/RequestPartMethodArgumentResolverTests.java
+++ b/spring-webmvc/src/test/java/org/springframework/web/servlet/mvc/method/annotation/RequestPartMethodArgumentResolverTests.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2015 the original author or authors.
+ * Copyright 2002-2016 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -41,6 +41,7 @@ import org.springframework.mock.web.test.MockHttpServletResponse;
import org.springframework.mock.web.test.MockMultipartFile;
import org.springframework.mock.web.test.MockMultipartHttpServletRequest;
import org.springframework.mock.web.test.MockPart;
+import org.springframework.util.ReflectionUtils;
import org.springframework.validation.beanvalidation.LocalValidatorFactoryBean;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.WebDataBinder;
@@ -53,7 +54,6 @@ import org.springframework.web.method.support.ModelAndViewContainer;
import org.springframework.web.multipart.MultipartException;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.support.MissingServletRequestPartException;
-import org.springframework.web.multipart.support.RequestPartServletServerHttpRequest;
import static org.junit.Assert.*;
import static org.mockito.BDDMockito.*;
@@ -86,7 +86,9 @@ public class RequestPartMethodArgumentResolverTests {
private MethodParameter paramPartArray;
private MethodParameter paramRequestParamAnnot;
private MethodParameter optionalMultipartFile;
+ private MethodParameter optionalMultipartFileList;
private MethodParameter optionalPart;
+ private MethodParameter optionalPartList;
private MethodParameter optionalRequestPart;
private NativeWebRequest webRequest;
@@ -97,10 +99,7 @@ public class RequestPartMethodArgumentResolverTests {
@SuppressWarnings("unchecked")
@Before
public void setUp() throws Exception {
- Method method = getClass().getMethod("handle", SimpleBean.class, SimpleBean.class,
- SimpleBean.class, MultipartFile.class, List.class, MultipartFile[].class,
- Integer.TYPE, MultipartFile.class, Part.class, List.class, Part[].class,
- MultipartFile.class, Optional.class, Optional.class, Optional.class);
+ Method method = ReflectionUtils.findMethod(getClass(), "handle", (Class>[]) null);
paramRequestPart = new SynthesizingMethodParameter(method, 0);
paramRequestPart.initParameterNameDiscovery(new LocalVariableTableParameterNameDiscoverer());
@@ -119,9 +118,13 @@ public class RequestPartMethodArgumentResolverTests {
paramRequestParamAnnot = new SynthesizingMethodParameter(method, 11);
optionalMultipartFile = new SynthesizingMethodParameter(method, 12);
optionalMultipartFile.initParameterNameDiscovery(new LocalVariableTableParameterNameDiscoverer());
- optionalPart = new SynthesizingMethodParameter(method, 13);
+ optionalMultipartFileList = new SynthesizingMethodParameter(method, 13);
+ optionalMultipartFileList.initParameterNameDiscovery(new LocalVariableTableParameterNameDiscoverer());
+ optionalPart = new SynthesizingMethodParameter(method, 14);
optionalPart.initParameterNameDiscovery(new LocalVariableTableParameterNameDiscoverer());
- optionalRequestPart = new SynthesizingMethodParameter(method, 14);
+ optionalPartList = new SynthesizingMethodParameter(method, 15);
+ optionalPartList.initParameterNameDiscovery(new LocalVariableTableParameterNameDiscoverer());
+ optionalRequestPart = new SynthesizingMethodParameter(method, 16);
messageConverter = mock(HttpMessageConverter.class);
given(messageConverter.getSupportedMediaTypes()).willReturn(Collections.singletonList(MediaType.TEXT_PLAIN));
@@ -136,35 +139,41 @@ public class RequestPartMethodArgumentResolverTests {
multipartRequest = new MockMultipartHttpServletRequest();
multipartRequest.addFile(multipartFile1);
multipartRequest.addFile(multipartFile2);
+ multipartRequest.addFile(new MockMultipartFile("otherPart", "", "text/plain", content));
webRequest = new ServletWebRequest(multipartRequest, new MockHttpServletResponse());
}
@Test
public void supportsParameter() {
- assertTrue("RequestPart parameter not supported", resolver.supportsParameter(paramRequestPart));
- assertTrue("MultipartFile parameter not supported", resolver.supportsParameter(paramMultipartFileNotAnnot));
- assertTrue("Part parameter not supported", resolver.supportsParameter(paramPart));
- assertTrue("List parameter not supported", resolver.supportsParameter(paramPartList));
- assertTrue("Part[] parameter not supported", resolver.supportsParameter(paramPartArray));
- assertTrue("MultipartFile parameter not supported", resolver.supportsParameter(paramMultipartFile));
- assertTrue("List parameter not supported", resolver.supportsParameter(paramMultipartFileList));
- assertTrue("MultipartFile[] parameter not supported", resolver.supportsParameter(paramMultipartFileArray));
- assertFalse("non-RequestPart parameter should not be supported", resolver.supportsParameter(paramInt));
- assertFalse("@RequestParam args should not be supported", resolver.supportsParameter(paramRequestParamAnnot));
+ assertTrue(resolver.supportsParameter(paramRequestPart));
+ assertTrue(resolver.supportsParameter(paramNamedRequestPart));
+ assertTrue(resolver.supportsParameter(paramValidRequestPart));
+ assertTrue(resolver.supportsParameter(paramMultipartFile));
+ assertTrue(resolver.supportsParameter(paramMultipartFileList));
+ assertTrue(resolver.supportsParameter(paramMultipartFileArray));
+ assertFalse(resolver.supportsParameter(paramInt));
+ assertTrue(resolver.supportsParameter(paramMultipartFileNotAnnot));
+ assertTrue(resolver.supportsParameter(paramPart));
+ assertTrue(resolver.supportsParameter(paramPartList));
+ assertTrue(resolver.supportsParameter(paramPartArray));
+ assertFalse(resolver.supportsParameter(paramRequestParamAnnot));
+ assertTrue(resolver.supportsParameter(optionalMultipartFile));
+ assertTrue(resolver.supportsParameter(optionalMultipartFileList));
+ assertTrue(resolver.supportsParameter(optionalPart));
+ assertTrue(resolver.supportsParameter(optionalPartList));
+ assertTrue(resolver.supportsParameter(optionalRequestPart));
}
@Test
public void resolveMultipartFile() throws Exception {
Object actual = resolver.resolveArgument(paramMultipartFile, null, webRequest, null);
- assertNotNull(actual);
assertSame(multipartFile1, actual);
}
@Test
public void resolveMultipartFileList() throws Exception {
Object actual = resolver.resolveArgument(paramMultipartFileList, null, webRequest, null);
- assertNotNull(actual);
assertTrue(actual instanceof List);
assertEquals(Arrays.asList(multipartFile1, multipartFile2), actual);
}
@@ -175,6 +184,7 @@ public class RequestPartMethodArgumentResolverTests {
assertNotNull(actual);
assertTrue(actual instanceof MultipartFile[]);
MultipartFile[] parts = (MultipartFile[]) actual;
+ assertEquals(2, parts.length);
assertEquals(parts[0], multipartFile1);
assertEquals(parts[1], multipartFile2);
}
@@ -184,6 +194,7 @@ public class RequestPartMethodArgumentResolverTests {
MockMultipartHttpServletRequest request = new MockMultipartHttpServletRequest();
MultipartFile expected = new MockMultipartFile("multipartFileNotAnnot", "Hello World".getBytes());
request.addFile(expected);
+ request.addFile(new MockMultipartFile("otherPart", "", "text/plain", "Hello World".getBytes()));
webRequest = new ServletWebRequest(request);
Object result = resolver.resolveArgument(paramMultipartFileNotAnnot, null, webRequest, null);
@@ -194,52 +205,52 @@ public class RequestPartMethodArgumentResolverTests {
@Test
public void resolvePartArgument() throws Exception {
- MockPart expected = new MockPart("part", "Hello World".getBytes());
MockHttpServletRequest request = new MockHttpServletRequest();
request.setMethod("POST");
request.setContentType("multipart/form-data");
+ MockPart expected = new MockPart("part", "Hello World".getBytes());
request.addPart(expected);
+ request.addPart(new MockPart("otherPart", "Hello World".getBytes()));
webRequest = new ServletWebRequest(request);
Object result = resolver.resolveArgument(paramPart, null, webRequest, null);
-
assertTrue(result instanceof Part);
assertEquals("Invalid result", expected, result);
}
@Test
public void resolvePartListArgument() throws Exception {
- MockPart part1 = new MockPart("requestPart1", "Hello World 1".getBytes());
- MockPart part2 = new MockPart("requestPart2", "Hello World 2".getBytes());
MockHttpServletRequest request = new MockHttpServletRequest();
request.setMethod("POST");
request.setContentType("multipart/form-data");
+ MockPart part1 = new MockPart("requestPart", "Hello World 1".getBytes());
+ MockPart part2 = new MockPart("requestPart", "Hello World 2".getBytes());
request.addPart(part1);
request.addPart(part2);
+ request.addPart(new MockPart("otherPart", "Hello World".getBytes()));
webRequest = new ServletWebRequest(request);
Object result = resolver.resolveArgument(paramPartList, null, webRequest, null);
-
assertTrue(result instanceof List);
assertEquals(Arrays.asList(part1, part2), result);
}
@Test
public void resolvePartArrayArgument() throws Exception {
- MockPart part1 = new MockPart("requestPart1", "Hello World 1".getBytes());
- MockPart part2 = new MockPart("requestPart2", "Hello World 2".getBytes());
MockHttpServletRequest request = new MockHttpServletRequest();
request.setMethod("POST");
request.setContentType("multipart/form-data");
+ MockPart part1 = new MockPart("requestPart", "Hello World 1".getBytes());
+ MockPart part2 = new MockPart("requestPart", "Hello World 2".getBytes());
request.addPart(part1);
request.addPart(part2);
+ request.addPart(new MockPart("otherPart", "Hello World".getBytes()));
webRequest = new ServletWebRequest(request);
Object result = resolver.resolveArgument(paramPartArray, null, webRequest, null);
-
assertTrue(result instanceof Part[]);
Part[] parts = (Part[]) result;
- assertThat(parts, Matchers.arrayWithSize(2));
+ assertEquals(2, parts.length);
assertEquals(parts[0], part1);
assertEquals(parts[1], part2);
}
@@ -302,8 +313,8 @@ public class RequestPartMethodArgumentResolverTests {
@Test // SPR-9079
public void isMultipartRequestPut() throws Exception {
this.multipartRequest.setMethod("PUT");
- Object actual = resolver.resolveArgument(paramMultipartFile, null, webRequest, null);
- assertSame(multipartFile1, actual);
+ Object actualValue = resolver.resolveArgument(paramMultipartFile, null, webRequest, null);
+ assertSame(multipartFile1, actualValue);
}
@Test
@@ -311,12 +322,16 @@ public class RequestPartMethodArgumentResolverTests {
MockMultipartHttpServletRequest request = new MockMultipartHttpServletRequest();
MultipartFile expected = new MockMultipartFile("optionalMultipartFile", "Hello World".getBytes());
request.addFile(expected);
+ request.addFile(new MockMultipartFile("otherPart", "", "text/plain", "Hello World".getBytes()));
webRequest = new ServletWebRequest(request);
- Object result = resolver.resolveArgument(optionalMultipartFile, null, webRequest, null);
+ Object actualValue = resolver.resolveArgument(optionalMultipartFile, null, webRequest, null);
+ assertTrue(actualValue instanceof Optional);
+ assertEquals("Invalid result", expected, ((Optional) actualValue).get());
- assertTrue(result instanceof Optional);
- assertEquals("Invalid result", expected, ((Optional) result).get());
+ actualValue = resolver.resolveArgument(optionalMultipartFile, null, webRequest, null);
+ assertTrue(actualValue instanceof Optional);
+ assertEquals("Invalid result", expected, ((Optional) actualValue).get());
}
@Test
@@ -324,10 +339,62 @@ public class RequestPartMethodArgumentResolverTests {
MockMultipartHttpServletRequest request = new MockMultipartHttpServletRequest();
webRequest = new ServletWebRequest(request);
- Object result = resolver.resolveArgument(optionalMultipartFile, null, webRequest, null);
+ Object actualValue = resolver.resolveArgument(optionalMultipartFile, null, webRequest, null);
+ assertEquals("Invalid argument value", Optional.empty(), actualValue);
- assertTrue(result instanceof Optional);
- assertFalse("Invalid result", ((Optional) result).isPresent());
+ actualValue = resolver.resolveArgument(optionalMultipartFile, null, webRequest, null);
+ assertEquals("Invalid argument value", Optional.empty(), actualValue);
+ }
+
+ @Test
+ public void resolveOptionalMultipartFileArgumentWithoutMultipartRequest() throws Exception {
+ webRequest = new ServletWebRequest(new MockHttpServletRequest());
+
+ Object actualValue = resolver.resolveArgument(optionalMultipartFile, null, webRequest, null);
+ assertEquals("Invalid argument value", Optional.empty(), actualValue);
+
+ actualValue = resolver.resolveArgument(optionalMultipartFile, null, webRequest, null);
+ assertEquals("Invalid argument value", Optional.empty(), actualValue);
+ }
+
+ @Test
+ public void resolveOptionalMultipartFileList() throws Exception {
+ MockMultipartHttpServletRequest request = new MockMultipartHttpServletRequest();
+ MultipartFile expected = new MockMultipartFile("requestPart", "Hello World".getBytes());
+ request.addFile(expected);
+ request.addFile(new MockMultipartFile("otherPart", "", "text/plain", "Hello World".getBytes()));
+ webRequest = new ServletWebRequest(request);
+
+ Object actualValue = resolver.resolveArgument(optionalMultipartFileList, null, webRequest, null);
+ assertTrue(actualValue instanceof Optional);
+ assertEquals("Invalid result", Collections.singletonList(expected), ((Optional) actualValue).get());
+
+ actualValue = resolver.resolveArgument(optionalMultipartFileList, null, webRequest, null);
+ assertTrue(actualValue instanceof Optional);
+ assertEquals("Invalid result", Collections.singletonList(expected), ((Optional) actualValue).get());
+ }
+
+ @Test
+ public void resolveOptionalMultipartFileListNotPresent() throws Exception {
+ MockMultipartHttpServletRequest request = new MockMultipartHttpServletRequest();
+ webRequest = new ServletWebRequest(request);
+
+ Object actualValue = resolver.resolveArgument(optionalMultipartFileList, null, webRequest, null);
+ assertEquals("Invalid argument value", Optional.empty(), actualValue);
+
+ actualValue = resolver.resolveArgument(optionalMultipartFileList, null, webRequest, null);
+ assertEquals("Invalid argument value", Optional.empty(), actualValue);
+ }
+
+ @Test
+ public void resolveOptionalMultipartFileListWithoutMultipartRequest() throws Exception {
+ webRequest = new ServletWebRequest(new MockHttpServletRequest());
+
+ Object actualValue = resolver.resolveArgument(optionalMultipartFileList, null, webRequest, null);
+ assertEquals("Invalid argument value", Optional.empty(), actualValue);
+
+ actualValue = resolver.resolveArgument(optionalMultipartFileList, null, webRequest, null);
+ assertEquals("Invalid argument value", Optional.empty(), actualValue);
}
@Test
@@ -337,12 +404,16 @@ public class RequestPartMethodArgumentResolverTests {
request.setMethod("POST");
request.setContentType("multipart/form-data");
request.addPart(expected);
+ request.addPart(new MockPart("otherPart", "Hello World".getBytes()));
webRequest = new ServletWebRequest(request);
- Object result = resolver.resolveArgument(optionalPart, null, webRequest, null);
+ Object actualValue = resolver.resolveArgument(optionalPart, null, webRequest, null);
+ assertTrue(actualValue instanceof Optional);
+ assertEquals("Invalid result", expected, ((Optional) actualValue).get());
- assertTrue(result instanceof Optional);
- assertEquals("Invalid result", expected, ((Optional) result).get());
+ actualValue = resolver.resolveArgument(optionalPart, null, webRequest, null);
+ assertTrue(actualValue instanceof Optional);
+ assertEquals("Invalid result", expected, ((Optional) actualValue).get());
}
@Test
@@ -352,36 +423,108 @@ public class RequestPartMethodArgumentResolverTests {
request.setContentType("multipart/form-data");
webRequest = new ServletWebRequest(request);
- Object result = resolver.resolveArgument(optionalPart, null, webRequest, null);
+ Object actualValue = resolver.resolveArgument(optionalPart, null, webRequest, null);
+ assertEquals("Invalid argument value", Optional.empty(), actualValue);
- assertTrue(result instanceof Optional);
- assertFalse("Invalid result", ((Optional) result).isPresent());
+ actualValue = resolver.resolveArgument(optionalPart, null, webRequest, null);
+ assertEquals("Invalid argument value", Optional.empty(), actualValue);
+ }
+
+ @Test
+ public void resolveOptionalPartArgumentWithoutMultipartRequest() throws Exception {
+ webRequest = new ServletWebRequest(new MockHttpServletRequest());
+
+ Object actualValue = resolver.resolveArgument(optionalPart, null, webRequest, null);
+ assertEquals("Invalid argument value", Optional.empty(), actualValue);
+
+ actualValue = resolver.resolveArgument(optionalPart, null, webRequest, null);
+ assertEquals("Invalid argument value", Optional.empty(), actualValue);
+ }
+
+ @Test
+ public void resolveOptionalPartList() throws Exception {
+ MockPart expected = new MockPart("requestPart", "Hello World".getBytes());
+ MockHttpServletRequest request = new MockHttpServletRequest();
+ request.setMethod("POST");
+ request.setContentType("multipart/form-data");
+ request.addPart(expected);
+ request.addPart(new MockPart("otherPart", "Hello World".getBytes()));
+ webRequest = new ServletWebRequest(request);
+
+ Object actualValue = resolver.resolveArgument(optionalPartList, null, webRequest, null);
+ assertTrue(actualValue instanceof Optional);
+ assertEquals("Invalid result", Collections.singletonList(expected), ((Optional) actualValue).get());
+
+ actualValue = resolver.resolveArgument(optionalPartList, null, webRequest, null);
+ assertTrue(actualValue instanceof Optional);
+ assertEquals("Invalid result", Collections.singletonList(expected), ((Optional) actualValue).get());
+ }
+
+ @Test
+ public void resolveOptionalPartListNotPresent() throws Exception {
+ MockHttpServletRequest request = new MockHttpServletRequest();
+ request.setMethod("POST");
+ request.setContentType("multipart/form-data");
+ webRequest = new ServletWebRequest(request);
+
+ Object actualValue = resolver.resolveArgument(optionalPartList, null, webRequest, null);
+ assertEquals("Invalid argument value", Optional.empty(), actualValue);
+
+ actualValue = resolver.resolveArgument(optionalPartList, null, webRequest, null);
+ assertEquals("Invalid argument value", Optional.empty(), actualValue);
+ }
+
+ @Test
+ public void resolveOptionalPartListWithoutMultipartRequest() throws Exception {
+ webRequest = new ServletWebRequest(new MockHttpServletRequest());
+
+ Object actualValue = resolver.resolveArgument(optionalPartList, null, webRequest, null);
+ assertEquals("Invalid argument value", Optional.empty(), actualValue);
+
+ actualValue = resolver.resolveArgument(optionalPartList, null, webRequest, null);
+ assertEquals("Invalid argument value", Optional.empty(), actualValue);
}
@Test
public void resolveOptionalRequestPart() throws Exception {
SimpleBean simpleBean = new SimpleBean("foo");
-
given(messageConverter.canRead(SimpleBean.class, MediaType.TEXT_PLAIN)).willReturn(true);
given(messageConverter.read(eq(SimpleBean.class), isA(HttpInputMessage.class))).willReturn(simpleBean);
ModelAndViewContainer mavContainer = new ModelAndViewContainer();
- Object actualValue = resolver.resolveArgument(optionalRequestPart, mavContainer, webRequest, new ValidatingBinderFactory());
+ Object actualValue = resolver.resolveArgument(optionalRequestPart, mavContainer, webRequest, new ValidatingBinderFactory());
+ assertEquals("Invalid argument value", Optional.of(simpleBean), actualValue);
+ assertFalse("The requestHandled flag shouldn't change", mavContainer.isRequestHandled());
+
+ actualValue = resolver.resolveArgument(optionalRequestPart, mavContainer, webRequest, new ValidatingBinderFactory());
assertEquals("Invalid argument value", Optional.of(simpleBean), actualValue);
assertFalse("The requestHandled flag shouldn't change", mavContainer.isRequestHandled());
}
@Test
public void resolveOptionalRequestPartNotPresent() throws Exception {
- given(messageConverter.canRead(SimpleBean.class, MediaType.TEXT_PLAIN)).willReturn(true);
- given(messageConverter.read(eq(SimpleBean.class), isA(RequestPartServletServerHttpRequest.class))).willReturn(null);
-
- ModelAndViewContainer mavContainer = new ModelAndViewContainer();
- Object actualValue = resolver.resolveArgument(optionalRequestPart, mavContainer, webRequest, new ValidatingBinderFactory());
+ MockHttpServletRequest request = new MockHttpServletRequest();
+ request.setMethod("POST");
+ request.setContentType("multipart/form-data");
+ webRequest = new ServletWebRequest(request);
+ Object actualValue = resolver.resolveArgument(optionalRequestPart, null, webRequest, null);
+ assertEquals("Invalid argument value", Optional.empty(), actualValue);
+
+ actualValue = resolver.resolveArgument(optionalRequestPart, null, webRequest, null);
+ assertEquals("Invalid argument value", Optional.empty(), actualValue);
+ }
+
+ @Test
+ public void resolveOptionalRequestPartWithoutMultipartRequest() throws Exception {
+ webRequest = new ServletWebRequest(new MockHttpServletRequest());
+
+ Object actualValue = resolver.resolveArgument(optionalRequestPart, null, webRequest, null);
+ assertEquals("Invalid argument value", Optional.empty(), actualValue);
+
+ actualValue = resolver.resolveArgument(optionalRequestPart, null, webRequest, null);
assertEquals("Invalid argument value", Optional.empty(), actualValue);
- assertFalse("The requestHandled flag shouldn't change", mavContainer.isRequestHandled());
}
@@ -390,8 +533,8 @@ public class RequestPartMethodArgumentResolverTests {
given(messageConverter.read(eq(SimpleBean.class), isA(HttpInputMessage.class))).willReturn(argValue);
ModelAndViewContainer mavContainer = new ModelAndViewContainer();
- Object actualValue = resolver.resolveArgument(parameter, mavContainer, webRequest, new ValidatingBinderFactory());
+ Object actualValue = resolver.resolveArgument(parameter, mavContainer, webRequest, new ValidatingBinderFactory());
assertEquals("Invalid argument value", argValue, actualValue);
assertFalse("The requestHandled flag shouldn't change", mavContainer.isRequestHandled());
}
@@ -425,22 +568,26 @@ public class RequestPartMethodArgumentResolverTests {
}
}
+
@SuppressWarnings("unused")
- public void handle(@RequestPart SimpleBean requestPart,
- @RequestPart(value="requestPart", required=false) SimpleBean namedRequestPart,
- @Valid @RequestPart("requestPart") SimpleBean validRequestPart,
- @RequestPart("requestPart") MultipartFile multipartFile,
- @RequestPart("requestPart") List multipartFileList,
- @RequestPart("requestPart") MultipartFile[] multipartFileArray,
- int i,
- MultipartFile multipartFileNotAnnot,
- Part part,
- @RequestPart("part") List partList,
- @RequestPart("part") Part[] partArray,
- @RequestParam MultipartFile requestParamAnnot,
- Optional optionalMultipartFile,
- Optional optionalPart,
- @RequestPart("requestPart") Optional optionalRequestPart) {
+ public void handle(
+ @RequestPart SimpleBean requestPart,
+ @RequestPart(value="requestPart", required=false) SimpleBean namedRequestPart,
+ @Valid @RequestPart("requestPart") SimpleBean validRequestPart,
+ @RequestPart("requestPart") MultipartFile multipartFile,
+ @RequestPart("requestPart") List multipartFileList,
+ @RequestPart("requestPart") MultipartFile[] multipartFileArray,
+ int i,
+ MultipartFile multipartFileNotAnnot,
+ Part part,
+ @RequestPart("requestPart") List partList,
+ @RequestPart("requestPart") Part[] partArray,
+ @RequestParam MultipartFile requestParamAnnot,
+ Optional optionalMultipartFile,
+ @RequestPart("requestPart") Optional> optionalMultipartFileList,
+ Optional optionalPart,
+ @RequestPart("requestPart") Optional> optionalPartList,
+ @RequestPart("requestPart") Optional optionalRequestPart) {
}
}
diff --git a/spring-webmvc/src/test/java/org/springframework/web/servlet/mvc/support/DefaultHandlerExceptionResolverTests.java b/spring-webmvc/src/test/java/org/springframework/web/servlet/mvc/support/DefaultHandlerExceptionResolverTests.java
index f7c35c2aee2..21bf3834bf1 100644
--- a/spring-webmvc/src/test/java/org/springframework/web/servlet/mvc/support/DefaultHandlerExceptionResolverTests.java
+++ b/spring-webmvc/src/test/java/org/springframework/web/servlet/mvc/support/DefaultHandlerExceptionResolverTests.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2013 the original author or authors.
+ * Copyright 2002-2016 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -47,7 +47,9 @@ import org.springframework.web.servlet.mvc.multiaction.NoSuchRequestHandlingMeth
import static org.junit.Assert.*;
-/** @author Arjen Poutsma */
+/**
+ * @author Arjen Poutsma
+ */
public class DefaultHandlerExceptionResolverTests {
private DefaultHandlerExceptionResolver exceptionResolver;
@@ -174,7 +176,9 @@ public class DefaultHandlerExceptionResolverTests {
assertNotNull("No ModelAndView returned", mav);
assertTrue("No Empty ModelAndView returned", mav.isEmpty());
assertEquals("Invalid status code", 400, response.getStatus());
- assertEquals("Required request part 'name' is not present.", response.getErrorMessage());
+ assertTrue(response.getErrorMessage().contains("request part"));
+ assertTrue(response.getErrorMessage().contains("name"));
+ assertTrue(response.getErrorMessage().contains("not present"));
}
@Test
@@ -211,6 +215,7 @@ public class DefaultHandlerExceptionResolverTests {
assertSame(ex, request.getAttribute("javax.servlet.error.exception"));
}
+
@SuppressWarnings("unused")
public void handle(String arg) {
}