Я столкнулся с неожиданным поведением в Hibernate Validator и JSF. Я хотел бы знать, является ли такое поведение ошибкой или недоразумением в моих собственных ожиданиях.
У меня есть страница Facelets:
<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html">
<h:body>
<h:form>
<h:inputText value="#{backingBean.someClass.someField}"/>
<h:commandButton value="submit" action="#{backingBean.submit1()}"/>
</h:form>
</h:body>
</html>
И у меня есть этот компонент поддержки:
import java.util.Set;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.RequestScoped;
import javax.validation.ConstraintViolation;
import javax.validation.Validation;
import javax.validation.Validator;
import javax.validation.ValidatorFactory;
import org.hibernate.validator.constraints.NotEmpty;
@ManagedBean
@RequestScoped
public class BackingBean {
private SomeClass someClass = new SomeSubClass();
public SomeClass getSomeClass() {
return someClass;
}
public void setSomeClass(SomeClass someClass) {
this.someClass = someClass;
}
public void submit1() {
System.out.println("BackingBean: " + someClass.getSomeField());
((SomeSubClass) someClass).submit2();
}
public static class SomeClass {
private String someField;
public String getSomeField() {
return someField;
}
public void setSomeField(String someField) {
this.someField = someField;
}
}
public static class SomeSubClass extends SomeClass {
@NotEmpty
private String someField;
private void submit2() {
System.out.println("SomeSubClass: " + someField);
}
}
public static void main(String[] args) {
ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
Validator validator = factory.getValidator();
SomeClass someClass = new SomeSubClass();
someClass.setSomeField("ham");
Set<ConstraintViolation<SomeClass>> errors = validator.validate(someClass);
for (ConstraintViolation<SomeClass> error : errors) {
System.out.println(error);
}
}
}
Обратите внимание, что SomeSubClass.someField
имеет то же имя, что и частная переменная в родительском классе. Это не имеет значения, потому что вы не можете затенять частное поле.
Обратите внимание на две вещи:
- Если вы запустите метод
main
вBackingBean
, валидатор всегда будет возвращать ошибку проверки (сообщение «может быть не пустым»), потому чтоSomeSubClass.someField
всегда имеет значение NULL. Мне такое поведение кажется правильным. - If you submit the form with a blank value, you will receive a "may not be empty" error message; if you enter a value, it will pass validation, but you will see in the console that the value of
SomeSubClass.someField
is still null. This behaviour seems incorrect to me.- If you change the name of
SomeSubClass.someField
tosomeField2
, you may submit the form with an empty value. This behaviour seems incorrect to me.
- If you change the name of
Похоже, что фаза проверки JSF и валидатор Hibernate не согласны с этим поведением. JSF применяет валидатор @NotEmpty
частного поля в подклассе к полю с тем же именем в родительском классе, но Hibernate Validator не показывает это поведение при изолированном тестировании.
Кто-нибудь может объяснить такое поведение? Это ошибка или недоразумение в моих ожиданиях?
С использованием:
- Сервер GlassFish с открытым исходным кодом, версия 3.1.2.2
- Мохарра 2.1.6
- Валидатор гибернации 4.3.0.Final