Search code examples
springvalidationspring-mvchibernate-validator

Spring validation vs Hibernate validation using annotation


i am creating a demo application using spring mvc 3.0.I have to apply the validation over the screen.I searches on the net and found that there is mainly 2 types of validation are used with the application :-

  1. Spring validations using validations Api
  2. Hibernate validation using hibernate validations

Hopefully somebody give me the suggestion which one is good one to implement in the application.


Solution

  • I used both - I like the Hibernate Validation more - pretty easy to implement and pretty standard. It is automatically enabled when you have an implementation on the classpath. Here is an example:

    @EmailValidator
    @NotBlank
    @Length(max=65)
    private String email; 
    

    Where does the message Error String comes from? In WEB-INF you must have a file called messages.properties :

    NotBlank.ForgotPasswordBackingObject.email=Email address must be present
    

    There is a standard @Email annotation, but an email such as : me@mycompany is considered valid, that is why I had to make my own @EmailValidator(changed a regex flag from * to + in the standard implementation). There are some issues that I came across : the order of validation - which validation you want to happen first, this is done with Validation groups, but this are not possible with the @Valid annotation, for example :

    @RequestMapping(method=RequestMethod.POST, value="/auth/changePassword")
    public ModelAndView submitChangePasswordPage(@Valid @ModelAttribute("ChangePasswordBackingObject") ChangePasswordBackingObject backingObject, BindingResult result, Principal principal)
    

    That is why if you have your Controller in this form (in Spring MVC for example), then you have to simulate your logic in a way - I've done that also.

    Another cool thing that you can do it to Validate two or more fields at at time (which I found pretty useful):

    @FieldMatch.List({
        @FieldMatch(firstValue = "password" , secondValue = "confirmPassword")
    })
    public class RequestAccountBackingObject implements Serializable {
        private String password;
        private String confirmPassword;
    

    And the implementation :

    @Target({TYPE, ANNOTATION_TYPE})
    @Retention(RUNTIME)
    @Constraint(validatedBy = FieldMatchImpl.class)
    @Documented
    public @interface FieldMatch{
        String message() default "{com.errorMessage}";
        Class<?>[] groups() default {};
        Class<? extends Payload>[] payload() default {};
        String firstValue();
        String secondValue();
        @Target({TYPE, ANNOTATION_TYPE})
        @Retention(RUNTIME)
        @Documented
        @interface List
        { FieldMatch[] value(); }
    }
    

    The other FieldMatchImpl would be :

    public class FieldMatchImpl implements ConstraintValidator<FieldMatch, Object>{
        private String firstFieldName;
        private String secondFieldName;
    

    and you need two methods implemented:

    public void initialize(final FieldMatch constraintAnnotation){
        firstFieldName = constraintAnnotation.firstValue();
        secondFieldName = constraintAnnotation.secondValue();
    

    Also:

    public boolean isValid(final Object value, final ConstraintValidatorContext context){
    
        final String firstObj = BeanUtils.getProperty(value, firstFieldName);
        final String secondObj = BeanUtils.getProperty(value, secondFieldName);
    

    Using org.apache.commons.beanutils.BeanUtils you can now validate the two fields.

    Like this:

    boolean result = firstObj.equals(secondObj);
    if(!result) {
        context.disableDefaultConstraintViolation();
        context.buildConstraintViolationWithTemplate(errorMessage).addNode(firstFieldName).addConstraintViolation();
    }
    

    Other then that it has been a pleasure using the Hibernate Validation so far.