Repository: tapestry-5 Updated Branches: refs/heads/master d29d6dc59 -> 5649174f0
TAP5-2030: Allow blank values to bypass value encoder and go directly to null, if enabled by annotation Project: http://git-wip-us.apache.org/repos/asf/tapestry-5/repo Commit: http://git-wip-us.apache.org/repos/asf/tapestry-5/commit/5649174f Tree: http://git-wip-us.apache.org/repos/asf/tapestry-5/tree/5649174f Diff: http://git-wip-us.apache.org/repos/asf/tapestry-5/diff/5649174f Branch: refs/heads/master Commit: 5649174f0fc642bd01baf5dcc81958a48b636556 Parents: d29d6dc Author: Howard M. Lewis Ship <hls...@apache.org> Authored: Fri Aug 1 16:26:43 2014 -0700 Committer: Howard M. Lewis Ship <hls...@apache.org> Committed: Fri Aug 1 16:26:43 2014 -0700 ---------------------------------------------------------------------- 54_RELEASE_NOTES.md | 9 ++++- .../TypeCoercedValueEncoderFactory.java | 11 ++++-- .../internal/transform/OnEventWorker.java | 32 ++++++++++------- .../src/test/app1/RequestParameterDemo.tml | 3 ++ .../integration/app1/RequestParameterTests.java | 10 ++++-- .../app1/pages/RequestParameterDemo.java | 37 ++++++++++++++------ 6 files changed, 74 insertions(+), 28 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/5649174f/54_RELEASE_NOTES.md ---------------------------------------------------------------------- diff --git a/54_RELEASE_NOTES.md b/54_RELEASE_NOTES.md index 9161e0a..00e3dcb 100644 --- a/54_RELEASE_NOTES.md +++ b/54_RELEASE_NOTES.md @@ -418,4 +418,11 @@ where desired. ## Java 1.6 required -As of version 5.4, Tapestry requires Java 1.6 at least. \ No newline at end of file +As of version 5.4, Tapestry requires Java 1.6 at least. + +## ValueEncoder Changes + +The automatic ValueEncoder from String to any Number type, or ti Boolean have +changed slightly. An empty input string is encoded to a null rather than being passed through +the type coercer. This reflects the desire that a submitted value (in a URL or a form) that is blank +is the same as no value: null. http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/5649174f/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/TypeCoercedValueEncoderFactory.java ---------------------------------------------------------------------- diff --git a/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/TypeCoercedValueEncoderFactory.java b/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/TypeCoercedValueEncoderFactory.java index bee075d..9d67d87 100644 --- a/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/TypeCoercedValueEncoderFactory.java +++ b/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/TypeCoercedValueEncoderFactory.java @@ -1,5 +1,3 @@ -// Copyright 2008 The Apache Software Foundation -// // 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 @@ -15,6 +13,7 @@ package org.apache.tapestry5.internal.services; import org.apache.tapestry5.ValueEncoder; +import org.apache.tapestry5.ioc.internal.util.InternalUtils; import org.apache.tapestry5.ioc.services.TypeCoercer; import org.apache.tapestry5.services.ValueEncoderFactory; @@ -33,6 +32,10 @@ public class TypeCoercedValueEncoderFactory implements ValueEncoderFactory<Objec public ValueEncoder<Object> create(final Class<Object> type) { + final boolean blankToNull = + Boolean.class.isAssignableFrom(type) || + Number.class.isAssignableFrom(type); + return new ValueEncoder<Object>() { public String toClient(Object value) @@ -42,6 +45,10 @@ public class TypeCoercedValueEncoderFactory implements ValueEncoderFactory<Objec public Object toValue(String clientValue) { + if (blankToNull && InternalUtils.isBlank(clientValue)) { + return null; + } + return typeCoercer.coerce(clientValue, type); } }; http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/5649174f/tapestry-core/src/main/java/org/apache/tapestry5/internal/transform/OnEventWorker.java ---------------------------------------------------------------------- diff --git a/tapestry-core/src/main/java/org/apache/tapestry5/internal/transform/OnEventWorker.java b/tapestry-core/src/main/java/org/apache/tapestry5/internal/transform/OnEventWorker.java index 9a4a92d..c640158 100644 --- a/tapestry-core/src/main/java/org/apache/tapestry5/internal/transform/OnEventWorker.java +++ b/tapestry-core/src/main/java/org/apache/tapestry5/internal/transform/OnEventWorker.java @@ -1,4 +1,3 @@ -// Copyright 2006-2013 The Apache Software Foundation // 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 @@ -432,35 +431,36 @@ public class OnEventWorker implements ComponentClassTransformWorker2 { try { - + Class parameterType = classCache.forName(parameterTypeName); boolean isArray = parameterType.isArray(); - + if (isArray) { parameterType = parameterType.getComponentType(); } - + ValueEncoder valueEncoder = valueEncoderSource.getValueEncoder(parameterType); String parameterValue = request.getParameter(parameterName); - if (!allowBlank && parameterValue == null) + if (!allowBlank && InternalUtils.isBlank(parameterValue)) throw new RuntimeException(String.format( "The value for query parameter '%s' was blank, but a non-blank value is needed.", parameterName)); - + Object value; - if (!isArray) { - value = coerce(parameterName, parameterType, parameterValue, valueEncoder); - } - else { + if (!isArray) + { + value = coerce(parameterName, parameterType, parameterValue, valueEncoder, allowBlank); + } else + { String[] parameterValues = request.getParameters(parameterName); Object[] array = (Object[]) Array.newInstance(parameterType, parameterValues.length); for (int i = 0; i < parameterValues.length; i++) { - array[i] = coerce(parameterName, parameterType, parameterValues[i], valueEncoder); + array[i] = coerce(parameterName, parameterType, parameterValues[i], valueEncoder, allowBlank); } value = array; } @@ -477,8 +477,16 @@ public class OnEventWorker implements ComponentClassTransformWorker2 } private Object coerce(final String parameterName, Class parameterType, - String parameterValue, ValueEncoder valueEncoder) + String parameterValue, ValueEncoder valueEncoder, boolean allowBlank) { + + if (!allowBlank && InternalUtils.isBlank(parameterValue)) + { + throw new RuntimeException(String.format( + "The value for query parameter '%s' was blank, but a non-blank value is needed.", + parameterName)); + } + Object value = valueEncoder.toValue(parameterValue); if (parameterType.isPrimitive() && value == null) http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/5649174f/tapestry-core/src/test/app1/RequestParameterDemo.tml ---------------------------------------------------------------------- diff --git a/tapestry-core/src/test/app1/RequestParameterDemo.tml b/tapestry-core/src/test/app1/RequestParameterDemo.tml index 6d13f2e..683b9c4 100644 --- a/tapestry-core/src/test/app1/RequestParameterDemo.tml +++ b/tapestry-core/src/test/app1/RequestParameterDemo.tml @@ -31,5 +31,8 @@ <li> <a href="${nullAllowedLink}">Null Allowed Link</a> </li> + <li> + <a href="${blankAllowedLink}">Blank Allowed Link</a> + </li> </ul> </html> \ No newline at end of file http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/5649174f/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/RequestParameterTests.java ---------------------------------------------------------------------- diff --git a/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/RequestParameterTests.java b/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/RequestParameterTests.java index 0ac0193..f2b8457 100644 --- a/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/RequestParameterTests.java +++ b/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/RequestParameterTests.java @@ -1,5 +1,3 @@ -// Copyright 2010-2013 The Apache Software Foundation -// // 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 @@ -68,4 +66,12 @@ public class RequestParameterTests extends App1TestCase "org.apache.tapestry5.integration.app1.pages.RequestParameterDemo.onFrob(int)", "Coercion of frodo to type java.lang.Integer"); } + + @Test + public void blank_allowed_for_wrapper_types_if_enabled() { + openLinks("RequestParameter Annotation Demo", "Blank Allowed Link"); + + assertText("id=current", "-1"); + + } } http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/5649174f/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/RequestParameterDemo.java ---------------------------------------------------------------------- diff --git a/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/RequestParameterDemo.java b/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/RequestParameterDemo.java index f7bd799..8e1184c 100644 --- a/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/RequestParameterDemo.java +++ b/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/RequestParameterDemo.java @@ -1,5 +1,3 @@ -// Copyright 2010 The Apache Software Foundation -// // 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 @@ -14,9 +12,6 @@ package org.apache.tapestry5.integration.app1.pages; -import java.util.Arrays; -import java.util.List; - import org.apache.tapestry5.ComponentResources; import org.apache.tapestry5.Link; import org.apache.tapestry5.annotations.Persist; @@ -24,12 +19,15 @@ import org.apache.tapestry5.annotations.Property; import org.apache.tapestry5.annotations.RequestParameter; import org.apache.tapestry5.ioc.annotations.Inject; +import java.util.Arrays; +import java.util.List; + public class RequestParameterDemo { private static final String PARAMETER_NAME = "gnip"; private static final String EVENT_NAME = "frob"; - + private static final String MULTIVALUED_PARAMETER_EVENT_NAME = "frobFrob"; @Property @@ -50,7 +48,7 @@ public class RequestParameterDemo return link; } - + public Link getMultivaluedQueryParameterLink() { Link link = resources.createEventLink(MULTIVALUED_PARAMETER_EVENT_NAME); @@ -69,6 +67,11 @@ public class RequestParameterDemo return link; } + public Link getBlankAllowedLink() + { + return resources.createEventLink("emptyStringAllowed").addParameter(PARAMETER_NAME, ""); + } + public Link getNullLink() { return resources.createEventLink(EVENT_NAME); @@ -80,20 +83,32 @@ public class RequestParameterDemo } void onFrob(@RequestParameter(PARAMETER_NAME) - int value) + int value) { this.value = value; } - + void onFrobFrob(@RequestParameter(PARAMETER_NAME) - Integer[] values) + Integer[] values) { this.values = Arrays.asList(values); } void onFrobNullAllowed(@RequestParameter(value = PARAMETER_NAME, allowBlank = true) - int value) + int value) { this.value = value; } + + void onEmptyStringAllowed(@RequestParameter(value = PARAMETER_NAME, allowBlank = true) Integer value) + { + if (value == null) + { + this.value = -1; + } else + { + this.value = value.intValue(); + } + + } }