JavaBean Validation - Cross parameter constraints

[Updated: Sep 26, 2016, Created: Sep 25, 2016]

Cross-parameter constraints are applied to the array of all parameters of a method or constructor.

This is usually useful when we want to validate parameters which are dependent on each other.

Using Cross-parameter on constructor

In following example we are going to validate whether the two dates passed to a constructor is in a valid date range, i.e. whether start date (the first parameter) is less than end date (the second parameter).

Creating constraint annotation

There's no difference between creating a normal constraint vs cross-parameter constraint.

    @Target({ElementType.CONSTRUCTOR, ElementType.ANNOTATION_TYPE})
    @Constraint(validatedBy = DateRangeValidator.class)
    public static @interface DateRangeParams {

        String message () default "'start date' must be less than 'end date'. " +
                            "Found: 'start date'=${validatedValue[0]}, " +
                            "'end date'=${validatedValue[1]}";

        Class<?>[] groups () default {};
        Class<? extends Payload>[] payload () default {};

Creating validator

Here we have to put an extra @SupportedValidationTarget(ValidationTarget.PARAMETERS) annotation at the validator class. This is an indication that the validation is to be performed on parameters and not on the return value.

There's one more difference here, we have to specify multiple parameters as an array of object for the second generic type, so that we can receive all parameters in the array.

    public static class DateRangeValidator implements
                        ConstraintValidator<DateRangeParams, Object[]> {
        public void initialize (DateRangeParams constraintAnnotation) {

        public boolean isValid (Object[] value, ConstraintValidatorContext context) {
            if (value == null || value.length != 2 ||
                                !(value[0] instanceof LocalDate) ||
                                !(value[1] instanceof LocalDate)) {
                return false;

            return ((LocalDate) value[0]).isBefore((LocalDate) value[1]);

The bean:

   public static class TradeHistory {
        private final LocalDate startDate;
        private final LocalDate endDate;

        public TradeHistory (LocalDate startDate, LocalDate endDate) {
            this.startDate = startDate;
            this.endDate = endDate;

        public LocalDate getStartDate () {
            return startDate;

        public LocalDate getEndDate () {
            return endDate;

Performing validation:

Here we are going to use ExecutableValidator#validateConstructorParameters(..) method.

  LocalDate startDate =;
  LocalDate endDate =;

  TradeHistory tradeHistory = new TradeHistory(startDate, endDate);

  Constructor<TradeHistory> constructor = TradeHistory.class.getConstructor(LocalDate
                            .class, LocalDate.class);

  ExecutableValidator executableValidator = validator.forExecutables();
  Set<ConstraintViolation<TradeHistory>> constraintViolations =
                                                   new Object[]{startDate, endDate});

  if (constraintViolations.size() > 0) {
  } else {
            //proceed using order


 TradeHistory.<cross-parameter> 'start date' must be less than 'end date'. Found: 'start date'=2016-09-25, 'end date'=2016-09-20

Using Cross-parameter on method

Similar to cross-parameter on constructors, we can do the same for method parameters. We just need to modify our bean accordingly, include 'ElementType.CONSTRUCTOR' to @Target annotation of our constraint and then to perform validation use method executableValidator.validateParameters(..).

Complete code is included in the example project below.

Example Project

Dependencies and Technologies Used:

  • Hibernate Validator Engine 5.2.4.Final: Hibernate's Bean Validation (JSR-303) reference implementation.
  • Expression Language API 2.2 2.2.4
  • Expression Language 2.2 Implementation 2.2.4
  • JDK 1.8
  • Maven 3.0.4

Class Level Constraints.project Select All Download
  • cross-parameter-constraint
    • src
      • main
        • java
          • com
            • logicbig
              • example

See Also