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..ba34c2e4553 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. @@ -20,7 +20,6 @@ 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; @@ -123,24 +122,23 @@ public class RequestPartMethodArgumentResolver extends AbstractMessageConverterM } @Override - @UsesJava8 public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer, NativeWebRequest request, WebDataBinderFactory binderFactory) throws Exception { HttpServletRequest servletRequest = request.getNativeRequest(HttpServletRequest.class); assertIsMultipartRequest(servletRequest); - MultipartHttpServletRequest multipartRequest = WebUtils.getNativeRequest(servletRequest, MultipartHttpServletRequest.class); + String partName = getPartName(parameter); Class paramType = parameter.getParameterType(); boolean optional = paramType.getName().equals("java.util.Optional"); if (optional) { + parameter = new MethodParameter(parameter); parameter.increaseNestingLevel(); paramType = parameter.getNestedParameterType(); } - String partName = getPartName(parameter); Object arg; if (MultipartFile.class == paramType) { @@ -194,7 +192,7 @@ public class RequestPartMethodArgumentResolver extends AbstractMessageConverterM throw new MissingServletRequestPartException(partName); } if (optional) { - arg = Optional.ofNullable(arg); + arg = OptionalResolver.resolveValue(arg); } return arg; @@ -264,4 +262,16 @@ public class RequestPartMethodArgumentResolver extends AbstractMessageConverterM } } + + /** + * Inner class to avoid hard-coded dependency on Java 8 Optional type... + */ + @UsesJava8 + private static class OptionalResolver { + + public static Object resolveValue(Object value) { + return Optional.ofNullable(value); + } + } + } 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..d1944b1783b 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. @@ -26,7 +26,6 @@ import javax.servlet.http.Part; import javax.validation.Valid; import javax.validation.constraints.NotNull; -import org.hamcrest.Matchers; import org.junit.Before; import org.junit.Test; @@ -157,14 +156,12 @@ public class RequestPartMethodArgumentResolverTests { @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 +172,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); } @@ -202,7 +200,6 @@ public class RequestPartMethodArgumentResolverTests { webRequest = new ServletWebRequest(request); Object result = resolver.resolveArgument(paramPart, null, webRequest, null); - assertTrue(result instanceof Part); assertEquals("Invalid result", expected, result); } @@ -219,7 +216,6 @@ public class RequestPartMethodArgumentResolverTests { webRequest = new ServletWebRequest(request); Object result = resolver.resolveArgument(paramPartList, null, webRequest, null); - assertTrue(result instanceof List); assertEquals(Arrays.asList(part1, part2), result); } @@ -236,10 +232,9 @@ public class RequestPartMethodArgumentResolverTests { 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 +297,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 @@ -313,10 +308,13 @@ public class RequestPartMethodArgumentResolverTests { request.addFile(expected); 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 +322,11 @@ 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 @@ -339,10 +338,13 @@ public class RequestPartMethodArgumentResolverTests { request.addPart(expected); 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,22 +354,26 @@ 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 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()); + 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()); } @@ -378,8 +384,12 @@ public class RequestPartMethodArgumentResolverTests { given(messageConverter.read(eq(SimpleBean.class), isA(RequestPartServletServerHttpRequest.class))).willReturn(null); ModelAndViewContainer mavContainer = new ModelAndViewContainer(); + Object actualValue = resolver.resolveArgument(optionalRequestPart, mavContainer, webRequest, new ValidatingBinderFactory()); + assertEquals("Invalid argument value", Optional.empty(), actualValue); + assertFalse("The requestHandled flag shouldn't change", mavContainer.isRequestHandled()); + actualValue = resolver.resolveArgument(optionalRequestPart, mavContainer, webRequest, new ValidatingBinderFactory()); assertEquals("Invalid argument value", Optional.empty(), actualValue); assertFalse("The requestHandled flag shouldn't change", mavContainer.isRequestHandled()); } @@ -390,8 +400,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 +435,24 @@ 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, + Optional optionalPart, + @RequestPart("requestPart") Optional optionalRequestPart) { } }