Close

Java Bean Validation - Using constraints on constructor and method parameters

[Last Updated: Aug 25, 2021]

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());
    }
}

Output

User.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());
    }
}

Output

run.arg0 size must be between 3 and 20
run.arg1 must not be null


Example Project

Dependencies 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 List
    ×

    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

Using constraints with constructor/method parameters Select All Download
  • parameter-validation
    • src
      • main
        • java
          • com
            • logicbig
              • example
                • ConstructorParamValidationExample.java

    See Also