I have a constraint on which I want to use EL to tune the message to the circumstances. Dependent on the length of an array, I want to show a different message. However, I'm having trouble getting the length of that array.
What am I doing wrong?
import org.junit.jupiter.api.Test;
import javax.validation.*;
import java.lang.annotation.*;
import static org.assertj.core.api.Assertions.assertThat;
public class FooTest {
private final Validator validator = Validation.buildDefaultValidatorFactory().getValidator();
@Test
public void foo() {
var violations = validator.validate(new ObjectWithFoo());
assertThat(violations).extracting("message")
.containsExactly("Field value should be foo");
}
@Test
public void foos() {
var violations = validator.validate(new ObjectWithFoos());
assertThat(violations).extracting("message")
.containsExactly("Field value should be one of [foo, bar, baz]");
}
@Foo(foos = {"foo"})
private static class ObjectWithFoo{}
@Foo(foos = {"foo", "bar", "baz"})
private static class ObjectWithFoos{}
@Constraint(validatedBy = FooValidator.class)
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface Foo{
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
String[] foos();
// This is the message I want to tune to the length of the array.
// If the array contains just one element, I want to show a different message.
// Note that 'one of foos' is a placeholder; I still need to figure out
// how to display the array in that case.
String message() default "Field value should be ${foos.length == 1 ? foos[0] : 'one of foos'}";
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@interface List {
Foo[] value();
}
}
public static class FooValidator implements ConstraintValidator<Foo, Object> {
@Override
public void initialize(Foo constraintAnnotation) {
}
@Override
public boolean isValid(Object o, ConstraintValidatorContext constraintValidatorContext) {
return false; // for this test, we want the validation to fail
}
}
}
Unfortunately, this throws an exception:
20:03:52.810 [main] WARN org.hibernate.validator.internal.engine.messageinterpolation.ElTermResolver -
HV000148: An exception occurred during evaluation of EL expression '${foos.length == 1 ? foos[0] : 'one of $foos'}'
java.lang.NumberFormatException: For input string: "length"
at java.base/java.lang.NumberFormatException.forInputString(NumberFormatException.java:65)
at java.base/java.lang.Integer.parseInt(Integer.java:652)