Search code examples
javabean-validationjavax.validation

Pass parameter from validate to custom validator in hibernate validator


I'm trying to validate a bean using custom validator. But the validator needs info that is to be passed to it from the method where validate is invoked. Is there a way to do that?

I can't pass it in initialize as it is not available at the time of bean creation.

Bean to validate

class vehicle {
   @VehicleNameValidator
   String vehicleName;
}

Annotation

@Target({ElementType.FIELD})
@Retention(RUNTIME)
@Constraint(validatedBy = VehicleNameValidatorImpl.class)
@Documented
public @interface VehicleNameValidator {
    String message() default "Invalid vehicle Name";

    Class<?>[] groups() default { };

    Class<? extends Payload>[] payload() default { };
}

custom validator

public class VehicleNameValidatorImpl implements ConstraintValidator<VehicleNameValidator, String[]> {

    @Override
    public boolean isValid(String vehicleName, ConstraintValidatorContext constraintValidatorContext) {
        boolean isValid = logicmethod()//some logic here
        return isValid;
    }
}

Main method

public static void main(String[] args) {
   String whatIwantToPass = runtimelogic(args);
   vehicle veh1 = new vehicle();
   Set<ConstraintViolation<vehicle>> constraintViolations = 
   validator.validate(veh1);
}

How to I pass variable "whatIwantToPass" from main method to VehicleNameValidatorImpl.


Solution

  • In case you are using Hibernate Validator you might want to take a look at constraint validator payload. In your case it would look somewhat like this:

    In your validator impl you can access the payload:

    public boolean isValid(String vehicleName, ConstraintValidatorContext constraintValidatorContext) {
        boolean isValid = false;
        if ( constraintValidatorContext instanceof HibernateConstraintValidatorContext ) {
            final String payload = constraintValidatorContext
                    .unwrap( HibernateConstraintValidatorContext.class )
                    .getConstraintValidatorPayload( String.class );
            // do whatever you need
            isValid = logicmethod()//some logic here
        }
        return isValid;
    }
    

    And the payload can be set either on the validator factory level or per validator like this:

    ValidatorFactory validatorFactory = Validation.byProvider( HibernateValidator.class )
            .configure()
            .buildValidatorFactory();
    
    String whatIwantToPass = runtimelogic( args );
    
    Validator validator = validatorFactory.unwrap( HibernateValidatorFactory.class )
            .usingContext()
            .constraintValidatorPayload( whatIwantToPass )
            .getValidator();
    
    // use the validator with the constraint validator payload 
    vehicle veh1 = new vehicle();
    Set<ConstraintViolation<vehicle>> constraintViolations = validator.validate( veh1 );
    

    For more detailed info check this part of documentation - Passing a payload to the constraint validator