I would not recommend it, but you can do it something like this:
@Target({ ElementType.FIELD }) @Retention(RetentionPolicy.RUNTIME) @Constraint(validatedBy = GenericValidatorBootstrapperValidator.class) public @interface CustomAnnotation { public String message(); Class<?>[] groups() default {}; Class<? extends Payload>[] payload() default {}; Class<? extends ConstraintValidator<? extends CustomAnnotation, Serializable>> validator(); } public class GenericValidatorBootstrapperValidator implements ConstraintValidator<CustomAnnotation, Object> { private final ConstraintValidator validator; @Override public void initialize(CustomAnnotation constraintAnnotation) { Class<? extends ConstraintValidator> validatorClass = constraintAnnotation.validator(); validator = validatorClass.newInstance(); validator.initialize( ... ); //TODO with what? } @Override public boolean isValid(Object value, ConstraintValidatorContext context) { return validator.isValid(value, context); } }
But then again, prefer specific annotations, they are more expressive.
Edit
After your comment, I think you want to be able to set different validators based on the return type of the property
@CustomAnnotation List<String> foo; @CustomAnnotation Table bar;
If so, add a few validator implementations in the @Constraint annotations.
@Target({ ElementType.FIELD }) @Retention(RetentionPolicy.RUNTIME) @Constraint(validatedBy = {ListValidatorImpl.class, TableValidatorImpl.class, ...}) public @interface CustomAnnotation { public String message(); Class<?>[] groups() default {}; Class<? extends Payload>[] payload() default {}; } public class ListValidatorImpl implements ConstraintValidator<CustomAnnotation, List> { @Override public boolean isValid(List value, ConstraintValidatorContext context) { } } public class TableValidatorImpl implements ConstraintValidator<CustomAnnotation, Table> { @Override public boolean isValid(Table value, ConstraintValidatorContext context) { } }
You can even link the contraint annotation to the implementation via the META/validation.xml file
<constraint-mappings xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://jboss.org/xml/ns/javax/validation/mapping validation-mapping-1.1.xsd" xmlns="http://jboss.org/xml/ns/javax/validation/mapping" version="1.1"> <constraint-definition annotation="org.mycompany.CustomAnnotation"> <validated-by include-existing-validators="true"> <value>org.mycompany.EnumCustomValidatorImpl</value> </validated-by> </constraint-definition> </constraint-mappings>
If you need something more flexible, I think my initial proposal will work. In the GenericValidatorBootstrapperValidator isValid method, you can call the correct validator instance based on the object type of the value parameter (for example, via instanceof ).