How to create a custom validator in Play Framework 2.0?

后端 未结 1 578
轮回少年
轮回少年 2020-12-01 01:25

Play 1.0 comes with a full featured validation framework base on http://oval.sourceforge.net/.

With the release of 2.0, my custom validators do not work anymore.

相关标签:
1条回答
  • 2020-12-01 02:11

    In Play 2.0, the validation framework extends beyond the actual validation of the data as it reaches to:

    • Annotations - to easily declare validation contraints using the '@' sign
    • Validators - which actually implements to logic behind the validation
    • Messages - to display parametrized error messages (i18 compliant)
    • Finally, HTML helpers - that glue all the previous together

    The HTML Helpers are something new to Play 2.0. In 1.x, Play was already pretty good at enforcing a well defined validation framework. It was powerful and easy to use. Yet we still had to wire the HTML form and the validation framework together. This could be a little confusing to the beginner.

    With Play 2.0, this is now done automatically.

    But let's focus on the answer and provide some guidance: We will create an AllUpperCase validator, that generates an error either when:

    • the input is not a String
    • the input is empty
    • one of the characters is lower-case.

    The validator

    package myvalidators;
    
    import javax.validation.*;
    
    public class AllUpperCaseValidator 
            extends play.data.validation.Constraints.Validator<Object> 
            implements ConstraintValidator<AllUpperCase, Object> {
    
        /* Default error message */
        final static public String message = "error.alluppercase";
    
        /**
         * Validator init
         * Can be used to initialize the validation based on parameters
         * passed to the annotation.
         */
        public void initialize(AllUpperCase constraintAnnotation) {}
    
        /**
         * The validation itself
         */
        public boolean isValid(Object object) {
            if(object == null)
                return false;
    
            if(!(object instanceof String))
                return false;
    
            String s = object.toString();  
            for(char c : s.toCharArray()) {
                if(Character.isLetter(c) && Character.isLowerCase(c))
                    return false;
            }
    
            return true;
        }
    
        /**
         * Constructs a validator instance.
         */
        public static play.data.validation.Constraints.Validator<Object> alluppercase() {
            return new AllUpperCaseValidator();
        }
    }
    

    The first thing you may notice is the import: Play 2.0 indeed complies with JSR 303 - Bean Validation Framework. In this context, the validator needs to implement ConstraintValidator. Which in our case translates into the annotation as class AllUpperCase (which we will introduce in a minute) and T as a generic Object.

    The validator is straighforward:
    We defined the method public boolean isValid(Object object) that returns a boolean, if true the validation passed. There is also an message id and a method that instanciates the validator.

    The Annotation

    The class below defines an annotation named @AllUpperCase which takes no parameters but enforces the validation defined previously. Providing details related to the annotation framework is outside the scope of this post.

    package myvalidators;
    
    import java.lang.annotation.*;
    import static java.lang.annotation.ElementType.*;
    import static java.lang.annotation.RetentionPolicy.*;
    
    import javax.validation.*;
    
    @Target({FIELD})
    @Retention(RUNTIME)
    @Constraint(validatedBy = AllUpperCaseValidator.class)
    @play.data.Form.Display(name="constraint.alluppercase")
    public @interface AllUpperCase {
        String message() default AllUpperCaseValidator.message;
        Class<?>[] groups() default {};
        Class<? extends Payload>[] payload() default {};
    }
    

    Note how the anotation glues to the other pieces of the puzzle.

    • @Constraint, a JSR 303 annotation, links to the validator
    • @play.data.Form.Display, links the annotation to the play html helpers. Note that the name is important: we are defining a constraint named alluppercase. Play uses this information to call the method public static play.data.validation.Constraints.Validator<Object> alluppercase() on the Validator.
    • Finally note that the default message is set within the anotation interface.

    Usage

    We now have our custom validator and annotation

    import myvalidators.*;
    public static class MyData {
        @AllUpperCase
        public String name;
    }
    

    Describing the usage is outside the scope of this post, please find a working sample at this URL

    0 讨论(0)
提交回复
热议问题