...
Tapestry provides a powerful validation mechanism which is described here. Among other things this mechanism allows you to annotate your domain model classes with the @Validate annotation @Validate. This annotation is problematic if your domain model is used in non-Tapestry applications as well as in Tapestry applications. Your non-Tapestry application becomes dependent on tapestry5-annotations module. To make your domain model independent from Tapestry you can use the JSR 303: Bean Validation. This library provides integration between Tapestry and JSR-303.
...
Bootstraping the Bean Validator
The BeanValidatorSource service BeanValidatorSource is responsible for bootstrapping the Validator. You can contribute a BeanValidatorConfigurer to the configuration of this service in order to participate on the configuration of Validator.
Code Block | ||||
---|---|---|---|---|
| ||||
@Contribute(BeanValidatorSource.class) public static void provideBeanValidatorConfigurer(OrderedConfiguration<BeanValidatorConfigurer> configuration) { configuration.add("MyConfigurer", new BeanValidatorConfigurer() { public void configure(javax.validation.Configuration<?> configuration) { configuration.ignoreXmlConfiguration(); } }); } |
...
In JSR-303 validation groups are used you to define a subset of the constraints validated at a given time. If no validation group is specified the Default group is taken. By default, Tapestry passes only this group to Validator. You can tell Tapestry to pass more groups by contributing group classes into the configuration of the BeanValidatorSource service.
...
Code Block | ||||
---|---|---|---|---|
| ||||
public class Login
{
@NotNull
@Size(max=10)
@Pattern(regexp = "[a-zA-Z]*")
@Property @Persist
private String userName;
@NotNull
@Size(min=5, max=30)
@Property @Persist
private String password;
void onSuccess()
{
// Login the user here
}
} |
You can event even mix JSR-303 annotations and Tapestry's @Validate annotation.
Code Block | ||||
---|---|---|---|---|
| ||||
public class Login
{
@NotNull
@Validate("maxlength=10")
@Pattern(regexp = "[a-zA-Z]*")
@Property @Persist
private String userName;
@NotNull
@Validate("minlength=5,maxlength=30")
@Property @Persist
private String password;
void onSuccess()
{
// Login the user here
}
} |
Next you have to pass the object to validate into the Form's validate parameter validate. In the following example the Form's fields are bound to the properties of the Login page Login. That's why we pass this, thus the page instance, into the to the validate parameter validate.
Code Block | ||||
---|---|---|---|---|
| ||||
<html xmlns:t="http://tapestry.apache.org/schema/tapestry_5_1_0.xsd"> <body> <t:form validate="this"> <t:errors/> <p> <t:textfield t:id="userName"/> </p> <p> <t:textfield t:id="password"/> </p> <p> <input type="submit" value="Login"/> </p> <t:form> </body> </html> |
Since the validate parameter validate defaults to the container of the Form component, we could also remove validate="this" in the example above.
...
Code Block | ||||
---|---|---|---|---|
| ||||
public class User
{
@NotNull
private String userName;
@NotNull
@Validate("minlength=10")
private String password;
...
} |
...
Unfortunately JSR-303 doesn’t cover the client-side validation, so web frameworks supporting this JSR must provided still need to come up with proprietary client-side solutions. Tapestry provides client-side validation for the following JSR-303 constraints:
...
Code Block | ||||
---|---|---|---|---|
| ||||
@Documented @Constraint(validatedBy = RangeValidator.class) @Target({ METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER }) @Retention(RUNTIME) public @interface Range { long max() default Long.MAX_VALUE; long min() default Long.MIN_VALUE; String message() default "{com.acme.constraint.Range.message}"; Class[] groups() default {}; Class[] payload() default {}; } |
To provide client-side validation of a constraint you have to add a JavaScript function to the built-in object Tapestry.Validator JavaScript-object. The function should contain exactly three parameters:
...
Now you have to tell Tapestry to call the function Tapestry.Validator.range when client-side validation of @Range should be executed. This is accomplished by a contribution to the ClientConstraintDescriptorSource service ClientConstraintDescriptorSource. The configuration of this service is a collection of ClientConstraintDescriptor. Each ClientConstraintDescriptor represents a client-side validation constraint. The constructor of ClientConstraintDescriptor has three parameters:
...