Reputation: 5443
I'm using Spring+Hibernate+Spring-MVC.
I want to define a custom constraint combining two other predefined validation annotations: @NotNull @Size
like this:
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
@NotNull
@Size(min=4)
public @interface JPasswordConstraint {
} // this is not correct. It's just a suggestion.
and I want to use this annotation in my form models.
public class ChangePasswordForm {
@NotNull
private String currentPass;
@JPasswordConstraint
private String newPass;
@JPasswordConstraint
private String newPassConfirm;
}
@RequestMapping(value = "/pass", method = RequestMethod.POST)
public String pass2(Model model, @Valid @ModelAttribute("changePasswordForm") ChangePasswordForm form, BindingResult result) {
model.addAttribute("changePasswordForm", form);
try {
userService.changePassword(form);
} catch (Exception ex) {
result.rejectValue(null, "error.objec", ex.getMessage());
System.out.println(result);
}
if (!result.hasErrors()) {
model.addAttribute("successMessage", "password changed successfully!");
}
return "user/pass";
}
But it does not work. It accepts the less than 4 character passwords.
How can I solve this problem?
Upvotes: 18
Views: 16199
Reputation: 793
You can combine several validation annotations into one the following way :
(This is an exemple which combines @Pattern(regexp = "[a-z]")
AND
@Size(min = 2, max = 3)
)
@Pattern(regexp = "[a-z]")
@Size(min = 2, max = 3)
@ReportAsSingleViolation
@Target({ METHOD, FIELD })
@Retention(RUNTIME)
@Constraint(validatedBy = { })
public @interface PatternOrSize {
String message() default "";
Class<?>[] groups() default { };
Class<? extends Payload>[] payload() default { };
}
Note that by default the annotations conditions follow the AND logic (i.e. all of them must be true).
For special needs, you can use the OR logic. You do so by using @ConstraintComposition(OR)
For example if you want @NotNull
OR `@Size`` do the following :
@ConstraintComposition(OR) // <---
@NotNull
@Size(min = 2, max = 3)
@ReportAsSingleViolation
@Target({ METHOD, FIELD })
@Retention(RUNTIME)
@Constraint(validatedBy = { })
public @interface PatternOrSize {
String message() default "";
Class<?>[] groups() default { };
Class<? extends Payload>[] payload() default { };
}
Upvotes: 7
Reputation: 7735
This is a bit late, but technique of combining validation annotations described in
Maybe it was not available, at the time of writing, but solution is following
@NotNull
@Size(min=4)
@Target({ METHOD, FIELD, ANNOTATION_TYPE })
@Retention(RUNTIME)
@Constraint(validatedBy = { })
@Documented
public @interface JPasswordConstraint {
String message() default "Password is invalid";
Class<?>[] groups() default { };
Class<? extends Payload>[] payload() default { };
}
Upvotes: 21