Справочная реализация
Hibernate Validator — это свободная справочная реализация валидации компонентов. Проект изначально был запущен в 2005 году компанией JBoss в рамках Hibernate Annotations, стал независимым в 2007 году, а статус справочной реализации приобрел в 2009 году (с выходом Hibernate Validator 4). В настоящее время Hibernate Validator 5 реализует валидацию компонентов (версия 1.1) и добавляет кое-какие собственные возможности, в числе которых политика быстрого отказа. В соответствии с этим принципом программа прерывает текущую валидацию и возвращается после первого же нарушения ограничивающих условий. К другим характерным особенностям этой реализации относится API для программного конфигурирования ограничений, а также дополнительные встроенные ограничения.
На момент написания этой книги Hibernate Validator 5 был единственной реализацией, совместимой с Bean Validation 1.1. В Apache BVal применялась спецификация Bean Validation 1.0, в настоящее время идет процесс сертификации на соответствие версии 1.1. Oval не реализует полную спецификацию Bean Validation, но умеет обрабатывать связанные с ней ограничения.
Написание ограничений
До сих пор мы говорили об ограничениях, применяемых к нескольким уровням вашего приложения. Такие ограничения могут быть написаны одновременно на нескольких языках, с применением разных технологий. Но я также упоминал и о дублировании валидационного кода. Итак, насколько сложно будет применить ограничение в ваших классах Java, использующих валидацию компонентов? В листинге 3.1 показано, насколько просто добавлять ограничения в бизнес-модель.
public class Book {
··@NotNull
··private String title;
··@NotNull @Min(2)
··private Float price;
··@Size(max = 2000)
··private String description;
··private String isbn;
··private Integer nbOfPage;
··// Конструкторы, геттеры, сеттеры
}
В листинге 3.1 показан класс Book с атрибутами, конструкторами, геттерами, сеттерами и аннотациями. Некоторые из этих атрибутов аннотированы с применением встроенных ограничений, таких как @NotNull, @Min и @Size. Так мы указываем валидационной среде исполнения, что заголовок title книги не может быть равен нулю и описание description не может превышать 2000 символов. Как видите, к атрибуту могут быть применены несколько ограничений (например, price не может быть равно нулю и его значение не может быть меньше 2).
Внутренняя организация ограничения
Ограничение определяется как комбинация ограничивающей аннотации и списка реализаций валидации ограничения. Ограничивающая аннотация применяется с типами, методами, полями или другими ограничивающими аннотациями (в случае с составными элементами). В большинстве спецификаций Java EE разработчики используют заранее определенные аннотации (например, @Entity, @Stateless и @Path). Но в случае с CDI (об этом шла речь в предыдущей главе) и при валидации компонентов программистам приходится писать собственные аннотации. Известно, что ограничение при валидации компонентов состоит из:
• аннотации, определяющей ограничение;
• списка классов, реализующих ограничивающий алгоритм с заданным типом.
В то же время аннотация выражает ограничение, действующее в предметной модели. Таким образом, реализация валидации определяет, удовлетворяет ли конкретное значение заданному ограничению.
Ограничение, применяемое с JavaBean, выражается с помощью одной или нескольких аннотаций. Аннотация считается ограничивающей, если применяемая в ней политика хранения содержит RUNTIME и если сама она аннотирована javax.validation.Constraint (эта аннотация ссылается на список реализаций валидации). В листинге 3.2 показана ограничивающая аннотация NotNull. Как видите, @Constraint(validatedBy = {}) указывает на класс реализации NotNullValidator.
@Target({METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER})
@Retention(RUNTIME)
@Documented
@Constraint(validatedBy = NotNullValidator.class)
public @interface NotNull {
··String message() default "{javax.validation.constraints.NotNull.message}";
··Class >[] groups() default {};
··Class extends Payload>[] payload() default {};
}
Ограничивающие аннотации — это самые обычные аннотации, поэтому с ними приходится определять своеобразные метааннотации: