JavaBean validation specifications provides ways to hook up custom annotations to the framework.
In cases where predefined constraints are not sufficient, we can easily create custom constraints for our specific validation requirements.
We have to follow these steps to create a custom constraint:
- Create a validator class which should implement
javax.validation.ConstraintValidator interface.
- Create the constraint annotation which should be annotated with
javax.validation.Constraint annotation.
To understand how to achieve above two steps, let's see the definitions of ConstraintValidator interface and javax.validation.Constraint annotation.
Definition of ConstraintValidator(Version: java-bean-validation 2.0.2) package javax.validation;
........
public interface ConstraintValidator<A extends Annotation, T> {
default void initialize(A constraintAnnotation) {} 1
boolean isValid(T value, ConstraintValidatorContext context); 2
}
Definition of Constraint(Version: java-bean-validation 2.0.2) package javax.validation;
........
@Documented
@Target({ANNOTATION_TYPE})
@Retention(RUNTIME)
public @interface Constraint {
Class<? extends ConstraintValidator<?, ?>>[] validatedBy(); 1
}
Example
Creating the custom annotation
In this example, we are going to validate weather a provided string is a valid language name or not.
New constraint annotation
package com.logicbig.example;
import javax.validation.Constraint;
import javax.validation.Payload;
import java.lang.annotation.*;
@Target({ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER,
ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = LanguageValidator.class)
@Documented
public @interface Language {
String message() default "must be a valid language display name." +
" found: ${validatedValue}";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
}
Creating the validator:
package com.logicbig.example;
import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
import java.util.Locale;
public class LanguageValidator implements ConstraintValidator<Language, String> {
@Override
public void initialize(Language constraintAnnotation) {
}
@Override
public boolean isValid(String value, ConstraintValidatorContext context) {
if (value == null) {
return false;
}
for (Locale locale : Locale.getAvailableLocales()) {
if (locale.getDisplayLanguage().equalsIgnoreCase(value)) {
return true;
}
}
return false;
}
}
The bean using our new constraint annotation
package com.logicbig.example;
class TestBean {
@Language
private String language;
public String getLanguage() {
return language;
}
public void setLanguage(String language) {
this.language = language;
}
}
Performing validation
package com.logicbig.example;
import javax.validation.*;
public class CustomConstraintExample {
private static final Validator validator;
static {
Configuration<?> config = Validation.byDefaultProvider().configure();
ValidatorFactory factory = config.buildValidatorFactory();
validator = factory.getValidator();
factory.close();
}
public static void main(String[] args) {
TestBean testBean = new TestBean();
testBean.setLanguage("englis");
validator.validate(testBean).stream().forEach(CustomConstraintExample::printError);
}
private static void printError(ConstraintViolation<TestBean> violation) {
System.out.println(violation.getPropertyPath() + " " + violation.getMessage());
}
}
Outputlanguage must be a valid language display name. found: englis
Example ProjectDependencies and Technologies Used: - hibernate-validator 6.2.0.Final (Hibernate's Jakarta Bean Validation reference implementation)
Version Compatibility: 5.0.0.Final - 6.2.0.Final Version compatibilities of hibernate-validator with this example: groupId: org.hibernate artifactId: hibernate-validator Reference implementation for Bean Validation 1.1
- 5.0.0.Final
- 5.0.1.Final
- 5.0.2.Final
- 5.0.3.Final
- 5.1.0.Final
- 5.1.1.Final
- 5.1.2.Final
- 5.1.3.Final
- 5.2.0.Final
- 5.2.1.Final
- 5.2.2.Final
- 5.2.3.Final
- 5.2.4.Final
- 5.2.5.Final
- 5.3.0.Final
- 5.3.1.Final
- 5.3.2.Final
- 5.3.3.Final
- 5.3.4.Final
- 5.3.5.Final
- 5.3.6.Final
- 5.4.0.Final
- 5.4.1.Final
- 5.4.2.Final
- 5.4.3.Final
groupId: org.hibernate.validator artifactId: hibernate-validator Reference implementation for Bean Validation 2.0
- 6.0.0.Final
- 6.0.1.Final
- 6.0.2.Final
- 6.0.3.Final
- 6.0.4.Final
- 6.0.5.Final
- 6.0.6.Final
- 6.0.7.Final
- 6.0.8.Final
- 6.0.9.Final
- 6.0.10.Final
- 6.0.11.Final
- 6.0.12.Final
- 6.0.13.Final
- 6.0.14.Final
- 6.0.15.Final
- 6.0.16.Final
- 6.0.17.Final
- 6.0.18.Final
- 6.0.19.Final
- 6.0.20.Final
- 6.0.21.Final
- 6.0.22.Final
- 6.1.0.Final
- 6.1.1.Final
- 6.1.2.Final
- 6.1.3.Final
- 6.1.4.Final
- 6.1.5.Final
- 6.1.6.Final
- 6.1.7.Final
- 6.2.0.Final
Version 7 and later: Jakarta Bean Validation 3.0 jakarta.* packages
Versions in green have been tested.
- javax.el-api 3.0.0 (Expression Language 3.0 API)
- javax.el 2.2.6 (Expression Language 2.2 Implementation)
- JDK 8
- Maven 3.8.1
|