nonder
nonder

Reputation: 155

Is it possible to pass validatedBy attribute to the annotation as a parameter?

I hard coded the validatedBy value as following.

@Constraint(validatedBy = ReminderValidator.class)
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface MyValidator{
    String message() default "{error.message}";
    Class<?>[] groups() default {};
    Class<? extends Payload>[] payload() default {};
}

Instead of hard coding the validatedBy value into my annotation interface, I want to pass it as a parameter something similar to the following.

@MyValidator(validatedBy = "ReminderValidator.class")
public class Reminder {
...
}

This will enable me to create just 1 annotation for all class validations. I will just provide different validator classes to the annotation to validate different classes. Is it possible to do something like this?

Upvotes: 2

Views: 997

Answers (2)

Maddy
Maddy

Reputation: 91

You can add multiple validators in the @Constraint annotation and it will pick the appropriate based on the object type.

@Constraint(validatedBy = { ReminderValidator.class, PendingValidator.class } )
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface MyValidator{
    String message() default "{error.message}";
    Class<?>[] groups() default {};
    Class<? extends Payload>[] payload() default {};
}

And

@MyValidator()
public class Reminder {
    ...
}

@MyValidator()
public class Pending {
    ...
}

Validator Examples

public class ReminderValidator implements ConstraintValidator<MyValidator, Reminder> {
...

public class PendingValidator implements ConstraintValidator<MyValidator, Pending> {
...

Upvotes: 2

Saurav Kumar Singh
Saurav Kumar Singh

Reputation: 1458

Let me know if this is an acceptable solution for you -

@Constraint(validatedBy = CommonValidator.class)
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface MyValidator{
    // this decides what actual validator we will use
    String validator();
    String message() default "{error.message}";
    Class<?>[] groups() default {};
    Class<? extends Payload>[] payload() default {};
}

Now in the CommonValidator we can decide the actual validator based on the value of validator.


Example of a static validator:

public class SomeValidator {
    public static boolean isValid(Object field, ConstraintValidatorContext context) {
        // your actual validation code
    }
}

Similarly you can define your other validators as well.


This is how you can use the static validator in actual validator :

public class CommonValidator implements ConstraintValidator<MyValidator, Object> {

    private String validator;

    @Override
    public void initialize(MyValidator myValidator) {
        this.validator = myValidator.validator();
        // do other inits as per your requirement
    }

    @Override
    public boolean isValid(Object field, ConstraintValidatorContext context) {
        ValidatorFactory.getValidator("someValidator").isValid(field, context)
        // return other validators like above
        return false;
    }
}

finally you can use you annotation like this -

@MyValidator(validator = "someValidator")
private Object object;

Object can be any other class as well, you have to handle this in individual static validator.

FYI - this is just an idea, Actual implementation might differ as per your use case.

Upvotes: 1

Related Questions