4

I would like to use Java Bean Validation to validate an Integer. It is a validation of multiple validations.

I'm currently using Spring Boot and validation, and system is using a @RestController where I'm receiving the post-call.

public Person addPerson(@RequestBody @Validated Person Person) {/*the code*/}

I would like the age to be validated, where these values are valid:

age == null or age == 0 or (age >= 15 and age <= 80)


public class Person {
    private Integer age;
}

I would like to be able to use the current validation constraints of java. Do I need to implement my own constraint annotation ?

This would be nice, but this does not work:

public class Person {
    @Null
    @Range(min=0, max=0)
    @Range(min=15, max = 80)
    private Integer age;
}
Kurt
  • 190
  • 1
  • 10
  • 1
    Can you clarify what you mean by 'would not work'? At which point are you running the validations? Which validation framework are you using? What is the problem you are getting? – jbx Sep 21 '18 at 09:42

2 Answers2

9

You can group build in constraints using ConstraintCoposition:

public class Test {

    private static ValidatorFactory factory = Validation.buildDefaultValidatorFactory();

    @ConstraintComposition(CompositionType.AND)
    @Min(value = 0)
    @Max(value = 0)
    @Target( { ElementType.ANNOTATION_TYPE } )
    @Retention( RetentionPolicy.RUNTIME )
    @Constraint(validatedBy = { })
    public @interface ZeroComposite {
        String message() default "Not valid";
        Class<?>[] groups() default { };
        Class< ? extends Payload>[] payload() default { };
    }

    @ConstraintComposition(CompositionType.OR)
    @Null
    @ZeroComposite
    @Range(min=15, max = 80)
    @Target( { ElementType.METHOD, ElementType.FIELD } )
    @Retention( RetentionPolicy.RUNTIME )
    @Constraint(validatedBy = { })
    public @interface Composite {
        String message() default "Not valid";
        Class<?>[] groups() default { };
        Class< ? extends Payload>[] payload() default { };
    }

    @Composite
    private Integer age;


    public Test(Integer age) {
        this.age = age;
    }

    public static void main(String args[]) {
        validate(new Test(-1));
        validate(new Test(null));
        validate(new Test(0));
        validate(new Test(5));
        validate(new Test(15));
        validate(new Test(80));
        validate(new Test(81));
    }

    private static void validate(Test t) {
        Set<ConstraintViolation<Test>> violations = 
            factory.getValidator().validate(t);

        for (ConstraintViolation<Test> cv : violations) {
            System.out.println(cv.toString());
        }
    }
}
kaos
  • 1,598
  • 11
  • 15
  • Thank you, this is perfect. Please add `ValidatorFactory factory = Validation.buildDefaultValidatorFactory();` in the validate method. Then this will be selected as the correct answer. – Kurt Sep 21 '18 at 11:32
  • Right, it should be defined as a static field. It was lost when i copied the code . – kaos Sep 21 '18 at 11:58
0

According to Implementing Validation for RESTful Services with Spring Boot the correct annotation is @Valid (and not @Validated)

Benoit
  • 5,118
  • 2
  • 24
  • 43
  • Yes, but according to this [link](https://stackoverflow.com/questions/44051244/valid-vs-validated-in-spring-boot-rest-api-requestbody?rq=1) it does not matter. – Kurt Sep 21 '18 at 11:28