springvalidationnestedbean-validationvalidationgroup

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


Solution

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