diff --git a/org.springframework.web.servlet/src/main/java/org/springframework/web/bind/annotation/support/HandlerMethodInvoker.java b/org.springframework.web.servlet/src/main/java/org/springframework/web/bind/annotation/support/HandlerMethodInvoker.java index 3bea9a84162..3fb397098fc 100644 --- a/org.springframework.web.servlet/src/main/java/org/springframework/web/bind/annotation/support/HandlerMethodInvoker.java +++ b/org.springframework.web.servlet/src/main/java/org/springframework/web/bind/annotation/support/HandlerMethodInvoker.java @@ -384,7 +384,7 @@ public class HandlerMethodInvoker { else if (required) { raiseMissingParameterException(paramName, paramType); } - checkValue(paramName, paramValue, paramType); + paramValue = checkValue(paramName, paramValue, paramType); } WebDataBinder binder = createBinder(webRequest, null, paramName); initBinder(handlerForInitBinderCall, paramName, binder, webRequest); @@ -411,7 +411,7 @@ public class HandlerMethodInvoker { else if (required) { raiseMissingHeaderException(headerName, paramType); } - checkValue(headerName, headerValue, paramType); + headerValue = checkValue(headerName, headerValue, paramType); } WebDataBinder binder = createBinder(webRequest, null, headerName); initBinder(handlerForInitBinderCall, headerName, binder, webRequest); @@ -434,7 +434,7 @@ public class HandlerMethodInvoker { else if (required) { raiseMissingCookieException(cookieName, paramType); } - checkValue(cookieName, cookieValue, paramType); + cookieValue = checkValue(cookieName, cookieValue, paramType); } WebDataBinder binder = createBinder(webRequest, null, cookieName); initBinder(handlerForInitBinderCall, cookieName, binder, webRequest); @@ -484,12 +484,18 @@ public class HandlerMethodInvoker { return name; } - private void checkValue(String name, Object value, Class paramType) { - if (value == null && paramType.isPrimitive()) { - throw new IllegalStateException("Optional " + paramType + " parameter '" + name + - "' is not present but cannot be translated into a null value due to being declared as a " + - "primitive type. Consider declaring it as object wrapper for the corresponding primitive type."); + private Object checkValue(String name, Object value, Class paramType) { + if (value == null) { + if (boolean.class.equals(paramType)) { + return Boolean.FALSE; + } + else if (paramType.isPrimitive()) { + throw new IllegalStateException("Optional " + paramType + " parameter '" + name + + "' is not present but cannot be translated into a null value due to being declared as a " + + "primitive type. Consider declaring it as object wrapper for the corresponding primitive type."); + } } + return value; } private WebDataBinder resolveModelAttribute(String attrName, MethodParameter methodParam, diff --git a/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/mvc/annotation/ServletAnnotationControllerTests.java b/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/mvc/annotation/ServletAnnotationControllerTests.java index 500ec6678be..2d184e3d90f 100644 --- a/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/mvc/annotation/ServletAnnotationControllerTests.java +++ b/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/mvc/annotation/ServletAnnotationControllerTests.java @@ -130,6 +130,28 @@ public class ServletAnnotationControllerTests { servlet.service(request, response); } + @Test + public void optionalParamPresent() throws Exception { + @SuppressWarnings("serial") DispatcherServlet servlet = new DispatcherServlet() { + @Override + protected WebApplicationContext createWebApplicationContext(WebApplicationContext parent) { + GenericWebApplicationContext wac = new GenericWebApplicationContext(); + wac.registerBeanDefinition("controller", new RootBeanDefinition(OptionalParamController.class)); + wac.refresh(); + return wac; + } + }; + servlet.init(new MockServletConfig()); + + MockHttpServletRequest request = new MockHttpServletRequest("GET", "/myPath.do"); + request.addParameter("id", "val"); + request.addParameter("flag", "true"); + request.addHeader("header", "otherVal"); + MockHttpServletResponse response = new MockHttpServletResponse(); + servlet.service(request, response); + assertEquals("val-true-otherVal", response.getContentAsString()); + } + @Test public void optionalParamMissing() throws Exception { @SuppressWarnings("serial") DispatcherServlet servlet = new DispatcherServlet() { @@ -146,7 +168,7 @@ public class ServletAnnotationControllerTests { MockHttpServletRequest request = new MockHttpServletRequest("GET", "/myPath.do"); MockHttpServletResponse response = new MockHttpServletResponse(); servlet.service(request, response); - assertEquals("null-null", response.getContentAsString()); + assertEquals("null-false-null", response.getContentAsString()); } @Test @@ -1318,10 +1340,10 @@ public class ServletAnnotationControllerTests { public static class OptionalParamController { @RequestMapping("/myPath.do") - public void myHandle(@RequestParam(required = false) String id, + public void myHandle(@RequestParam(required = false) String id, @RequestParam(required = false) boolean flag, @RequestHeader(value = "header", required = false) String header, HttpServletResponse response) throws IOException { - response.getWriter().write(String.valueOf(id) + "-" + String.valueOf(header)); + response.getWriter().write(String.valueOf(id) + "-" + flag + "-" + String.valueOf(header)); } }