Kontakt

Archive for Februar, 2010

Tapestry and JSR-303 Bean Validation API – Now with client-side validation

Freitag, Februar 26th, 2010

In this post I described the Tapestry/JSR-303 integration library. If you read this blog post you might remember a limitation: at that time the library didn’t support the client-side validation. The reason is that the JSR 303 doesn’t cover the client-side validation, so that most web frameworks supporting this JSR have to provide proprietary solutions.  Due to lack of time it took longer to add the missing feature but finally the client-side validation is supported.

Let’s have a look how to add 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.

@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. The function should contain exactly three parameters:

  1. Field being validated
  2. Validation message
  3. JSON object with values from the constraint annotation

Here is an example:

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

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

  1. Class of the constraint annotation
  2. Name of the JavaScript function
  3. The last parameter is a varargs. It is used to pass the attribute names of the constraint annotation to be passed (along with their values) to the JavaScript function as an JSON object.

In the following example the annotation @Range is associated with the JavaScript function range. The attributes max and min and their values are passed to the function.

public class AppModule {

   public static void contributeClientConstraintDescriptorSource(
      Configuration<ClientConstraintDescriptor> config) {

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

That’s it! Enjoy.

New Tapestry 5 article at JAXenter

Mittwoch, Februar 17th, 2010

JAXenter just published a new article on Tapestry 5 written by me. The article is in German and is a first part of an article series about Tapestry 5. If you read German and want to start with Tapestry, you should read it. Enjoy.

Tapestry 5 Blog - Copyright © 2009 - Eclectic Theme by Your Inspiration Web - Powered by WordPress