Bean Validation message interpolation with array constraint parameter used as variable in message

3.9k views Asked by At

Is it possible to join the int array arguments in javax.validation error message interpolation?

I want to validate a string for different possible lengths and I started implementing a custom constraint:

@Constraint(validatedBy = {BarcodeValidator.class})
public @interface Barcode {
String message() default "{validation.Barcode.message}";
  int[] lengths();
}

The validator:

public class BarcodeValidator implements ConstraintValidator<Barcode, String> {

  private List<Integer> lengths;

  @Override
  public void initialize(Barcode barcode) {
    lengths = new ArrayList<>(barcode.lengths().length);
    for (int l : barcode.lengths()) lengths.add(l);
  }

  @Override
  public boolean isValid(String value, ConstraintValidatorContext context) {
    return value != null && lengths.contains(value.length());
  }
}

I would like a custom message for it like: The barcode must be 12/23/45 character long!

I have figured out I can use the annotation parameters in the message, so I would like to do something like:

validation.Barcode.message = The barcode must be ${'/'.join(lengths)} character long!

Is something like that possible or should I do it in some other way?

(P.S.: My first question here on SO.)

1

There are 1 answers

0
MrMeszaros On BEST ANSWER

Eventually I found a solution.
Validator class:

public class BarcodeValidator implements ConstraintValidator<Barcode, String> {

  private List<Integer> lengths;

  @Override
  public void initialize(Barcode barcode) {
    lengths = new ArrayList<>(barcode.lengths().length);
    for (int l : barcode.lengths()) lengths.add(l);
  }

  @Override
  public boolean isValid(String value, ConstraintValidatorContext context) {
    context.unwrap(HibernateConstraintValidatorContext.class).addExpressionVariable("joinedLengths", String.join(" / ", lengths));
    return value != null && lengths.contains(value.length());
  }
}

*.properties:

validation.Barcode.message = The barcode must be ${joinedLengths} character long!

Also tried naming the parameter lengths, but that did not work - it is probably bound to the type int[].