We can do validations on constructor parameters or method parameters by placing the constraints just right before the parameters.
ExecutableValidator is used perform such validation.
Definition of ExecutableValidator(Version: java-bean-validation 2.0.2) package javax.validation.executable;
........
public interface ExecutableValidator {
<T> Set<ConstraintViolation<T>> validateParameters(
T object, Method method, Object[] parameterValues, Class<?>... groups);
<T> Set<ConstraintViolation<T>> validateReturnValue(
T object, Method method, Object returnValue, Class<?>... groups);
<T> Set<ConstraintViolation<T>> validateConstructorParameters(
Constructor<? extends T> constructor,
Object[] parameterValues,
Class<?>... groups);
<T> Set<ConstraintViolation<T>> validateConstructorReturnValue(
Constructor<? extends T> constructor, T createdObject, Class<?>... groups);
}
As seen above ExecutableValidator can be used to validate constructor/method parameters and their return values. In this example we will focus on only validator parameters.
Examples
Using constraints on constructor parameter
We can validate constructor parameters before the constructor is invoked so that we can be sure that all preconditions are met before calling a constructor.
package com.logicbig.example;
import javax.validation.*;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Pattern;
import javax.validation.executable.ExecutableValidator;
import java.lang.reflect.Constructor;
import java.util.Comparator;
import java.util.Set;
public class ConstructorParamValidationExample {
private static class User {
private final String name;
private final String phone;
public User(@NotNull String name,
@NotNull
@Pattern(regexp = "(\\d){3,3}-\\d{3,3}-\\d{4,4}",
message = "must match 111-111-1111 format")
String phone) {
this.name = name;
this.phone = phone;
}
public String getName() {
return name;
}
public String getPhone() {
return phone;
}
}
public static void main(String[] args) throws NoSuchMethodException {
Validator validator = getValidator();
Constructor<User> constructor =
User.class.getConstructor(String.class, String.class);
ExecutableValidator executableValidator = validator.forExecutables();
String userName = null;
String userPhone = "223-223-222";
Set<ConstraintViolation<User>> constraintViolations =
executableValidator.validateConstructorParameters(constructor,
new Object[]{userName, userPhone});
if (constraintViolations.size() > 0) {
constraintViolations.stream().sorted(Comparator.comparing(o -> o.getPropertyPath().toString()))
.forEach(ConstructorParamValidationExample::printError);
} else {
User user = new User(userName, userPhone);
System.out.println(user);
}
}
private static Validator getValidator() {
Configuration<?> config = Validation.byDefaultProvider().configure();
ValidatorFactory factory = config.buildValidatorFactory();
Validator validator = factory.getValidator();
factory.close();
return validator;
}
private static void printError(
ConstraintViolation<User> violation) {
System.out.println(violation.getPropertyPath() + " " + violation.getMessage());
}
}
OutputUser.arg0 must not be null User.arg1 must match 111-111-1111 format
Using constraints on method parameters
Just like constrictors, we can also find out validation violations on method parameter before the method is invoked. That way we can make sure that all preconditions are satisfied before calling a method.
package com.logicbig.example;
import javax.validation.*;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
import javax.validation.executable.ExecutableValidator;
import java.lang.reflect.Method;
import java.util.Comparator;
import java.util.Set;
public class MethodParamValidationExample {
private static class Task {
public void run (@Size(min = 3, max = 20) String name,
@NotNull Runnable runnable) {
System.out.println("starting task synchronously: " + name);
runnable.run();
}
}
public static void main (String[] args) throws NoSuchMethodException {
Validator validator = getValidator();
Method method = Task.class.getDeclaredMethod("run",
new Class[]{String.class, Runnable.class});
ExecutableValidator executableValidator = validator.forExecutables();
Task task = new Task();
String taskName = "a";
Runnable runnable = null;
Set<ConstraintViolation<Task>> violations =
executableValidator.validateParameters(task, method,
new Object[]{taskName, runnable});
if (violations.size() > 0) {
violations.stream().sorted(Comparator.comparing(o -> o.getPropertyPath().toString()))
.forEach(MethodParamValidationExample::printError);
} else {
task.run(taskName, runnable);
}
}
private static Validator getValidator(){
Configuration<?> config = Validation.byDefaultProvider().configure();
ValidatorFactory factory = config.buildValidatorFactory();
Validator validator = factory.getValidator();
factory.close();
return validator;
}
private static void printError (
ConstraintViolation<Task> violation) {
System.out.println(violation.getPropertyPath() + " " + violation.getMessage());
}
}
Outputrun.arg0 size must be between 3 and 20 run.arg1 must not be null
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
|