Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Comment: fixed language param of code macro
Since
since5.2
 
Wiki Markup
{float:right|background=#eee}
{contentbylabel:title=Related Articles|showLabels=false|showSpace=false|space=TAPESTRY|labels=validation}
{float}

...

The BeanValidatorSource service 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
java
languagejava

@Contribute(BeanValidatorSource.class)
public static void provideBeanValidatorConfigurer(OrderedConfiguration<BeanValidatorConfigurer> configuration)
{
   configuration.add("MyConfigurer", new BeanValidatorConfigurer()
   {
      public void configure(javax.validation.Configuration<?> configuration)
      {
         configuration.ignoreXmlConfiguration();
      }
   });
}

...

Once you included this library and its dependencies into your web app, you may use the JSR-303 annotations to validate the user's input.

Code Block
java
languagejava

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 even mix JSR-303 annotations and Tapestry's @Validate annotation.

Code Block
java
languagejava

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. In the following example the Form's fields are bound to the properties of the Login page. That's why we pass this, thus the page instance, to the  validate parameter.

Code Block
xml
languagexml

<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>

...

If you use the BeanEditForm component it's even easier to validate your beans. The only thing you have to do is to annotate your beans with JSR-303 annotations. If you are migrating from Tapestry's built-in validation mechanism to JSR-303 Bean Validation, you don't have to change your template at all.

Code Block
java
languagejava

public class User
{
   @NotNull
   private String userName;

   @NotNull
   @Validate("minlength=10")
   private String password;

   ...
}

...

Now let's see how to provide own client-side validation for JSR-303 constraints. Imagine you created the following constraint definition. The server-side implementation of the constraint is implemented by RangeValidator. I suppose you are familiar with JSR-303, so I don’t explain how to implement RangeValidator.

Code Block
java
languagejava

@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 {};
}

...

Here is an example:

Code Block
javascript
languagejavascriptjs

Tapestry.Validator.range = function(field, message, spec) {
   field.addValidator(function(value) {
      if (value < spec.min || value > spec.max) {
         throw message;
      }
   });
};

...

The last step is to make the contribution, which links the @Range annotation with the JavaScript function range. The attributes max and min and their values are passed to the function.

Code Block
java
languagejava

@Contribute(ClientConstraintDescriptorSource.class)
public static void provideClientConstraintDescriptors(Configuration<ClientConstraintDescriptor> config) {

   config.add(new ClientConstraintDescriptor(Range.class, "range", "min", "max"));
}