Esta fábrica permite desacoplar a Constraint da implementação concreta do ConstraintValidator, possibilitando que aquela esteja fisicamente separada em projeto distinto do que conterá a implementação do validador acionado por ela, o que pode ser útil em sistemas compostos por múltiplos módulos independentes e que compartilham dados, aonde pode ser interessante, por exemplo, concentrar entidades e DTOs, classes normalmente marcadas com uma ou mais constraint para validar seus dados, em um projeto separado do negócio e da apresentação, o qual será compartilhado como dependência entre os vários módulos que utilizarão aqueles dados e com menor acoplamento direto entre os módulos. Neste cenário a validação das entidades do módulo "FOO" pode ser acionado a partir do módulo "BAR" através, por exemplo, de um serviço EJB.
Segundo especificado na API a implementação de validadores customizados segue o seguinte modelo:
Constraint
@Target( { METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER}) @Retention(RUNTIME) @Constraint(validatedBy = MyValidator.class) @Documented public @interface MyConstraint { String message() default "My message"; Class<?>[] groups() default {}; Class<? extends Payload>[] payload() default {}; }
Validador
public class MyValidator implements ConstraintValidator<MyConstraint, String> { public void initialize(MyConstraint constraintAnnotation) { ... } public boolean isValid(String object, ConstraintValidatorContext constraintContext) { ... } }
Com o uso do componente, é possível atribuir uma interface à constraint como visto a seguir:
Constraint
@Target( { METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER}) @Retention(RUNTIME) @Constraint(validatedBy = IMyValidator.class) @Documented public @interface MyConstraint { String message() default "My message"; Class<?>[] groups() default {}; Class<? extends Payload>[] payload() default {}; }
Interface do Validador
public interface IMyValidator extends ConstraintValidator<MyConstraint, String> { }
Validador
public class MyValidator implements IMyValidator { public void initialize(MyConstraint constraintAnnotation) { ... } public boolean isValid(String object, ConstraintValidatorContext constraintContext) { ... } }