i have a little problem with implementing properly my own validation annotation.
Here is sample code:
@Pattern(regexp="[0-9]*")
@Size(min=3, max=10)
@Constraint(validatedBy = SampleValidator.class)
@Documented
@Target({ANNOTATION_TYPE, METHOD, FIELD, CONSTRUCTOR, PARAMETER})
@Retention(RUNTIME)
public @interface MyAnnotation {
String message() default "Wrong!";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
@Target({ METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER })
@Retention(RUNTIME)
@Documented
@interface List {
MyAnnotation[] value();
}
}
My problem is, I want my annotation to work in the way, that @Size
and @Pattern
annotation run first and if they're valid then (and only then) run validator provided by @Constraint
annotation (SampleValidator.class
).
Put it simple:
SampleValidator
only if @Pattern
and @Size
are valid(I implementes SampleValidator just as additional validator that should be called only in some specific circumstances)
How can I obtain such behaviour? Thanks in advance!
Obviously, I can't do anything like that:
@GroupSequence({ Step1.class, Step2.class })
@Constraint(validatedBy = SampleValidator.class, groups = Step1.class) // no 'groups' attribute
@Size(min=3, max=10, groups = Step2.class)
@Pattern(regexp="[0-9]*", groups = Step2.class)
@Documented
@Target({ANNOTATION_TYPE, METHOD, FIELD, CONSTRUCTOR, PARAMETER})
@Retention(RUNTIME)
public @interface MyAnnotation {
...
}
The answer is only partly correct. Yes @ReportAsSingleViolation that only one single violations will be generated and validation will stop after first failure in this case. However, the specification gives no guarantee in which order constraints are evaluated. It could be the composing constraints first or the validator specified via @Constraint. If anything you would rely on some implementation detail which could change any time. Also there is no order defined in which @Size and @Pattern are evaluated. Bottom line, you cannot achieve your wanted behaviour with constraint composition.
If you want to guarantee a sequenced execution you need to look at the GroupSequence feature.