I have one NumberConstraint as follows:
@Constraint(validatedBy = { StringConstraintValidator.class, })
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.FIELD, ElementType.PARAMETER, })
public @interface StringConstraint {
String message() default "'${validatedValue}' ist not valid Number. " +
"A String is composed of 7 characters (digits and capital letters). Valid example: WBAVD13.";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
}
and it is validated by StringConstraintValidator as follows:
@Component
public class StringConstraintValidator implements ConstraintValidator<StringConstraint, String> {
private static final String REGEX_String = "^[A-Z0-9]{7}$";
@Override
public void initialize(final StringConstraint annotation) {
// noop
}
@Override
public boolean isValid(final String value, final ConstraintValidatorContext context) {
return isValid(value);
}
public boolean isValid(final String value) {
// Number is not always null Checked via @NotNull
LoggingContext.get().setString(value);
if (value == null) {
return false;
}
return Pattern.compile(REGEX_STRING).matcher(value).matches();
}
}
I can apply this StringConstraint on single field of request object as follows:
@StringConstraint
private String number;
but if my request object contains a List of Strings then how can I use this constraint on entire List or do I have to define new on List type ?? Something like ConstraintValidator<StringConstraint, List ???>
My request object is:
@JsonProperty(value = "items", required = true)
@Schema(description = "List of items.", required = true)
private List<String> items= new ArrayList<>();
So i want to apply my validator on all the strings in the list. How can i apply @StringConstraint
on my list ?
Yes, you can add more validators for one constraint by using a comma-separated list of validator classes in the validatedBy
attribute of the @Constraint
annotation. For example, you can write:
@Constraint(validatedBy = {StringConstraintValidator.class, BlablaValidot.class})
public @interface MyConstraint {
// other attributes
}
The @Constraint
annotation is used to define a custom constraint annotation that can be applied to fields, methods, classes, etc. The validatedBy
attribute specifies one or more classes that implement the ConstraintValidator
interface and provide the logic to validate the annotated element. You can use multiple validators for the same constraint if you want to check different aspects or conditions of the value. For example, you can have one validator that checks the length of a string and another that checks the format of a string.
Here are some examples of custom constraint annotations with multiple validators:
@PhoneNumber
annotation that validates a phone number using two validators: one for the country code and one for the number format.@Constraint(validatedBy = {CountryCodeValidator.class, PhoneNumberValidator.class})
@Target({ElementType.FIELD, ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
public @interface PhoneNumber {
String message() default "Invalid phone number";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
}
@Password
annotation that validates a password using three validators: one for the minimum length, one for the maximum length, and one for the presence of special characters.@Constraint(validatedBy = {MinLengthValidator.class, MaxLengthValidator.class, SpecialCharValidator.class})
@Target({ElementType.FIELD, ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
public @interface Password {
String message() default "Invalid password";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
int minLength() default 8;
int maxLength() default 20;
String specialChars() default "!@#$%^&*";
}