Одной из ключевых особенностей Vaadin 7 является его тесная интеграция с JSR 303, также известная как Bean Validation. Эта статья подробно расскажет о том, как добиться такой проверки.
Для начала давайте рассмотрим простой пример использования: пользователь заполняет форму. Когда возникает ошибка, пользователь визуально информируется об ошибке. Отправка формы возможна только после исправления всех ошибок. Это общий сценарий, и мы реализуем его вместе с Ваадином.
Предпосылки
Перед тем, как идти дальше, необходимо выполнить несколько условий:
- Во-первых, нам понадобится реализация JSR 303. В этом случае мы будем использовать Hibernate Validator (который также является эталонной реализацией JSR-303)
- Следующим шагом является определение базового компонента. В нашем случае мы будем делать это простым (и глупым): Person и связанные с ним атрибуты. Имя и фамилия не должны быть пустыми, в то время как электронная почта, если она существует, должна соответствовать шаблону электронной почты.
import java.util.Date; import javax.validation.constraints.NotNull; import javax.validation.constraints.Size; import org.hibernate.validator.constraints.Email; public class Person { private long id; private Gender gender; @Size(max = 250) @NotNull private String firstName; @Size(max = 250) @NotNull private String lastName; @Size(max = 250) @Email private String email; private Date birthdate; // Getters and setters }
Обратите внимание, что ограничения NotNull и Size исходят от самого JSR (пакет javax.validation.constraints), в то время как электронная почта поступает от Hibernate Validator (пакет org.hibernate.validator.constraints). Несмотря на связь, учитывая добавленную стоимость, у меня нет никаких сомнений в ее использовании.
Пользователи
Как только боб аннотирован, это только вопрос:
- Создание нового бина: это довольно очевидно
- Vaadin 7, исключив класс Form, нам нужно поместить компонент в его замену FieldGroup.
- Затем нам нужно получить ссылку на каждое отображаемое поле (в отличие от формы, где было значение по умолчанию, и мы могли бы его настроить). FieldGroup имеет методы для создания каждого поля и привязки его к базовому свойству компонента.
- Каждое поле затем устанавливает свой валидатор (при необходимости)
- Наконец, каждое поле должно быть установлено в нашем макете так, как нужно
Последние штрихи
Есть пара завершающих штрихов, необходимых для достижения отточенного пользовательского интерфейса.
Нет предварительной проверки
Если все предыдущие фрагменты кода выполняются в методе init (), пользователи увидят ошибки проверки имени и фамилии при отображении страницы, поскольку все атрибуты компонента изначально пусты.
Таким образом, крайне желательно устанавливать валидаторы только после первого отображения страницы без ошибок. Это может быть сделано, когда поле теряет фокус. Тем не менее, это должно быть сделано, даже если поле никогда не получает фокус. Таким образом, это должно быть сделано в двух местах:
- В каждом проверенном поле слушателя размытия
- Непосредственно перед фиксацией FieldGroup
Обратите внимание, что поскольку мы не храним ссылку на установленный валидатор, мы должны удалить его перед установкой, иначе это приведет к двойной (или более) одинаковой валидации.
Для ясности, вот код ValidatorUtils:
Правильный виджет для правильного типа данных
This point has nothing to do with validation, but it brings a nice finishing touch to the user interface. Did you notice that when we built the gender field, we passed a Select parameter and presto, the return field was a select. Wouldn’t it be better if the birthdate field would be displayed as a true DateField? We can try this:
Unfortunately, this doesn’t work as Vaadin loudly complains with a com.vaadin.data.fieldgroup.FieldGroup$BindException: Unable to build a field of type com.vaadin.ui.DateField for editing java.util.Date. This means that in contrast to the old Form, FieldGroup doesn’t handle date fields. As both use field factories (albeit of a different type), this is easily corrected. We just have to create a field group factory that return DateField when passed Date attributes and delegates to the default field group factory otherwise.
Затем мы устанавливаем экземпляр этой фабрики в группу полей, передавая нужный нам тип поля.
Удалить начальные уродливые нулевые значения
Finally, since the Person bean is initialized with null values, null appears when the page first loads. For a end-user, this is not particularly desirable. We have to cast the field returned by the field group to a more friendly type and call the setNullRepresentation() method.
Conclusion
In this article, we used the power of Vaadin 7 to easily create a submit form, complete with validation coming from JSR 303 annotations. The full sources of this article can be found on Github.