Ich weiß, Hibernate-Validator unterstützt TYPE_USE
Annotationen: obwohl es nicht seine eigenen definiert, können Sie benutzerdefinierte definieren und verwenden.TYPE_USE-Annotation im Hibernate-Validator
Ich könnte eine solche Annotation (Code bald) korrekt definieren und validieren, aber dann möchte ich den Fehler in einen Pfad mappen, der verwendet wird, um den Fehler für den Benutzer anzuzeigen.
Gegeben dann Probe nach
public class SampleTest {
private final Validator validator = Validation.buildDefaultValidatorFactory().getValidator();
public static class LimitedSizeStringValidator implements ConstraintValidator<LimitedSize, String> {
private LimitedSize constraint;
@Override
public void initialize(LimitedSize constraintAnnotation) {
this.constraint = constraintAnnotation;
}
@Override
public boolean isValid(String value, ConstraintValidatorContext context) {
String s = Ensure.notNull(value);
return s.length() >= constraint.min() &&
s.length() <= constraint.max();
}
}
@Retention(RUNTIME)
@Documented
@Target({TYPE_USE})
@Constraint(validatedBy = {LimitedSizeStringValidator.class})
public @interface LimitedSize {
String message() default "{javax.validation.constraints.Size.message}";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
int min() default 0;
int max() default Integer.MAX_VALUE;
}
private static class TestBean {
@Valid
private Collection<@LimitedSize(max = 3) String> strings = new ArrayList<>();
@Valid
private Collection<InnerBean> beans = new ArrayList<>();
}
private static class InnerBean {
@Min(3)
private final int value;
private InnerBean(int value) {
this.value = value;
}
}
@Test
public void testBeanInvalid() {
TestBean testBean = new TestBean();
assertThat(validator.validate(testBean)).isEmpty();
testBean.strings.add("ok");
testBean.strings.add("ok2");
testBean.beans.add(new InnerBean(4));
assertThat(validator.validate(testBean)).isEmpty();
testBean.strings.add("not_ok");
testBean.beans.add(new InnerBean(2));
Set<ConstraintViolation<TestBean>> violations = validator.validate(testBean);
assertThat(violations).hasSize(2);
StreamSupport.stream(violations.spliterator(), false)
.forEach(v -> {
System.out.println(v.getPropertyPath());
System.out.println(v.getMessage());
v.getPropertyPath().forEach(p -> System.out.print("'" + p.getName() + (p.getIndex() != null ? "[" + p.getIndex() + "]" : "") + "' -> "));
System.out.println();
});
}
}
Ich mag die Fehler in einem Objekt wie
errors: [
["beans", "1", "value"],
["strings", "2"]
]
Wie in meiner Probe abbilden würde, mein Ansatz ist im Moment durch die Verletzung Pfad der Navigation (http://docs.oracle.com/javaee/7/api/javax/validation/ConstraintViolation.html#getPropertyPath--), die für den ersten Fall perfekt funktioniert, aber für den zweiten fehlschlägt (ich finde keinen Weg, den Index des fehlerhaften Objekts abzurufen). Ich glaube, der Grund dafür ist, bei der Umsetzung von javax.validation.Path.PropertyNode in Hibernate-Validator (Ich bin derzeit auf Version 5.2.4.Final
, und der Code sieht genauso aus wie in den verknüpften 5.2.1.Final
als Referenz.
@Override
public final Integer getIndex() {
if (parent == null) {
return null;
}
else {
return parent.index;
}
}
Mit TYPE_USE
dieser Ansatz kann nicht funktionieren meiner Meinung nach, weil das fehlerhafte Objekt ein Blatt ist, damit kein Kind-Knoten den Index abgerufen werden kann.
Nizza genug, hibernate Implementierung von javax.validation.Path
überschreibt die toString
Verfahren ist derart, dass violation.getPropertyPath().toString()
ist beans[1].value
und strings[2]
(in der Sampl e Code oben).
Also, zu den Fragen: Ist meine Navigation falsch und es gibt eine andere Möglichkeit, ein solches Mapping aus der ConstraintViolation
zu extrahieren? Oder ist das ein Feature-Request für Hibernate-Entwickler (Ich kann sehen, dass vor TYPE_USE
Annotationen die getIndex
Ansatz sie umgesetzt war völlig in Ordnung?
Es fühlt sich einfach seltsam Ich bin der erste, der sich mit diesem Problem (Ich habe versucht, Google und konnte nicht Finden Sie etwas, das am nächsten ist: https://github.com/hibernate/hibernate-validator/pull/441), also frage ich mich, ob der Fehler meiner ist eher als eine Winterschlafbeschränkung
danke für die schnelle Rückmeldung. hier das Problem: https://hibernate.atlassian.net/browse/HV-1121. Ich denke vielleicht sogar daran, eine PR direkt zu öffnen (aber nicht vor Sonntag sicher) – ThanksForAllTheFish
Das Problem wurde in Hibernate Validator 5.3.0.Final behoben. –