I am trying to create custom validator for some class I defined constraint as following ( according to different samples , for example from here )
@Target({ TYPE, ANNOTATION_TYPE })
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = { MyClassValidator.class })
@Documented
public @interface MyClassValid {
String message() default "The password2 does not comply with the rules";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
}
Then I created corresponding validator :
public class MyClassValidator implements ConstraintValidator<MyClassValid, ChangePasswordBody> {
@Override
public boolean isValid(ChangePasswordBody value, ConstraintValidatorContext context) {
/*This check only for sample . Ot can be replaced by other logic*/
if (value.getNewPassword().length() > 2 ) {
return true;
}
return false;
}
}
Class to be validated :
@MyClassValid
public class ChangePasswordBody {
private String oldPassword;
private String newPassword;
public String getOldPassword() {
return oldPassword;
}
public void setOldPassword(String oldPassword) {
this.oldPassword = oldPassword;
}
public String getNewPassword() {
return newPassword;
}
public void setNewPassword(String newPassword) {
this.newPassword = newPassword;
}
}
This is code using ChangePasswordBody
private static void testChangePwd(ApplicationContext applicationContext) {
//...
ChangePasswordBody pwdBody = new ChangePasswordBody();
isValidPassword(pwdBody);
//...
}
private static void isValidPassword(ChangePasswordBody pwdBody) {
pwdBody.setNewPassword("l");
}
I see that when executing testChangePwd
method - MyClassValidator.isValid is not invoked. Is there something missing / wrong in the code ? Thanks in advance
The validation will not take place automatically , you have to somehow invoke it using the bean validation API (e.g. Validator
)
Presume spring-boot already auto-configures a Validator
, in your case you could trigger the validation programatically by :
private static void testChangePwd(ApplicationContext applicationContext) {
ChangePasswordBody pwdBody = new ChangePasswordBody();
pwdBody.setNewPassword("l");
Validator validator = applicationContext.getBean(Validator.class);
Set<ConstraintViolation<ChangePasswordBody>> validationErrors = validator.validate(pwdBody);
//handle the validationErrors here...
}
But it is a very bad idea that it requires to get a bean from the spring context in the business codes as it would couple it to spring . A much better approach is to make the object that you want to validate as the method argument and validate it through executing that method.
Something likes :
@Validated
public class PasswordService {
public void changePassword(@Valid ChangePasswordBody request) {
}
}
And if ChangePasswordBody
fails the validation , it will throw ConstraintViolationException
.