You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tapestry.apache.org by hl...@apache.org on 2012/12/15 03:12:56 UTC
[2/6] git commit: Recode the tapestry-beanvalidator client-side
support
Recode the tapestry-beanvalidator client-side support
Project: http://git-wip-us.apache.org/repos/asf/tapestry-5/repo
Commit: http://git-wip-us.apache.org/repos/asf/tapestry-5/commit/d9adc77f
Tree: http://git-wip-us.apache.org/repos/asf/tapestry-5/tree/d9adc77f
Diff: http://git-wip-us.apache.org/repos/asf/tapestry-5/diff/d9adc77f
Branch: refs/heads/5.4-js-rewrite
Commit: d9adc77fd8fc0046bf9be3dace6889e17c79b128
Parents: 395d034
Author: Howard M. Lewis Ship <hl...@apache.org>
Authored: Fri Dec 14 17:57:53 2012 -0800
Committer: Howard M. Lewis Ship <hl...@apache.org>
Committed: Fri Dec 14 17:57:53 2012 -0800
----------------------------------------------------------------------
tapestry-beanvalidator/build.gradle | 27 +-
.../modules/beanvalidator/validation.coffee | 67 +++
.../beanvalidator/BeanValidatorModule.java | 115 ++++--
.../beanvalidator/ClientConstraintDescriptor.java | 80 ++---
.../ClientConstraintDescriptorSource.java | 21 +-
.../tapestry5/internal/beanvalidator/BaseCCD.java | 66 +++
.../internal/beanvalidator/BeanFieldValidator.java | 312 ++++++++-------
.../ClientConstraintDescriptorImpl.java | 50 ++--
.../beanvalidator/tapestry-beanvalidator.js | 64 ---
.../TapestryBeanValidationIntegrationTests.java | 30 +-
.../testapp/pages/BeanEditFormValidationDemo.java | 2 +
.../testapp/pages/ClientValidationDemo.java | 2 +
.../testapp/pages/FormClientValidationDemo.java | 11 +-
.../example/testapp/pages/FormValidationDemo.java | 9 +
.../test/java/org/example/testapp/pages/Index.java | 3 +
.../example/testapp/pages/InjectValidatorDemo.java | 2 +
.../org/example/testapp/pages/OnPrepareDemo.java | 2 +
.../src/test/webapp/FormClientValidationDemo.tml | 56 ++--
.../src/test/webapp/FormValidationDemo.tml | 64 ++--
19 files changed, 581 insertions(+), 402 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/d9adc77f/tapestry-beanvalidator/build.gradle
----------------------------------------------------------------------
diff --git a/tapestry-beanvalidator/build.gradle b/tapestry-beanvalidator/build.gradle
index bf57826..a72108b 100644
--- a/tapestry-beanvalidator/build.gradle
+++ b/tapestry-beanvalidator/build.gradle
@@ -1,3 +1,5 @@
+import t5build.*
+
description = "Support for JSR-303 Bean Validation via the Hibernate validator implementation"
dependencies {
@@ -9,8 +11,25 @@ dependencies {
testCompile project(':tapestry-test')
}
-jar {
- manifest {
- attributes 'Tapestry-Module-Classes': 'org.apache.tapestry5.beanvalidator.BeanValidatorModule'
+task compileCoffeeScript(type: CompileCoffeeScript) {
+ outputDir "build/compiled-coffeescript"
+}
+
+processResources {
+ from compileCoffeeScript
+}
+
+idea.module {
+ sourceDirs += compileCoffeeScript.srcDir
+ sourceDirs += compileCoffeeScript.outputDir
+
+ // Hack the IML so that "build" is not excluded; necessary because several directories under build
+ // are added as source, resources, or test folders.
+ iml.whenMerged { module ->
+ module.excludeFolders.removeAll {
+ it.canonicalUrl.endsWith "/build"
+ }
}
-}
\ No newline at end of file
+}
+
+jar.manifest.attributes 'Tapestry-Module-Classes': 'org.apache.tapestry5.beanvalidator.BeanValidatorModule'
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/d9adc77f/tapestry-beanvalidator/src/main/coffeescript/META-INF/modules/beanvalidator/validation.coffee
----------------------------------------------------------------------
diff --git a/tapestry-beanvalidator/src/main/coffeescript/META-INF/modules/beanvalidator/validation.coffee b/tapestry-beanvalidator/src/main/coffeescript/META-INF/modules/beanvalidator/validation.coffee
new file mode 100644
index 0000000..b8eebf7
--- /dev/null
+++ b/tapestry-beanvalidator/src/main/coffeescript/META-INF/modules/beanvalidator/validation.coffee
@@ -0,0 +1,67 @@
+# Copyright 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.
+# 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.
+
+# ##beanvalidator/validation
+#
+# Supports extra validations related to the beanvalidator module.
+define ["_", "core/dom", "core/events", "core/utils", "core/validation"],
+ (_, dom, events, utils) ->
+
+ rangeValue = (element, attribute, defaultValue) ->
+ v = element.attribute attribute
+ if v is null
+ defaultValue
+ else
+ parseInt v
+
+ countOptions = (e) ->
+ # A select that is used as part of a palette is different; the validation attributes
+ # are attached to the selected (right side) <select>, and anything there counts as part
+ # of the selection.
+ if e.findContainer ".t-palette"
+ e.element.options.length
+ else
+ # An ordinary <select> may have multiple options (the clumsy control-click way)
+ _.filter(e.element.options, (o) -> o.selected).length
+
+ doRangeValidate = (element, value, memo) ->
+ min = rangeValue element, "data-range-min", 0
+ max = rangeValue element, "data-range-max", Number.MAX_VALUE
+
+ # If the translated value is still a string, and not a number, then the
+ # size refers to the length of the string, not its numeric value.
+ if _.isString value
+ value = value.length
+
+ unless min <= value <= max
+ memo.error = (element.attribute "data-range-message") or "RANGE ERROR"
+ return false
+
+ return true
+
+ dom.onDocument events.field.optional, "[data-optionality=prohibited]", (event, memo) ->
+
+ unless utils.isBlank memo.value
+ memo.error = (this.attribute "data-prohibited-message") or "PROHIBITED"
+ return false
+
+ return true
+
+ dom.onDocument events.field.validate, "input[data-range-min], input[data-range-max], textarea[data-range-min], textarea[data-range-max]", (event, memo) ->
+ doRangeValidate this, memo.translated, memo
+
+ dom.onDocument events.field.validate, "select[data-range-min], select[data-range-max]", (event, memo) ->
+ doRangeValidate this, (countOptions this), memo
+
+ return
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/d9adc77f/tapestry-beanvalidator/src/main/java/org/apache/tapestry5/beanvalidator/BeanValidatorModule.java
----------------------------------------------------------------------
diff --git a/tapestry-beanvalidator/src/main/java/org/apache/tapestry5/beanvalidator/BeanValidatorModule.java b/tapestry-beanvalidator/src/main/java/org/apache/tapestry5/beanvalidator/BeanValidatorModule.java
index 16a39eb..ce75c93 100644
--- a/tapestry-beanvalidator/src/main/java/org/apache/tapestry5/beanvalidator/BeanValidatorModule.java
+++ b/tapestry-beanvalidator/src/main/java/org/apache/tapestry5/beanvalidator/BeanValidatorModule.java
@@ -1,4 +1,4 @@
-// Copyright 2009, 2010, 2011 The Apache Software Foundation
+// Copyright 2009, 2010, 2011, 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,7 +13,6 @@
// limitations under the License.
package org.apache.tapestry5.beanvalidator;
-import org.apache.tapestry5.Asset;
import org.apache.tapestry5.MarkupWriter;
import org.apache.tapestry5.internal.beanvalidator.*;
import org.apache.tapestry5.ioc.Configuration;
@@ -23,7 +22,8 @@ import org.apache.tapestry5.ioc.ServiceBinder;
import org.apache.tapestry5.ioc.annotations.Local;
import org.apache.tapestry5.ioc.services.PropertyShadowBuilder;
import org.apache.tapestry5.ioc.services.ThreadLocale;
-import org.apache.tapestry5.services.*;
+import org.apache.tapestry5.services.FieldValidatorDefaultSource;
+import org.apache.tapestry5.services.javascript.DataConstants;
import org.apache.tapestry5.services.javascript.JavaScriptSupport;
import javax.validation.MessageInterpolator;
@@ -31,6 +31,7 @@ import javax.validation.Validator;
import javax.validation.ValidatorFactory;
import javax.validation.constraints.*;
import javax.validation.groups.Default;
+import java.util.Map;
/**
* Module for JSR-303 services.
@@ -85,44 +86,100 @@ public class BeanValidatorModule
});
}
- public static void contributeClientConstraintDescriptorSource(
- final Configuration<ClientConstraintDescriptor> configuration)
+ public static void contributeClientConstraintDescriptorSource(final JavaScriptSupport javaScriptSupport,
+ final Configuration<ClientConstraintDescriptor> configuration)
{
- configuration.add(new ClientConstraintDescriptor(Max.class, "maxnumber", "value"));
- configuration.add(new ClientConstraintDescriptor(Min.class, "minnumber", "value"));
- configuration.add(new ClientConstraintDescriptor(NotNull.class, "notnull"));
- configuration.add(new ClientConstraintDescriptor(Null.class, "isnull"));
- configuration.add(new ClientConstraintDescriptor(Pattern.class, "pattern", "regexp"));
- configuration.add(new ClientConstraintDescriptor(Size.class, "size", "min", "max"));
- }
+ configuration.add(new BaseCCD(Max.class, "value")
+ {
+ @Override
+ public void applyClientValidation(MarkupWriter writer, String message, Map<String, Object> attributes)
+ {
+ javaScriptSupport.require("core/validation");
+ writer.attributes(
+ "data-validate", true,
+ "data-validate-max", attributes.get("value"),
+ "data-max-message", message);
- public void contributeMarkupRenderer(
- OrderedConfiguration<MarkupRendererFilter> configuration,
+ }
+ });
- final AssetSource assetSource,
+ configuration.add(new BaseCCD(Min.class, "value")
+ {
+ @Override
+ public void applyClientValidation(MarkupWriter writer, String message, Map<String, Object> attributes)
+ {
+ javaScriptSupport.require("core/validation");
+ writer.attributes(
+ DataConstants.VALIDATION_ATTRIBUTE, true,
+ "data-validate-min", attributes.get("value"),
+ "data-min-message", message);
- final ThreadLocale threadLocale,
+ }
+ });
- final Environment environment)
- {
- MarkupRendererFilter injectBeanValidatorScript = new MarkupRendererFilter()
+ configuration.add(new BaseCCD(NotNull.class)
{
- public void renderMarkup(MarkupWriter writer, MarkupRenderer renderer)
+ @Override
+ public void applyClientValidation(MarkupWriter writer, String message, Map<String, Object> attributes)
{
+ javaScriptSupport.require("core/validation");
+ writer.attributes(
+ DataConstants.VALIDATION_ATTRIBUTE, true,
+ "data-optionality", "required",
+ "data-required-message", message);
+ }
+ });
- JavaScriptSupport javaScriptSupport = environment.peek(JavaScriptSupport.class);
+ configuration.add(new BaseCCD(Null.class)
+ {
+ @Override
+ public void applyClientValidation(MarkupWriter writer, String message, Map<String, Object> attributes)
+ {
+ javaScriptSupport.require("beanvalidator/validation");
+ writer.attributes(
+ DataConstants.VALIDATION_ATTRIBUTE, true,
+ "data-optionality", "prohibited",
+ "data-prohibited-message", message);
+ }
+ });
- Asset validators = assetSource.getAsset(null, "org/apache/tapestry5/beanvalidator/tapestry-beanvalidator.js",
- threadLocale.getLocale());
+ configuration.add(new BaseCCD(Pattern.class, "regexp")
+ {
+ @Override
+ public void applyClientValidation(MarkupWriter writer, String message, Map<String, Object> attributes)
+ {
+ javaScriptSupport.require("core/validation");
+ writer.attributes(
+ DataConstants.VALIDATION_ATTRIBUTE, true,
+ "data-validate-regexp", attributes.get("regexp"),
+ "data-regexp-message", message);
+ }
+ });
- javaScriptSupport.importJavaScriptLibrary(validators);
+ configuration.add(new BaseCCD(Size.class, "min", "max")
+ {
+ @Override
+ public void applyClientValidation(MarkupWriter writer, String message, Map<String, Object> attributes)
+ {
+ javaScriptSupport.require("beanvalidator/validation");
+ writer.attributes(
+ DataConstants.VALIDATION_ATTRIBUTE, true,
+ "data-range-message", message);
- renderer.renderMarkup(writer);
- }
- };
+ int min = (Integer) attributes.get("min");
+ if (min != 0)
+ {
+ writer.attributes("data-range-min", min);
+ }
- configuration.add("BeanValidatorScript", injectBeanValidatorScript, "after:*");
- }
+ int max = (Integer) attributes.get("max");
+ if (max != Integer.MAX_VALUE)
+ {
+ writer.attributes("data-range-max", max);
+ }
+ }
+ });
+ }
}
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/d9adc77f/tapestry-beanvalidator/src/main/java/org/apache/tapestry5/beanvalidator/ClientConstraintDescriptor.java
----------------------------------------------------------------------
diff --git a/tapestry-beanvalidator/src/main/java/org/apache/tapestry5/beanvalidator/ClientConstraintDescriptor.java b/tapestry-beanvalidator/src/main/java/org/apache/tapestry5/beanvalidator/ClientConstraintDescriptor.java
index 34110bf..3e6e813 100644
--- a/tapestry-beanvalidator/src/main/java/org/apache/tapestry5/beanvalidator/ClientConstraintDescriptor.java
+++ b/tapestry-beanvalidator/src/main/java/org/apache/tapestry5/beanvalidator/ClientConstraintDescriptor.java
@@ -1,72 +1,50 @@
-// Copyright 2009 The Apache Software Foundation
+// Copyright 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.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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.apache.tapestry5.beanvalidator;
-import static org.apache.tapestry5.ioc.internal.util.CollectionFactory.newSet;
+import org.apache.tapestry5.MarkupWriter;
+import java.util.Map;
import java.util.Set;
-import org.apache.tapestry5.json.JSONObject;
-
/**
- * Describes a single client-side constraint.
- *
+ * Applies client-side validation constraints based on a particular JSR 303 annotation.
+ * <p/>
+ * Note: converted from a final class to an interface as part of 5.4.
*/
-public final class ClientConstraintDescriptor
+public interface ClientConstraintDescriptor
{
- private final Class annotationClass;
- private final String validatorName;
- private final Set<String> attributes;
-
- /**
- * Creates a {@link ClientConstraintDescriptor}.
- *
- * @param annotationClass Type of the constraint annotation
- * @param validatorName Name of the client-side validator
- * @param attributes Attribute names of the constraint annotation to be passed (along with their values) to the JavaScript validator
- * function as an {@link JSONObject}.
- */
- public ClientConstraintDescriptor(final Class annotationClass,
- final String validatorName, final String... attributes)
- {
- this.annotationClass = annotationClass;
- this.validatorName = validatorName;
- this.attributes = newSet(attributes);
- }
-
- /**
- * Returns the annotation describing the constraint declaration.
- */
- public Class getAnnotationClass()
- {
- return this.annotationClass;
- }
+ /**
+ * The annotation class that drives this descriptor.
+ */
+ Class getAnnotationClass();
- /**
- * Returns the name of the client-side validator.
- */
- public String getValidatorName()
- {
- return this.validatorName;
- }
+ /**
+ * Names of attributes from the {@link javax.validation.metadata.ConstraintDescriptor} that are relevant.
+ */
+ Set<String> getAttributes();
- /**
- * Attribute names of the constraint annotation to be passed (along with their values) to the JavaScript validator
- * function as an {@link JSONObject}.
- */
- public Set<String> getAttributes()
- {
- return this.attributes;
- }
-}
\ No newline at end of file
+ /**
+ * Applies the validation
+ *
+ * @param writer
+ * used to write new attributes into the HTML tag for the user interface element
+ * @param message
+ * error message to present to user when the constraint is violated
+ * @param attributes
+ * {@linkplain #getAttributes()} selected attributes} from the {@link javax.validation.metadata.ConstraintDescriptor}
+ */
+ void applyClientValidation(MarkupWriter writer, String message, Map<String, Object> attributes);
+}
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/d9adc77f/tapestry-beanvalidator/src/main/java/org/apache/tapestry5/beanvalidator/ClientConstraintDescriptorSource.java
----------------------------------------------------------------------
diff --git a/tapestry-beanvalidator/src/main/java/org/apache/tapestry5/beanvalidator/ClientConstraintDescriptorSource.java b/tapestry-beanvalidator/src/main/java/org/apache/tapestry5/beanvalidator/ClientConstraintDescriptorSource.java
index 1bc522a..6eadf2a 100644
--- a/tapestry-beanvalidator/src/main/java/org/apache/tapestry5/beanvalidator/ClientConstraintDescriptorSource.java
+++ b/tapestry-beanvalidator/src/main/java/org/apache/tapestry5/beanvalidator/ClientConstraintDescriptorSource.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,19 +13,20 @@
// limitations under the License.
package org.apache.tapestry5.beanvalidator;
+import org.apache.tapestry5.internal.beanvalidator.BaseCCD;
import org.apache.tapestry5.ioc.annotations.UsesConfiguration;
/**
* Source for {@link ClientConstraintDescriptor}.
- *
*/
-@UsesConfiguration(ClientConstraintDescriptor.class)
-public interface ClientConstraintDescriptorSource
+@UsesConfiguration(BaseCCD.class)
+public interface ClientConstraintDescriptorSource
{
- /**
- * Return a {@link ClientConstraintDescriptor} for a constraint annotation or null.
- *
- * @param annotationClass type of the constraint annotation
- */
- ClientConstraintDescriptor getConstraintDescriptor(Class annotationClass);
+ /**
+ * Return a {@link ClientConstraintDescriptor} for a constraint annotation or null if not found.
+ *
+ * @param annotationClass
+ * type of the constraint annotation
+ */
+ ClientConstraintDescriptor getConstraintDescriptor(Class annotationClass);
}
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/d9adc77f/tapestry-beanvalidator/src/main/java/org/apache/tapestry5/internal/beanvalidator/BaseCCD.java
----------------------------------------------------------------------
diff --git a/tapestry-beanvalidator/src/main/java/org/apache/tapestry5/internal/beanvalidator/BaseCCD.java b/tapestry-beanvalidator/src/main/java/org/apache/tapestry5/internal/beanvalidator/BaseCCD.java
new file mode 100644
index 0000000..78ed0de
--- /dev/null
+++ b/tapestry-beanvalidator/src/main/java/org/apache/tapestry5/internal/beanvalidator/BaseCCD.java
@@ -0,0 +1,66 @@
+// Copyright 2009 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
+//
+// 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.apache.tapestry5.internal.beanvalidator;
+
+import org.apache.tapestry5.beanvalidator.ClientConstraintDescriptor;
+import org.apache.tapestry5.json.JSONObject;
+
+import java.util.Set;
+
+import static org.apache.tapestry5.ioc.internal.util.CollectionFactory.newSet;
+
+/**
+ * Describes a single client-side constraint.
+ */
+public abstract class BaseCCD implements ClientConstraintDescriptor
+{
+ private final Class annotationClass;
+
+ private final Set<String> attributes;
+
+ /**
+ * Creates a {@link BaseCCD}.
+ *
+ * @param annotationClass
+ * Type of the constraint annotation
+ * @param attributes
+ * Attribute names of the constraint annotation to be passed (along with their values) to the JavaScript validator
+ * function as an {@link JSONObject}.
+ */
+ public BaseCCD(Class annotationClass, String... attributes)
+ {
+ this.annotationClass = annotationClass;
+ this.attributes = newSet(attributes);
+ }
+
+ /**
+ * Returns the annotation describing the constraint declaration.
+ */
+ @Override
+ public Class getAnnotationClass()
+ {
+ return annotationClass;
+ }
+
+
+ /**
+ * Attribute names of the constraint annotation to be passed (along with their values) to the JavaScript validator
+ * function as an {@link JSONObject}.
+ */
+ @Override
+ public Set<String> getAttributes()
+ {
+ return attributes;
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/d9adc77f/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..81149d7 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,175 @@ 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.json.JSONObject;
+import org.apache.tapestry5.ioc.internal.util.CollectionFactory;
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));
+
+ 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));
}
-
- 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()
+ attributes.put(attribute, object);
+ }
+
+ clientConstraintDescriptor.applyClientValidation(writer, message, attributes);
+ }
+ }
+
+ @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()
{
- return descriptor;
+ return descriptor;
}
- public Object getValidatedValue()
+ public Object getValidatedValue()
{
- return null;
+ return null;
}
});
- }
+ }
}
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/d9adc77f/tapestry-beanvalidator/src/main/java/org/apache/tapestry5/internal/beanvalidator/ClientConstraintDescriptorImpl.java
----------------------------------------------------------------------
diff --git a/tapestry-beanvalidator/src/main/java/org/apache/tapestry5/internal/beanvalidator/ClientConstraintDescriptorImpl.java b/tapestry-beanvalidator/src/main/java/org/apache/tapestry5/internal/beanvalidator/ClientConstraintDescriptorImpl.java
index 4455ace..569bcaf 100644
--- a/tapestry-beanvalidator/src/main/java/org/apache/tapestry5/internal/beanvalidator/ClientConstraintDescriptorImpl.java
+++ b/tapestry-beanvalidator/src/main/java/org/apache/tapestry5/internal/beanvalidator/ClientConstraintDescriptorImpl.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,35 +13,35 @@
// limitations under the License.
package org.apache.tapestry5.internal.beanvalidator;
-import static org.apache.tapestry5.ioc.internal.util.CollectionFactory.newList;
+import org.apache.tapestry5.beanvalidator.ClientConstraintDescriptor;
+import org.apache.tapestry5.beanvalidator.ClientConstraintDescriptorSource;
import java.util.Collection;
-import org.apache.tapestry5.beanvalidator.ClientConstraintDescriptorSource;
-import org.apache.tapestry5.beanvalidator.ClientConstraintDescriptor;
+import static org.apache.tapestry5.ioc.internal.util.CollectionFactory.newList;
-public class ClientConstraintDescriptorImpl implements ClientConstraintDescriptorSource
+public class ClientConstraintDescriptorImpl implements ClientConstraintDescriptorSource
{
- private Collection<ClientConstraintDescriptor> descriptors = newList();
-
- public ClientConstraintDescriptorImpl(
- final Collection<ClientConstraintDescriptor> configuration)
- {
- super();
- this.descriptors = configuration;
- }
-
- public ClientConstraintDescriptor getConstraintDescriptor(final Class annotationClass)
- {
- for (final ClientConstraintDescriptor desc : this.descriptors)
- {
- if (desc.getAnnotationClass().equals(annotationClass))
- {
- return desc;
- }
- }
- return null;
- }
+ private Collection<ClientConstraintDescriptor> descriptors = newList();
+
+ public ClientConstraintDescriptorImpl(
+ final Collection<ClientConstraintDescriptor> configuration)
+ {
+ this.descriptors = configuration;
+ }
+
+ public ClientConstraintDescriptor getConstraintDescriptor(final Class annotationClass)
+ {
+ for (final ClientConstraintDescriptor desc : this.descriptors)
+ {
+ if (desc.getAnnotationClass().equals(annotationClass))
+ {
+ return desc;
+ }
+ }
+
+ return null;
+ }
}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/d9adc77f/tapestry-beanvalidator/src/main/resources/org/apache/tapestry5/beanvalidator/tapestry-beanvalidator.js
----------------------------------------------------------------------
diff --git a/tapestry-beanvalidator/src/main/resources/org/apache/tapestry5/beanvalidator/tapestry-beanvalidator.js b/tapestry-beanvalidator/src/main/resources/org/apache/tapestry5/beanvalidator/tapestry-beanvalidator.js
deleted file mode 100644
index 07a5bd5..0000000
--- a/tapestry-beanvalidator/src/main/resources/org/apache/tapestry5/beanvalidator/tapestry-beanvalidator.js
+++ /dev/null
@@ -1,64 +0,0 @@
-// 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
-//
-// 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.
-
-Tapestry.Validator.notnull = function(field, message, spec)
-{
- Tapestry.Validator.required(field, message);
-};
-
-Tapestry.Validator.isnull = function(field, message, spec)
-{
- field.addValidator(function(value)
- {
- if (value != null)
- throw message;
- });
-};
-
-Tapestry.Validator.maxnumber = function(field, message, spec)
-{
- Tapestry.Validator.max(field, message, spec.value);
-};
-
-Tapestry.Validator.minnumber = function(field, message, spec)
-{
- Tapestry.Validator.min(field, message, spec.value);
-};
-
-Tapestry.Validator.size = function(field, message, spec)
-{
- field.addValidator(function(value)
- {
- if (Object.isString(value))
- {
- if (value.length < spec.min) throw message;
- if (value.length > spec.max) throw message;
-
- }
- else if (Object.isArray(value))
- {
- if(this.tagName == "SELECT")
- {
- var selectedOptions = Element.childElements(this).size();
- if (selectedOptions < spec.min) throw message;
- if (selectedOptions > spec.max) throw message;
- }
- }
- });
-};
-
-Tapestry.Validator.pattern = function(field, message, spec)
-{
- Tapestry.Validator.regexp(field, message, spec.regexp);
-};
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/d9adc77f/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 0eb48dd..29b50bf 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
@@ -21,6 +21,10 @@ import org.testng.annotations.Test;
@TapestryTestConfiguration(webAppFolder = "src/test/webapp")
public class TapestryBeanValidationIntegrationTests extends SeleniumTestCase
{
+ public static final String AVAILABLE_OPTIONS = "css=.t-palette-available select";
+
+ public static final String SELECT_BUTTON = "css=.t-palette [data-action=select]";
+
@Test
public void form_validation() throws Exception
{
@@ -30,6 +34,8 @@ public class TapestryBeanValidationIntegrationTests extends SeleniumTestCase
clickAndWait(SUBMIT);
+ // waitForPageInitialized();
+
assertTextPresent("Login Name may not be null");
assertTextPresent("Secret Password may not be null");
assertTextPresent("Programming Languages size must be between 2 and 3");
@@ -40,9 +46,9 @@ public class TapestryBeanValidationIntegrationTests extends SeleniumTestCase
type("secretPassword", "igor");
- addSelection("programmingLanguages-avail", "label=Java");
- addSelection("programmingLanguages-avail", "label=Ruby");
- click("programmingLanguages-select");
+ addSelection(AVAILABLE_OPTIONS, "label=Java");
+ addSelection(AVAILABLE_OPTIONS, "label=Ruby");
+ click(SELECT_BUTTON);
select("favoriteColors", "label=Green");
@@ -106,10 +112,12 @@ public class TapestryBeanValidationIntegrationTests extends SeleniumTestCase
}
@Test
- public void client_validaton() throws Exception
+ public void client_validation() throws Exception
{
openLinks("Client Validation Demo");
+ waitForPageInitialized();
+
//@NotNull
click(SUBMIT);
@@ -146,14 +154,18 @@ public class TapestryBeanValidationIntegrationTests extends SeleniumTestCase
type("stringSizeValue", "ab");
- addSelection("languages-avail", "label=Java");
- click("languages-select");
+ click(SUBMIT);
+
+ // Have to select at least one value
+
+ addSelection(AVAILABLE_OPTIONS, "label=Ruby");
+ click(SELECT_BUTTON);
click(SUBMIT);
assertTextPresent("Languages size must be between 2 and 3");
- click(SUBMIT);
+ waitForPageInitialized();
assertTextPresent("Null Value must be null");
}
@@ -164,14 +176,16 @@ public class TapestryBeanValidationIntegrationTests extends SeleniumTestCase
{
openLinks("Form Client Validation Demo");
+ waitForPageInitialized();
+
click(SUBMIT);
assertTextPresent("Login Name may not be null");
assertTextPresent("Secret Password may not be null");
- assertTextPresent("Programming Languages may not be null");
assertTextPresent("Favorite Colors may not be null");
assertTextPresent("Birth Day may not be null");
+
type("loginName", "123");
click(SUBMIT);
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/d9adc77f/tapestry-beanvalidator/src/test/java/org/example/testapp/pages/BeanEditFormValidationDemo.java
----------------------------------------------------------------------
diff --git a/tapestry-beanvalidator/src/test/java/org/example/testapp/pages/BeanEditFormValidationDemo.java b/tapestry-beanvalidator/src/test/java/org/example/testapp/pages/BeanEditFormValidationDemo.java
index 1754c7a..00f71e7 100644
--- a/tapestry-beanvalidator/src/test/java/org/example/testapp/pages/BeanEditFormValidationDemo.java
+++ b/tapestry-beanvalidator/src/test/java/org/example/testapp/pages/BeanEditFormValidationDemo.java
@@ -13,10 +13,12 @@
// limitations under the License.
package org.example.testapp.pages;
+import org.apache.tapestry5.annotations.Import;
import org.apache.tapestry5.annotations.Persist;
import org.apache.tapestry5.annotations.Property;
import org.example.testapp.entities.User;
+@Import(stack = "core")
public class BeanEditFormValidationDemo
{
@Property
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/d9adc77f/tapestry-beanvalidator/src/test/java/org/example/testapp/pages/ClientValidationDemo.java
----------------------------------------------------------------------
diff --git a/tapestry-beanvalidator/src/test/java/org/example/testapp/pages/ClientValidationDemo.java b/tapestry-beanvalidator/src/test/java/org/example/testapp/pages/ClientValidationDemo.java
index 5a42c64..14d0de1 100644
--- a/tapestry-beanvalidator/src/test/java/org/example/testapp/pages/ClientValidationDemo.java
+++ b/tapestry-beanvalidator/src/test/java/org/example/testapp/pages/ClientValidationDemo.java
@@ -13,11 +13,13 @@
// limitations under the License.
package org.example.testapp.pages;
+import org.apache.tapestry5.annotations.Import;
import org.apache.tapestry5.annotations.Persist;
import org.apache.tapestry5.annotations.Property;
import org.apache.tapestry5.internal.services.StringValueEncoder;
import org.example.testapp.entities.TestEntity;
+@Import(stack = "core")
public class ClientValidationDemo
{
@Property
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/d9adc77f/tapestry-beanvalidator/src/test/java/org/example/testapp/pages/FormClientValidationDemo.java
----------------------------------------------------------------------
diff --git a/tapestry-beanvalidator/src/test/java/org/example/testapp/pages/FormClientValidationDemo.java b/tapestry-beanvalidator/src/test/java/org/example/testapp/pages/FormClientValidationDemo.java
index c157c5f..a5ed4ff 100644
--- a/tapestry-beanvalidator/src/test/java/org/example/testapp/pages/FormClientValidationDemo.java
+++ b/tapestry-beanvalidator/src/test/java/org/example/testapp/pages/FormClientValidationDemo.java
@@ -13,6 +13,7 @@
// limitations under the License.
package org.example.testapp.pages;
+import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
@@ -20,12 +21,14 @@ import javax.validation.constraints.NotNull;
import javax.validation.constraints.Pattern;
import javax.validation.constraints.Size;
+import org.apache.tapestry5.annotations.Import;
import org.apache.tapestry5.annotations.Persist;
import org.apache.tapestry5.annotations.Property;
import org.apache.tapestry5.beaneditor.Validate;
import org.apache.tapestry5.internal.services.StringValueEncoder;
import org.example.testapp.services.Foo;
+@Import(stack = "core")
public class FormClientValidationDemo
{
@NotNull(groups=Foo.class)
@@ -55,7 +58,13 @@ public class FormClientValidationDemo
@Property
@Persist
private Date date;
-
+
+ void onPrepare() {
+ if (languages == null) {
+ languages = new ArrayList<String>();
+ }
+ }
+
public StringValueEncoder getStringValueEncoder()
{
return new StringValueEncoder();
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/d9adc77f/tapestry-beanvalidator/src/test/java/org/example/testapp/pages/FormValidationDemo.java
----------------------------------------------------------------------
diff --git a/tapestry-beanvalidator/src/test/java/org/example/testapp/pages/FormValidationDemo.java b/tapestry-beanvalidator/src/test/java/org/example/testapp/pages/FormValidationDemo.java
index a5f2702..cb46348 100644
--- a/tapestry-beanvalidator/src/test/java/org/example/testapp/pages/FormValidationDemo.java
+++ b/tapestry-beanvalidator/src/test/java/org/example/testapp/pages/FormValidationDemo.java
@@ -13,6 +13,7 @@
// limitations under the License.
package org.example.testapp.pages;
+import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
@@ -20,12 +21,14 @@ import javax.validation.constraints.NotNull;
import javax.validation.constraints.Past;
import javax.validation.constraints.Size;
+import org.apache.tapestry5.annotations.Import;
import org.apache.tapestry5.annotations.Persist;
import org.apache.tapestry5.annotations.Property;
import org.apache.tapestry5.beaneditor.Validate;
import org.apache.tapestry5.internal.services.StringValueEncoder;
import org.example.testapp.services.Foo;
+@Import(stack = "core")
public class FormValidationDemo
{
@NotNull(groups=Foo.class)
@@ -62,6 +65,12 @@ public class FormValidationDemo
@Persist
private Date date;
+ public void onPrepare() {
+ if (languages == null) {
+ languages = new ArrayList<String>();
+ }
+ }
+
public StringValueEncoder getStringValueEncoder()
{
return new StringValueEncoder();
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/d9adc77f/tapestry-beanvalidator/src/test/java/org/example/testapp/pages/Index.java
----------------------------------------------------------------------
diff --git a/tapestry-beanvalidator/src/test/java/org/example/testapp/pages/Index.java b/tapestry-beanvalidator/src/test/java/org/example/testapp/pages/Index.java
index b8fb10d..307e9da 100644
--- a/tapestry-beanvalidator/src/test/java/org/example/testapp/pages/Index.java
+++ b/tapestry-beanvalidator/src/test/java/org/example/testapp/pages/Index.java
@@ -13,10 +13,13 @@
// limitations under the License.
package org.example.testapp.pages;
+import org.apache.tapestry5.annotations.Import;
+
/**
* Start page of the test app.
*
*/
+@Import(stack = "core")
public class Index
{
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/d9adc77f/tapestry-beanvalidator/src/test/java/org/example/testapp/pages/InjectValidatorDemo.java
----------------------------------------------------------------------
diff --git a/tapestry-beanvalidator/src/test/java/org/example/testapp/pages/InjectValidatorDemo.java b/tapestry-beanvalidator/src/test/java/org/example/testapp/pages/InjectValidatorDemo.java
index adae5bf..9808523 100644
--- a/tapestry-beanvalidator/src/test/java/org/example/testapp/pages/InjectValidatorDemo.java
+++ b/tapestry-beanvalidator/src/test/java/org/example/testapp/pages/InjectValidatorDemo.java
@@ -19,6 +19,7 @@ import javax.validation.ConstraintViolation;
import javax.validation.Validator;
import javax.validation.constraints.NotNull;
+import org.apache.tapestry5.annotations.Import;
import org.apache.tapestry5.annotations.InjectComponent;
import org.apache.tapestry5.annotations.Persist;
import org.apache.tapestry5.annotations.Property;
@@ -27,6 +28,7 @@ import org.apache.tapestry5.corelib.components.Form;
import org.apache.tapestry5.ioc.annotations.Inject;
import org.example.testapp.services.Bar;
+@Import(stack = "core")
public class InjectValidatorDemo
{
@NotNull(groups=Bar.class)
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/d9adc77f/tapestry-beanvalidator/src/test/java/org/example/testapp/pages/OnPrepareDemo.java
----------------------------------------------------------------------
diff --git a/tapestry-beanvalidator/src/test/java/org/example/testapp/pages/OnPrepareDemo.java b/tapestry-beanvalidator/src/test/java/org/example/testapp/pages/OnPrepareDemo.java
index 42510e0..1453645 100644
--- a/tapestry-beanvalidator/src/test/java/org/example/testapp/pages/OnPrepareDemo.java
+++ b/tapestry-beanvalidator/src/test/java/org/example/testapp/pages/OnPrepareDemo.java
@@ -13,9 +13,11 @@
// limitations under the License.
package org.example.testapp.pages;
+import org.apache.tapestry5.annotations.Import;
import org.apache.tapestry5.annotations.Property;
import org.example.testapp.entities.User;
+@Import(stack = "core")
public class OnPrepareDemo
{
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/d9adc77f/tapestry-beanvalidator/src/test/webapp/FormClientValidationDemo.tml
----------------------------------------------------------------------
diff --git a/tapestry-beanvalidator/src/test/webapp/FormClientValidationDemo.tml b/tapestry-beanvalidator/src/test/webapp/FormClientValidationDemo.tml
index 344246c..bdcce37 100644
--- a/tapestry-beanvalidator/src/test/webapp/FormClientValidationDemo.tml
+++ b/tapestry-beanvalidator/src/test/webapp/FormClientValidationDemo.tml
@@ -1,28 +1,32 @@
<html xmlns:t="http://tapestry.apache.org/schema/tapestry_5_1_0.xsd">
- <body>
- <t:form>
- <t:errors/>
-
- <br/>
-
- <t:textfield t:id="loginName" value="userName"/>
-
- <br/>
-
- <t:textfield t:id="secretPassword" value="password"/>
-
- <br/>
- <t:palette t:id="programmingLanguages" model="literal:Java,C,Ruby,Python,Perl" selected="languages" encoder="stringValueEncoder"/>
-
- <br/>
- <t:select t:id="favoriteColors" model="literal:Red,Green,Blue" value="color"/>
-
- <br/>
- <t:datefield t:id="birthDay" value="date" format="dd.MM.yyyy"/>
-
- <br/>
- <input type="submit" value="Go"/>
-
- </t:form>
- </body>
+<body>
+<div class="container">
+
+ <t:form>
+ <t:errors/>
+
+ <br/>
+
+ <t:textfield t:id="loginName" value="userName"/>
+
+ <br/>
+
+ <t:textfield t:id="secretPassword" value="password"/>
+
+ <br/>
+ <t:palette t:id="programmingLanguages" model="literal:Java,C,Ruby,Python,Perl" selected="languages"
+ encoder="stringValueEncoder"/>
+
+ <br/>
+ <t:select t:id="favoriteColors" model="literal:Red,Green,Blue" value="color"/>
+
+ <br/>
+ <t:datefield t:id="birthDay" value="date" format="dd.MM.yyyy"/>
+
+ <br/>
+ <input type="submit" value="Go"/>
+
+ </t:form>
+</div>
+</body>
</html>
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/d9adc77f/tapestry-beanvalidator/src/test/webapp/FormValidationDemo.tml
----------------------------------------------------------------------
diff --git a/tapestry-beanvalidator/src/test/webapp/FormValidationDemo.tml b/tapestry-beanvalidator/src/test/webapp/FormValidationDemo.tml
index 380283e..2701ea5 100644
--- a/tapestry-beanvalidator/src/test/webapp/FormValidationDemo.tml
+++ b/tapestry-beanvalidator/src/test/webapp/FormValidationDemo.tml
@@ -1,32 +1,36 @@
<html xmlns:t="http://tapestry.apache.org/schema/tapestry_5_1_0.xsd">
- <body>
- <t:form clientValidation="none">
- <t:errors/>
-
- <br/>
-
- <t:textfield t:id="loginName" value="userName"/>
-
- <br/>
-
- <t:textfield t:id="secretPassword" value="password"/>
-
- <br/>
- <t:palette t:id="programmingLanguages" model="literal:Java,C,Ruby,Python,Perl" selected="languages" encoder="stringValueEncoder"/>
-
- <br/>
- <t:select t:id="favoriteColors" model="literal:Red,Green,Blue" value="color"/>
-
- <br/>
- <label t:type="label" for="moreColors"/>
- <t:checklist t:id="moreColors" model="literal:White,Yellow,Orange,Pink" selected="moreColors" encoder="stringValueEncoder"/>
-
- <br/>
- <t:datefield t:id="birthDay" value="date" format="dd.MM.yyyy"/>
-
- <br/>
- <input type="submit" value="Go"/>
-
- </t:form>
- </body>
+<body>
+<div class="container">
+ <t:form clientValidation="none">
+ <t:errors/>
+
+ <br/>
+
+ <t:textfield t:id="loginName" value="userName"/>
+
+ <br/>
+
+ <t:textfield t:id="secretPassword" value="password"/>
+
+ <br/>
+ <t:palette t:id="programmingLanguages" model="literal:Java,C,Ruby,Python,Perl" selected="languages"
+ encoder="stringValueEncoder"/>
+
+ <br/>
+ <t:select t:id="favoriteColors" model="literal:Red,Green,Blue" value="color"/>
+
+ <br/>
+ <label t:type="label" for="moreColors"/>
+ <t:checklist t:id="moreColors" model="literal:White,Yellow,Orange,Pink" selected="moreColors"
+ encoder="stringValueEncoder"/>
+
+ <br/>
+ <t:datefield t:id="birthDay" value="date" format="dd.MM.yyyy"/>
+
+ <br/>
+ <input type="submit" value="Go"/>
+
+ </t:form>
+</div>
+</body>
</html>
\ No newline at end of file