In JSR-303 (Bean Validation) you need to define a special annotation for each constraint validator you write. This makes perfect sense if you are creating reusable constraint validators (like the standard @Max
, @NotNull
, etc).
However in real life every validated bean requires its own validator to do more complex business validations. With vanilla JSR-303 implementations you have to create a separate annotation for every validator. This forces developer to write one-time-only annotations and makes the overall concept of bean validation look stupid. The necessity for one-time-only annotations can be avoided if JSR-303 offers some sort of delegating constraint annotation: @ValidateBy(validator=my.custom.Validator)
.
Now to my question:
UPDATE 1 - Specific use-case (which led to this question)
We have a moderate enterprise application with pretty rich business model (40 manageable entities, 20 embeddable entities, 25 read-only entities). This means that we have a lots of HTML forms. Each form is backed by a designated form bean (70 form beans) with JSR-303 annotations. Some forms require custom non-trivial validation (e.g. if delivery type is email then a contact email must be set, ...). With JSR-303 we have 33 form-bean specific validators with 33 (unnecessary one-time-only) annotations.
With the number of Java classes (entities, controllers, DAOs, DTOs, mappers, validators, etc... right now this makes 800 .java
files) I don't like having any boilerplate code around.
Sometimes you need to ask the question to realize how to solve "the problem" yourself. Based on Gunnar's answer and comments:
You can create @MyDomainModelValid
constriant definition for the custom domain model with all the necessary validators:
@Target({TYPE})
@Retention(RUNTIME)
@Constraint(validatedBy={
MyFirstEntityValidator.class, MySecondEntityValidator.class,
MyThirdEntityValidator.class, EtCetera.class})
public @interface MyDomainModelValid {
String message() default "entity.notValid";
Class<?>[] groups() default { };
Class<? extends Payload>[] payload() default {};
}
JSR-303 implementation will make sure that a correct validator is called for a specific entity. So there is no need for previously proposed @ValidatedBy
annotation.