Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Nested validation groups, Spring, JSR 303

I'm trying to do a nested validation in my Spring application.

public class Parent{

   public interface MyGroup{}

   @NotNull(groups = MyGroup.class)
   private Child child;

   // getters and setters omited

}

public class Child{

   public interface OptionalGroup {}

   @NotBlank(groups = OptionalGroup.class)
   private String aField;

}

I already looked at @Valid from javax.validation package but it doesn't support group. I also checked @Validated annotation from spring but I can't applied it on a field.

I want to do something like :

public class Parent{

   public interface MyGroup{}

   @NotNull(groups = MyGroup.class)
   @CascadeValidate(groups = MyGroup.class, cascadeGroups = OptionalGroup.class) 
   // 'groups' correspond to parent group and 'cascadeGroups' to a group that needs to be apply to the Child field.

   private Child child;

}

And then I can pragmatically do wherever I want:

@Inject SmartValidator validator;

public void validationMethod(Parent parent, boolean condition) throws ValidationException {
   if(condition){
      MapBindingResult errors= new MapBindingResult(new HashMap<>(), target.getClass().getSimpleName());

      validator.validate(parent, errors, Parent.MyGroup.class); // validate all constraints associated to MyGroup

      if(errors.hasErrors()) throw new ValidationException(errors); // A custom exception
   }

}

Any ideas how to do that?

Thanks a lot

like image 527
LG_ Avatar asked Sep 07 '15 10:09

LG_


1 Answers

I finally found the solution. Actually I misunderstood what @Validwas made for.

The key is to declare same group for Parent and child attribute.

Solution :

public class Parent{

   public interface MyGroup{}

   @NotNull(groups = MyGroup.class)
   @Valid // This annotation will launch nested validation
   private Child child;

   // getters and setters omited

}

public class Child{

   @NotBlank(groups = Parent.MyGroup.class) // Declare same group
   private String aField;

}

In this case, when I do :

 @Inject SmartValidator validator;

public void validationMethod(Parent parent, boolean condition) throws ValidationException {
   if(condition){
      MapBindingResult errors= new MapBindingResult(new HashMap<>(), target.getClass().getSimpleName());

      // validate all constraints associated to MyGroup (even in my nested objects)
      validator.validate(parent, errors, Parent.MyGroup.class); 

      if(errors.hasErrors()) throw new ValidationException(errors); // A custom exception
   }

}

If a validation error is detected in my child field 'aField', the first associated validation error code (see FieldError.codes) will be 'NotBlank.Parent.afield'.

I should have better checked @Valid documentation.

like image 79
LG_ Avatar answered Nov 03 '22 13:11

LG_