You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tapestry.apache.org by th...@apache.org on 2014/05/27 16:29:28 UTC
git commit: Backports the fix for TAP5-1718 to 5.3.x
Repository: tapestry-5
Updated Branches:
refs/heads/5.3 4445ae4df -> 4a5b8fc69
Backports the fix for TAP5-1718 to 5.3.x
Project: http://git-wip-us.apache.org/repos/asf/tapestry-5/repo
Commit: http://git-wip-us.apache.org/repos/asf/tapestry-5/commit/4a5b8fc6
Tree: http://git-wip-us.apache.org/repos/asf/tapestry-5/tree/4a5b8fc6
Diff: http://git-wip-us.apache.org/repos/asf/tapestry-5/diff/4a5b8fc6
Branch: refs/heads/5.3
Commit: 4a5b8fc6994b0138e60f90666b55f3b54c71ecfe
Parents: 4445ae4
Author: Thiago H. de Paula Figueiredo <th...@apache.org>
Authored: Fri Jan 10 15:25:12 2014 -0200
Committer: Thiago H. de Paula Figueiredo <th...@arsmachina.com.br>
Committed: Tue May 27 11:29:11 2014 -0300
----------------------------------------------------------------------
.../beanvalidator/BeanFieldValidator.java | 348 +++++++++++--------
.../TapestryBeanValidationIntegrationTests.java | 24 +-
.../example/testapp/entities/ComplexBean.java | 13 +
.../example/testapp/pages/NestedObjectDemo.java | 38 ++
.../org/example/testapp/services/AppModule.java | 1 +
.../src/test/webapp/Index.tml | 3 +
.../src/test/webapp/NestedObjectDemo.tml | 22 ++
.../internal/bindings/PropBinding.java | 12 +-
.../internal/bindings/PropBindingFactory.java | 2 +-
.../InternalComponentResourcesImpl.java | 7 +
10 files changed, 312 insertions(+), 158 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/4a5b8fc6/tapestry-beanvalidator/src/main/java/org/apache/tapestry5/internal/beanvalidator/BeanFieldValidator.java
----------------------------------------------------------------------
diff --git a/tapestry-beanvalidator/src/main/java/org/apache/tapestry5/internal/beanvalidator/BeanFieldValidator.java b/tapestry-beanvalidator/src/main/java/org/apache/tapestry5/internal/beanvalidator/BeanFieldValidator.java
index 43eedfd..06e6fb9 100644
--- a/tapestry-beanvalidator/src/main/java/org/apache/tapestry5/internal/beanvalidator/BeanFieldValidator.java
+++ b/tapestry-beanvalidator/src/main/java/org/apache/tapestry5/internal/beanvalidator/BeanFieldValidator.java
@@ -1,4 +1,4 @@
-// Copyright 2010 The Apache Software Foundation
+// Copyright 2010, 2012 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.
@@ -13,21 +13,6 @@
// limitations under the License.
package org.apache.tapestry5.internal.beanvalidator;
-import static java.lang.String.format;
-
-import java.lang.annotation.Annotation;
-import java.util.Iterator;
-import java.util.Set;
-
-import javax.validation.ConstraintViolation;
-import javax.validation.MessageInterpolator;
-import javax.validation.Validator;
-import javax.validation.ValidatorFactory;
-import javax.validation.MessageInterpolator.Context;
-import javax.validation.metadata.BeanDescriptor;
-import javax.validation.metadata.ConstraintDescriptor;
-import javax.validation.metadata.PropertyDescriptor;
-
import org.apache.tapestry5.Field;
import org.apache.tapestry5.FieldValidator;
import org.apache.tapestry5.MarkupWriter;
@@ -36,156 +21,213 @@ import org.apache.tapestry5.beanvalidator.BeanValidatorGroupSource;
import org.apache.tapestry5.beanvalidator.ClientConstraintDescriptor;
import org.apache.tapestry5.beanvalidator.ClientConstraintDescriptorSource;
import org.apache.tapestry5.internal.BeanValidationContext;
+import org.apache.tapestry5.ioc.internal.util.CollectionFactory;
import org.apache.tapestry5.json.JSONObject;
import org.apache.tapestry5.services.Environment;
import org.apache.tapestry5.services.FormSupport;
+import javax.validation.ConstraintViolation;
+import javax.validation.MessageInterpolator;
+import javax.validation.MessageInterpolator.Context;
+import javax.validation.Validator;
+import javax.validation.ValidatorFactory;
+import javax.validation.metadata.BeanDescriptor;
+import javax.validation.metadata.ConstraintDescriptor;
+import javax.validation.metadata.PropertyDescriptor;
+
+import java.lang.annotation.Annotation;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Set;
+
+import static java.lang.String.format;
+
public class BeanFieldValidator implements FieldValidator
{
- private final Field field;
- private final ValidatorFactory validatorFactory;
- private final BeanValidatorGroupSource beanValidationGroupSource;
- private final ClientConstraintDescriptorSource clientValidatorSource;
- private final FormSupport formSupport;
- private final Environment environment;
-
- public BeanFieldValidator(Field field,
- ValidatorFactory validatorFactory,
- BeanValidatorGroupSource beanValidationGroupSource,
- ClientConstraintDescriptorSource clientValidatorSource,
- FormSupport formSupport,
- Environment environment)
- {
- this.field = field;
- this.validatorFactory = validatorFactory;
- this.beanValidationGroupSource = beanValidationGroupSource;
- this.clientValidatorSource = clientValidatorSource;
- this.formSupport = formSupport;
- this.environment = environment;
- }
-
- public boolean isRequired()
- {
- return false;
- }
-
- public void render(final MarkupWriter writer)
- {
- final BeanValidationContext beanValidationContext = environment.peek(BeanValidationContext.class);
-
- if (beanValidationContext == null)
- {
- return;
- }
-
- final Validator validator = validatorFactory.getValidator();
-
- BeanDescriptor beanDescriptor = validator.getConstraintsForClass(beanValidationContext.getBeanType());
-
- String currentProperty = beanValidationContext.getCurrentProperty();
-
- if(currentProperty == null) return;
-
- PropertyDescriptor propertyDescriptor = beanDescriptor.getConstraintsForProperty(currentProperty);
-
- if(propertyDescriptor == null) return;
-
- for (final ConstraintDescriptor<?> descriptor :propertyDescriptor.getConstraintDescriptors())
- {
- Class<? extends Annotation> annotationType = descriptor.getAnnotation().annotationType();
-
- ClientConstraintDescriptor clientConstraintDescriptor = clientValidatorSource.getConstraintDescriptor(annotationType);
-
- if(clientConstraintDescriptor != null)
- {
- String message = format("%s %s", field.getLabel(), interpolateMessage(descriptor));
-
- JSONObject specs = new JSONObject();
-
- for (String attribute : clientConstraintDescriptor.getAttributes())
+ private final Field field;
+ private final ValidatorFactory validatorFactory;
+ private final BeanValidatorGroupSource beanValidationGroupSource;
+ private final ClientConstraintDescriptorSource clientValidatorSource;
+ private final FormSupport formSupport;
+ private final Environment environment;
+
+ public BeanFieldValidator(Field field,
+ ValidatorFactory validatorFactory,
+ BeanValidatorGroupSource beanValidationGroupSource,
+ ClientConstraintDescriptorSource clientValidatorSource,
+ FormSupport formSupport,
+ Environment environment)
+ {
+ this.field = field;
+ this.validatorFactory = validatorFactory;
+ this.beanValidationGroupSource = beanValidationGroupSource;
+ this.clientValidatorSource = clientValidatorSource;
+ this.formSupport = formSupport;
+ this.environment = environment;
+ }
+
+ public boolean isRequired()
+ {
+ return false;
+ }
+
+ public void render(final MarkupWriter writer)
+ {
+ final BeanValidationContext beanValidationContext = environment.peek(BeanValidationContext.class);
+
+ if (beanValidationContext == null)
+ {
+ return;
+ }
+
+ final Validator validator = validatorFactory.getValidator();
+
+ BeanDescriptor beanDescriptor = validator.getConstraintsForClass(beanValidationContext.getBeanType());
+
+ String currentProperty = beanValidationContext.getCurrentProperty();
+
+ if (currentProperty == null) return;
+
+ PropertyDescriptor propertyDescriptor = beanDescriptor.getConstraintsForProperty(currentProperty);
+
+ if (propertyDescriptor == null) return;
+
+ for (final ConstraintDescriptor<?> descriptor : propertyDescriptor.getConstraintDescriptors())
+ {
+ Class<? extends Annotation> annotationType = descriptor.getAnnotation().annotationType();
+
+ ClientConstraintDescriptor clientConstraintDescriptor = clientValidatorSource.getConstraintDescriptor(annotationType);
+
+ if (clientConstraintDescriptor == null)
+ {
+ continue;
+ }
+
+ String message = format("%s %s", field.getLabel(), interpolateMessage(descriptor));
+ JSONObject specs = new JSONObject();
+
+ Map<String, Object> attributes = CollectionFactory.newMap();
+
+ for (String attribute : clientConstraintDescriptor.getAttributes())
+ {
+ Object object = descriptor.getAttributes().get(attribute);
+
+ if (object == null)
{
- Object object = descriptor.getAttributes().get(attribute);
-
- if (object == null)
- {
- throw new RuntimeException("Expected attribute is null");
- }
- specs.put(attribute, object);
+ throw new NullPointerException(
+ String.format("Attribute '%s' of %s is null but is required to apply client-side validation.",
+ attribute, descriptor));
}
+ attributes.put(attribute, object);
+
+ specs.put(attribute, object);
- formSupport.addValidation(field, clientConstraintDescriptor.getValidatorName(), message, specs);
- }
- }
- }
-
- @SuppressWarnings("unchecked")
- public void validate(final Object value) throws ValidationException
- {
-
- final BeanValidationContext beanValidationContext = environment.peek(BeanValidationContext.class);
-
- if (beanValidationContext == null)
- {
- return;
- }
-
- final Validator validator = validatorFactory.getValidator();
-
- String currentProperty = beanValidationContext.getCurrentProperty();
-
- if(currentProperty == null) return;
-
- BeanDescriptor beanDescriptor = validator.getConstraintsForClass(beanValidationContext.getBeanType());
-
- PropertyDescriptor propertyDescriptor = beanDescriptor.getConstraintsForProperty(currentProperty);
-
- if(propertyDescriptor == null) return;
-
- final Set<ConstraintViolation<Object>> violations = validator.validateValue(
- (Class<Object>) beanValidationContext.getBeanType(), currentProperty,
- value, beanValidationGroupSource.get());
-
- if (violations.isEmpty())
- {
- return;
- }
-
- final StringBuilder builder = new StringBuilder();
-
- for (Iterator iterator = violations.iterator(); iterator.hasNext();)
- {
- ConstraintViolation<?> violation = (ConstraintViolation<Object>) iterator.next();
-
- builder.append(format("%s %s", field.getLabel(), violation.getMessage()));
-
- if(iterator.hasNext())
- builder.append(", ");
-
- }
-
- throw new ValidationException(builder.toString());
-
- }
-
- private String interpolateMessage(final ConstraintDescriptor<?> descriptor)
- {
- String messageTemplate = (String) descriptor.getAttributes().get("message");
-
- MessageInterpolator messageInterpolator = validatorFactory.getMessageInterpolator();
-
- return messageInterpolator.interpolate(messageTemplate, new Context()
- {
-
- public ConstraintDescriptor<?> getConstraintDescriptor()
+ }
+
+ formSupport.addValidation(field, clientConstraintDescriptor.getValidatorName(), message, specs);
+
+ }
+
+ }
+
+ @SuppressWarnings("unchecked")
+ public void validate(final Object value) throws ValidationException
+ {
+
+ final BeanValidationContext beanValidationContext = environment.peek(BeanValidationContext.class);
+
+ if (beanValidationContext == null)
+ {
+ return;
+ }
+
+ final Validator validator = validatorFactory.getValidator();
+
+ String currentProperty = beanValidationContext.getCurrentProperty();
+
+ if (currentProperty == null) return;
+
+ Class<?> beanType = beanValidationContext.getBeanType();
+ String[] path = currentProperty.split("\\.");
+ BeanDescriptor beanDescriptor = validator.getConstraintsForClass(beanType);
+
+ for (int i = 1; i < path.length - 1; i++)
+ {
+ Class<?> constrainedPropertyClass = getConstrainedPropertyClass(beanDescriptor, path[i]);
+ if (constrainedPropertyClass != null) {
+ beanType = constrainedPropertyClass;
+ beanDescriptor = validator.getConstraintsForClass(beanType);
+ }
+ }
+
+ final String propertyName = path[path.length - 1];
+ PropertyDescriptor propertyDescriptor = beanDescriptor.getConstraintsForProperty(propertyName);
+
+ if (propertyDescriptor == null) return;
+
+ final Set<ConstraintViolation<Object>> violations = validator.validateValue(
+ (Class<Object>) beanType, propertyName,
+ value, beanValidationGroupSource.get());
+
+ if (violations.isEmpty())
+ {
+ return;
+ }
+
+ final StringBuilder builder = new StringBuilder();
+
+ for (Iterator<ConstraintViolation<Object>> iterator = violations.iterator(); iterator.hasNext(); )
+ {
+ ConstraintViolation<?> violation = iterator.next();
+
+ builder.append(format("%s %s", field.getLabel(), violation.getMessage()));
+
+ if (iterator.hasNext())
+ builder.append(", ");
+
+ }
+
+ throw new ValidationException(builder.toString());
+
+ }
+
+ /**
+ * Returns the class of a given property, but only if it is a constrained property of the
+ * parent class. Otherwise, it returns null.
+ */
+ final private static Class<?> getConstrainedPropertyClass(BeanDescriptor beanDescriptor, String propertyName)
+ {
+ Class<?> clasz = null;
+ for (PropertyDescriptor descriptor : beanDescriptor.getConstrainedProperties())
+ {
+ if (descriptor.getPropertyName().equals(propertyName))
+ {
+ clasz = descriptor.getElementClass();
+ break;
+ }
+ }
+ return clasz;
+ }
+
+ private String interpolateMessage(final ConstraintDescriptor<?> descriptor)
+ {
+ String messageTemplate = (String) descriptor.getAttributes().get("message");
+
+ MessageInterpolator messageInterpolator = validatorFactory.getMessageInterpolator();
+
+ return messageInterpolator.interpolate(messageTemplate, new Context()
+ {
+
+ public ConstraintDescriptor<?> getConstraintDescriptor()
{
- return descriptor;
+ return descriptor;
}
- public Object getValidatedValue()
+ public Object getValidatedValue()
{
- return null;
+ return null;
}
});
- }
-}
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/4a5b8fc6/tapestry-beanvalidator/src/test/java/org/apache/tapestry5/beanvalidator/integration/TapestryBeanValidationIntegrationTests.java
----------------------------------------------------------------------
diff --git a/tapestry-beanvalidator/src/test/java/org/apache/tapestry5/beanvalidator/integration/TapestryBeanValidationIntegrationTests.java b/tapestry-beanvalidator/src/test/java/org/apache/tapestry5/beanvalidator/integration/TapestryBeanValidationIntegrationTests.java
index 1d686c4..f068d6a 100644
--- a/tapestry-beanvalidator/src/test/java/org/apache/tapestry5/beanvalidator/integration/TapestryBeanValidationIntegrationTests.java
+++ b/tapestry-beanvalidator/src/test/java/org/apache/tapestry5/beanvalidator/integration/TapestryBeanValidationIntegrationTests.java
@@ -1,4 +1,4 @@
-// Copyright 2009, 2010 The Apache Software Foundation
+// Copyright 2009-2014 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.
@@ -18,7 +18,7 @@ import org.apache.tapestry5.test.TapestryTestConfiguration;
import org.testng.annotations.Test;
@Test(sequential = true, groups = "integration")
-@TapestryTestConfiguration(webAppFolder = "src/test/webapp")
+@TapestryTestConfiguration(webAppFolder = "src/test/webapp", port = 8080, browserStartCommand="*opera"/*browserStartCommand="*custom /usr/bin/chromium-browser"*/)
public class TapestryBeanValidationIntegrationTests extends SeleniumTestCase
{
@Test
@@ -217,6 +217,26 @@ public class TapestryBeanValidationIntegrationTests extends SeleniumTestCase
}
+ // TAP5-1718
+ @Test
+ public void nested_object_validation() throws Exception
+ {
+
+ final String locatorTemplate = "//p[@data-error-block-for='%s']";
+
+ openLinks("NestedObject Demo");
+
+ clickAndWait(SUBMIT);
+
+ assertEquals("You must provide a value for Not Null String.",
+ getText(String.format(locatorTemplate, "notNullString")));
+ assertEquals("Simple Not Null Property may not be null",
+ getText(String.format(locatorTemplate, "simpleNotNullProperty")));
+ assertEquals("Min Value must be greater than or equal to 6",
+ getText(String.format(locatorTemplate, "minValue")));
+
+ }
+
protected final void assertBubbleMessage(String fieldId, String expected)
{
String popupId = fieldId + "_errorpopup";
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/4a5b8fc6/tapestry-beanvalidator/src/test/java/org/example/testapp/entities/ComplexBean.java
----------------------------------------------------------------------
diff --git a/tapestry-beanvalidator/src/test/java/org/example/testapp/entities/ComplexBean.java b/tapestry-beanvalidator/src/test/java/org/example/testapp/entities/ComplexBean.java
index beaa840..44af90d 100644
--- a/tapestry-beanvalidator/src/test/java/org/example/testapp/entities/ComplexBean.java
+++ b/tapestry-beanvalidator/src/test/java/org/example/testapp/entities/ComplexBean.java
@@ -1,10 +1,13 @@
package org.example.testapp.entities;
+import javax.validation.Valid;
import javax.validation.constraints.NotNull;
public class ComplexBean
{
+ @Valid
+ private SomeSimpleBean otherSimpleBean;
private SomeSimpleBean someSimpleBean;
private SomeOtherSimpleBean someOtherSimpleBean;
@@ -41,4 +44,14 @@ public class ComplexBean
this.simpleNotNullProperty = simpleNotNullProperty;
}
+ public SomeSimpleBean getOtherSimpleBean()
+ {
+ return otherSimpleBean;
+ }
+
+ public void setOtherSimpleBean(SomeSimpleBean otherSimpleBean)
+ {
+ this.otherSimpleBean = otherSimpleBean;
+ }
+
}
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/4a5b8fc6/tapestry-beanvalidator/src/test/java/org/example/testapp/pages/NestedObjectDemo.java
----------------------------------------------------------------------
diff --git a/tapestry-beanvalidator/src/test/java/org/example/testapp/pages/NestedObjectDemo.java b/tapestry-beanvalidator/src/test/java/org/example/testapp/pages/NestedObjectDemo.java
new file mode 100644
index 0000000..f6406bd
--- /dev/null
+++ b/tapestry-beanvalidator/src/test/java/org/example/testapp/pages/NestedObjectDemo.java
@@ -0,0 +1,38 @@
+package org.example.testapp.pages;
+
+import org.apache.tapestry5.alerts.AlertManager;
+import org.apache.tapestry5.alerts.Duration;
+import org.apache.tapestry5.alerts.Severity;
+import org.apache.tapestry5.annotations.Persist;
+import org.apache.tapestry5.annotations.Property;
+import org.apache.tapestry5.ioc.annotations.Inject;
+import org.example.testapp.entities.ComplexBean;
+import org.example.testapp.entities.SomeSimpleBean;
+
+public class NestedObjectDemo
+{
+
+ @Property
+ @Persist
+ private ComplexBean complexBean;
+
+ @Property
+ @Persist
+ private String notNullString;
+
+ @Inject
+ private AlertManager alertManager;
+
+ public void onActivate() {
+ if (complexBean == null) {
+ complexBean = new ComplexBean();
+ SomeSimpleBean otherSimpleBean = new SomeSimpleBean();
+ complexBean.setOtherSimpleBean(otherSimpleBean);
+ }
+ }
+
+ void onSuccess() {
+ alertManager.alert(Duration.TRANSIENT, Severity.SUCCESS, "Validation passed");
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/4a5b8fc6/tapestry-beanvalidator/src/test/java/org/example/testapp/services/AppModule.java
----------------------------------------------------------------------
diff --git a/tapestry-beanvalidator/src/test/java/org/example/testapp/services/AppModule.java b/tapestry-beanvalidator/src/test/java/org/example/testapp/services/AppModule.java
index 446d217..d8905b3 100644
--- a/tapestry-beanvalidator/src/test/java/org/example/testapp/services/AppModule.java
+++ b/tapestry-beanvalidator/src/test/java/org/example/testapp/services/AppModule.java
@@ -28,6 +28,7 @@ public class AppModule
public static void contributeApplicationDefaults(MappedConfiguration<String, String> configuration)
{
configuration.add(SymbolConstants.PRODUCTION_MODE, "false");
+ configuration.add(SymbolConstants.HMAC_PASSPHRASE, "u93490jhsprf2904rh29-3uj");
}
public static void contributeBeanValidatorSource(
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/4a5b8fc6/tapestry-beanvalidator/src/test/webapp/Index.tml
----------------------------------------------------------------------
diff --git a/tapestry-beanvalidator/src/test/webapp/Index.tml b/tapestry-beanvalidator/src/test/webapp/Index.tml
index 0970c96..6734533 100644
--- a/tapestry-beanvalidator/src/test/webapp/Index.tml
+++ b/tapestry-beanvalidator/src/test/webapp/Index.tml
@@ -27,6 +27,9 @@
<li>
<t:pagelink page="ComplexBeanDemo">ComplexBean Demo</t:pagelink>
</li>
+ <li>
+ <t:pagelink page="NestedObjectDemo">NestedObject Demo</t:pagelink>
+ </li>
</ul>
</body>
</html>
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/4a5b8fc6/tapestry-beanvalidator/src/test/webapp/NestedObjectDemo.tml
----------------------------------------------------------------------
diff --git a/tapestry-beanvalidator/src/test/webapp/NestedObjectDemo.tml b/tapestry-beanvalidator/src/test/webapp/NestedObjectDemo.tml
new file mode 100644
index 0000000..cfe9371
--- /dev/null
+++ b/tapestry-beanvalidator/src/test/webapp/NestedObjectDemo.tml
@@ -0,0 +1,22 @@
+<html xmlns:t="http://tapestry.apache.org/schema/tapestry_5_1_0.xsd">
+ <body>
+ <t:alerts/>
+ <t:form clientValidation="none" validate="complexBean">
+ <t:errors/>
+ <div class="t-beaneditor-row">
+ <t:label for="notNullString"/>
+ <t:textfield t:id="notNullString" t:validate="required"/>
+ </div>
+ <div class="t-beaneditor-row">
+ <t:label for="simpleNotNullProperty"/>
+ <t:textfield t:id="simpleNotNullProperty" t:value="complexBean.simpleNotNullProperty"/>
+ </div>
+ <div class="t-beaneditor-row">
+ <t:label for="minValue"/>
+ <t:textfield t:id="minValue" t:value="complexBean.otherSimpleBean.minValue"/>
+ </div>
+<!-- <t:beaneditor object="complexBean"/> -->
+ <input type="submit" id="submit" value="Go"/>
+ </t:form>
+ </body>
+</html>
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/4a5b8fc6/tapestry-core/src/main/java/org/apache/tapestry5/internal/bindings/PropBinding.java
----------------------------------------------------------------------
diff --git a/tapestry-core/src/main/java/org/apache/tapestry5/internal/bindings/PropBinding.java b/tapestry-core/src/main/java/org/apache/tapestry5/internal/bindings/PropBinding.java
index 4656fe2..0e7e097 100644
--- a/tapestry-core/src/main/java/org/apache/tapestry5/internal/bindings/PropBinding.java
+++ b/tapestry-core/src/main/java/org/apache/tapestry5/internal/bindings/PropBinding.java
@@ -35,14 +35,16 @@ public class PropBinding extends AbstractBinding implements InternalPropBinding
private final String toString;
private boolean invariant;
+
+ private final String expression;
- public PropBinding(final Location location, final Object root, final PropertyConduit conduit, final String toString
- )
+ public PropBinding(final Location location, final Object root, final PropertyConduit conduit, final String expression, final String toString)
{
super(location);
this.root = root;
this.conduit = conduit;
+ this.expression = expression;
this.toString = toString;
invariant = conduit.getAnnotation(Invariant.class) != null;
@@ -109,4 +111,10 @@ public class PropBinding extends AbstractBinding implements InternalPropBinding
{
return TapestryInternalUtils.toInternalPropertyConduit(conduit).getPropertyName();
}
+
+ public String getExpression()
+ {
+ return expression;
+ }
+
}
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/4a5b8fc6/tapestry-core/src/main/java/org/apache/tapestry5/internal/bindings/PropBindingFactory.java
----------------------------------------------------------------------
diff --git a/tapestry-core/src/main/java/org/apache/tapestry5/internal/bindings/PropBindingFactory.java b/tapestry-core/src/main/java/org/apache/tapestry5/internal/bindings/PropBindingFactory.java
index 2865808..4f65bac 100644
--- a/tapestry-core/src/main/java/org/apache/tapestry5/internal/bindings/PropBindingFactory.java
+++ b/tapestry-core/src/main/java/org/apache/tapestry5/internal/bindings/PropBindingFactory.java
@@ -51,6 +51,6 @@ public class PropBindingFactory implements BindingFactory
String toString = interner.format("PropBinding[%s %s(%s)]", description, container
.getCompleteId(), expression);
- return new PropBinding(location, target, conduit, toString);
+ return new PropBinding(location, target, conduit, expression, toString);
}
}
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/4a5b8fc6/tapestry-core/src/main/java/org/apache/tapestry5/internal/structure/InternalComponentResourcesImpl.java
----------------------------------------------------------------------
diff --git a/tapestry-core/src/main/java/org/apache/tapestry5/internal/structure/InternalComponentResourcesImpl.java b/tapestry-core/src/main/java/org/apache/tapestry5/internal/structure/InternalComponentResourcesImpl.java
index 78cdd07..39defda 100644
--- a/tapestry-core/src/main/java/org/apache/tapestry5/internal/structure/InternalComponentResourcesImpl.java
+++ b/tapestry-core/src/main/java/org/apache/tapestry5/internal/structure/InternalComponentResourcesImpl.java
@@ -18,6 +18,7 @@ import org.apache.tapestry5.*;
import org.apache.tapestry5.func.Worker;
import org.apache.tapestry5.internal.InternalComponentResources;
import org.apache.tapestry5.internal.bindings.InternalPropBinding;
+import org.apache.tapestry5.internal.bindings.PropBinding;
import org.apache.tapestry5.internal.services.Instantiator;
import org.apache.tapestry5.internal.transform.ParameterConduit;
import org.apache.tapestry5.internal.util.NamedSet;
@@ -668,6 +669,12 @@ public class InternalComponentResourcesImpl extends LockSupport implements Inter
return null;
}
+ // TAP5-1718: we need the full prop binding expression, not just the (final) property name
+ if (binding instanceof PropBinding)
+ {
+ return ((PropBinding) binding).getExpression();
+ }
+
if (binding instanceof InternalPropBinding)
{
return ((InternalPropBinding) binding).getPropertyName();