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 17bceb9c31d..62b58d14df7 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 @@ -199,7 +199,7 @@ public class ServletAnnotationControllerTests { MockHttpServletRequest request = new MockHttpServletRequest("GET", "/myPath.do"); MockHttpServletResponse response = new MockHttpServletResponse(); servlet.service(request, response); - assertEquals("foo-null-bar", response.getContentAsString()); + assertEquals("foo--bar", response.getContentAsString()); } @Test @@ -1970,7 +1970,7 @@ public class ServletAnnotationControllerTests { @RequestMapping("/myPath.do") public void myHandle(@RequestParam(value = "id", defaultValue = "foo") String id, - @RequestParam(value = "otherId", required = false) String id2, + @RequestParam(value = "otherId", defaultValue = "") String id2, @RequestHeader(defaultValue = "bar") String header, HttpServletResponse response) throws IOException { response.getWriter().write(String.valueOf(id) + "-" + String.valueOf(id2) + "-" + String.valueOf(header)); diff --git a/org.springframework.web/src/main/java/org/springframework/web/bind/annotation/CookieValue.java b/org.springframework.web/src/main/java/org/springframework/web/bind/annotation/CookieValue.java index 5e476fe415b..4a74acb4585 100644 --- a/org.springframework.web/src/main/java/org/springframework/web/bind/annotation/CookieValue.java +++ b/org.springframework.web/src/main/java/org/springframework/web/bind/annotation/CookieValue.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2009 the original author or authors. + * Copyright 2002-2010 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. @@ -63,6 +63,6 @@ public @interface CookieValue { * The default value to use as a fallback. Supplying a default value implicitly * sets {@link #required()} to false. */ - String defaultValue() default ""; + String defaultValue() default ValueConstants.DEFAULT_NONE; } diff --git a/org.springframework.web/src/main/java/org/springframework/web/bind/annotation/RequestHeader.java b/org.springframework.web/src/main/java/org/springframework/web/bind/annotation/RequestHeader.java index e9214a2de43..5e985d18e9e 100644 --- a/org.springframework.web/src/main/java/org/springframework/web/bind/annotation/RequestHeader.java +++ b/org.springframework.web/src/main/java/org/springframework/web/bind/annotation/RequestHeader.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2009 the original author or authors. + * Copyright 2002-2010 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. @@ -58,6 +58,6 @@ public @interface RequestHeader { * The default value to use as a fallback. Supplying a default value implicitely * sets {@link #required()} to false. */ - String defaultValue() default ""; + String defaultValue() default ValueConstants.DEFAULT_NONE; } diff --git a/org.springframework.web/src/main/java/org/springframework/web/bind/annotation/RequestParam.java b/org.springframework.web/src/main/java/org/springframework/web/bind/annotation/RequestParam.java index 33b1ed55f61..0ed714f989b 100644 --- a/org.springframework.web/src/main/java/org/springframework/web/bind/annotation/RequestParam.java +++ b/org.springframework.web/src/main/java/org/springframework/web/bind/annotation/RequestParam.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2009 the original author or authors. + * Copyright 2002-2010 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. @@ -60,6 +60,6 @@ public @interface RequestParam { * The default value to use as a fallback. Supplying a default value implicitly * sets {@link #required()} to false. */ - String defaultValue() default ""; + String defaultValue() default ValueConstants.DEFAULT_NONE; } diff --git a/org.springframework.web/src/main/java/org/springframework/web/bind/annotation/ValueConstants.java b/org.springframework.web/src/main/java/org/springframework/web/bind/annotation/ValueConstants.java new file mode 100644 index 00000000000..e7f9c1a132d --- /dev/null +++ b/org.springframework.web/src/main/java/org/springframework/web/bind/annotation/ValueConstants.java @@ -0,0 +1,38 @@ +/* + * Copyright 2002-2010 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.bind.annotation; + +/** + * Common value constants shared between bind annotations. + * + * @author Juergen Hoeller + * @since 3.0.1 + */ +public interface ValueConstants { + + /** + * Constant defining a value for no default - as a replacement for + * null which we cannot use in annotation attributes. + *

This is an artificial arrangement of 16 unicode characters, + * with its sole purpose being to never match user-declared values. + * @see RequestParam#defaultValue() + * @see RequestHeader#defaultValue() + * @see CookieValue#defaultValue() + */ + String DEFAULT_NONE = "\n\t\t\n\t\t\n\uE000\uE001\uE002\n\t\t\t\t\n"; + +} diff --git a/org.springframework.web/src/main/java/org/springframework/web/bind/annotation/support/HandlerMethodInvoker.java b/org.springframework.web/src/main/java/org/springframework/web/bind/annotation/support/HandlerMethodInvoker.java index f2c97699c98..5c2ebf0714e 100644 --- a/org.springframework.web/src/main/java/org/springframework/web/bind/annotation/support/HandlerMethodInvoker.java +++ b/org.springframework.web/src/main/java/org/springframework/web/bind/annotation/support/HandlerMethodInvoker.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2009 the original author or authors. + * Copyright 2002-2010 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. @@ -50,7 +50,6 @@ import org.springframework.util.ClassUtils; import org.springframework.util.LinkedMultiValueMap; import org.springframework.util.MultiValueMap; import org.springframework.util.ReflectionUtils; -import org.springframework.util.StringUtils; import org.springframework.validation.BindException; import org.springframework.validation.BindingResult; import org.springframework.validation.Errors; @@ -63,6 +62,7 @@ import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestHeader; import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.ValueConstants; import org.springframework.web.bind.support.DefaultSessionAttributeStore; import org.springframework.web.bind.support.SessionAttributeStore; import org.springframework.web.bind.support.SessionStatus; @@ -200,14 +200,14 @@ public class HandlerMethodInvoker { RequestParam requestParam = (RequestParam) paramAnn; paramName = requestParam.value(); required = requestParam.required(); - defaultValue = requestParam.defaultValue(); + defaultValue = parseDefaultValueAttribute(requestParam.defaultValue()); found++; } else if (RequestHeader.class.isInstance(paramAnn)) { RequestHeader requestHeader = (RequestHeader) paramAnn; headerName = requestHeader.value(); required = requestHeader.required(); - defaultValue = requestHeader.defaultValue(); + defaultValue = parseDefaultValueAttribute(requestHeader.defaultValue()); found++; } else if (RequestBody.class.isInstance(paramAnn)) { @@ -218,7 +218,7 @@ public class HandlerMethodInvoker { CookieValue cookieValue = (CookieValue) paramAnn; cookieName = cookieValue.value(); required = cookieValue.required(); - defaultValue = cookieValue.defaultValue(); + defaultValue = parseDefaultValueAttribute(cookieValue.defaultValue()); found++; } else if (PathVariable.class.isInstance(paramAnn)) { @@ -430,7 +430,7 @@ public class HandlerMethodInvoker { } } if (paramValue == null) { - if (StringUtils.hasText(defaultValue)) { + if (defaultValue != null) { paramValue = resolveDefaultValue(defaultValue); } else if (required) { @@ -483,7 +483,7 @@ public class HandlerMethodInvoker { headerValue = (headerValues.length == 1 ? headerValues[0] : headerValues); } if (headerValue == null) { - if (StringUtils.hasText(defaultValue)) { + if (defaultValue != null) { headerValue = resolveDefaultValue(defaultValue); } else if (required) { @@ -566,7 +566,7 @@ public class HandlerMethodInvoker { } Object cookieValue = resolveCookieValue(cookieName, paramType, webRequest); if (cookieValue == null) { - if (StringUtils.hasText(defaultValue)) { + if (defaultValue != null) { cookieValue = resolveDefaultValue(defaultValue); } else if (required) { @@ -762,6 +762,10 @@ public class HandlerMethodInvoker { throw new UnsupportedOperationException("@RequestBody not supported"); } + protected String parseDefaultValueAttribute(String value) { + return (ValueConstants.DEFAULT_NONE.equals(value) ? null : value); + } + protected Object resolveDefaultValue(String value) { return value; }