«1. Обзор
Легко злоупотребить ограничениями проверки bean-компонентов. Например, мы можем случайно украсить атрибут String ограничением @Future. Такие ошибки могут привести к непредсказуемым ошибкам во время выполнения.
К счастью, обработчик аннотаций Hibernate Validator помогает обнаруживать эти проблемы во время компиляции. Благодаря ошибкам, которые он выдает, мы можем отловить эти ошибки раньше.
В этом уроке мы рассмотрим, как настроить процессор, и рассмотрим некоторые распространенные проблемы, которые он может нам найти.
2. Конфигурация
2.1. Установка
Давайте начнем с добавления зависимости обработчика аннотаций в наш pom.xml:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.6.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
<compilerArgs>
<arg>-Averbose=true</arg>
<arg>-AmethodConstraintsSupported=true</arg>
<arg>-AdiagnosticKind=ERROR</arg>
</compilerArgs>
<annotationProcessorPaths>
<path>
<groupId>org.hibernate.validator</groupId>
<artifactId>hibernate-validator-annotation-processor</artifactId>
<version>6.2.0.Final</version>
</path>
</annotationProcessorPaths>
</configuration>
</plugin>
Следует отметить, что версия 7 этого инструмента совместима только с ограничениями jakarta.validation:
<dependency>
<groupId>jakarta.validation</groupId>
<artifactId>jakarta.validation-api</artifactId>
<version>3.0.1</version>
</dependency>
процессор также предоставляет руководство по его настройке для основных IDE Java.
2.2. Параметры компилятора
Давайте настроим параметры компилятора нашего процессора:
<compilerArgs>
<arg>-Averbose=true</arg>
<arg>-AmethodConstraintsSupported=true</arg>
<arg>-AdiagnosticKind=ERROR</arg>
</compilerArgs>
Во-первых, параметр DiagnosticKind нацелен на уровень ведения журнала. Предпочтительно оставить значение ERROR по умолчанию, чтобы выявить проблемы во время компиляции. Все допустимые значения указаны в перечислении Diagnostic.Kind.
Далее, если мы хотим ограничить проверку аннотаций только геттерами, мы должны установить для параметра methodConstraintsSupported значение false.
Здесь мы установили для verbose значение true, чтобы получить больше вывода, но мы можем установить его и в false, если нам не нужно много вывода журнала.
3. Распространенные проблемы с ограничениями
Процессор аннотаций поставляется с набором предопределенных ошибок для проверки. Рассмотрим подробнее три из них на примере простого класса Message:
public class Message {
// constructor omitted
}
3.1. Только геттеры могут быть аннотированы
Во-первых, этой проблемы не должно быть с параметрами процессора по умолчанию. Как следует из названия, он появляется, когда мы аннотируем не-геттер-метод. Нам нужно установить для параметра methodConstraintsSupported значение true, чтобы разрешить это.
Давайте добавим три аннотированных метода в наш класс Message:
@Min(3)
public boolean broadcast() {
return true;
}
@NotNull
public void archive() {
}
@AssertTrue
public boolean delete() {
return false;
}
Затем мы установим для параметра methodConstraintsSupported значение false в нашей конфигурации:
<compilerArgs>
<arg>AmethodConstraintsSupported=false</arg>
</compilerArgs>
Наконец, эти три метода заставят процессор обнаружить наш проблема:
[ERROR] COMPILATION ERROR :
[INFO] -------------------------------------------------------------
[ERROR] ${home}\baeldung\tutorials\javaxval\src\main\java\com\baeldung\javaxval\methodvalidation\model\ReservationManagement.java:[25,4] error: Constraint annotations must not be specified at methods, which are no valid JavaBeans getter methods.
[ERROR] ${home}\baeldung\tutorials\javaxval\src\main\java\com\baeldung\javaxval\hibernate\validator\ap\Message.java:[55,4] error: Constraint annotations must not be specified at methods, which are no valid JavaBeans getter methods.
[ERROR] ${home}\baeldung\tutorials\javaxval\src\main\java\com\baeldung\javaxval\hibernate\validator\ap\Message.java:[38,5] error: Constraint annotations must not be specified at methods, which are no valid JavaBeans getter methods.
[ERROR] ${home}\baeldung\tutorials\javaxval\src\main\java\com\baeldung\javaxval\hibernate\validator\ap\Message.java:[47,4] error: Constraint annotations must not be specified at methods, which are no valid JavaBeans getter methods.
[INFO] 4 errors
[INFO] -------------------------------------------------------------
[INFO] ------------------------------------------------------------------------
[INFO] BUILD FAILURE
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 5.457 s
[INFO] Finished at: 2022-01-20T21:42:47Z
[INFO] ------------------------------------------------------------------------
[ERROR] Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.6.1:compile (default-compile) on project javaxval: Compilation failure: Compilation failure:
[ERROR] ${home}\baeldung\tutorials\javaxval\src\main\java\com\baeldung\javaxval\methodvalidation\model\ReservationManagement.java:[25,4] error: Constraint annotations must not be specified at methods, which are no valid JavaBeans getter methods.
[ERROR] ${home}\baeldung\tutorials\javaxval\src\main\java\com\baeldung\javaxval\hibernate\validator\ap\Message.java:[55,4] error: Constraint annotations must not be specified at methods, which are no valid JavaBeans getter methods.
[ERROR] ${home}\baeldung\tutorials\javaxval\src\main\java\com\baeldung\javaxval\hibernate\validator\ap\Message.java:[38,5] error: Constraint annotations must not be specified at methods, which are no valid JavaBeans getter methods.
[ERROR] ${home}\baeldung\tutorials\javaxval\src\main\java\com\baeldung\javaxval\hibernate\validator\ap\Message.java:[47,4] error: Constraint annotations must not be specified at methods, which are no valid JavaBeans getter methods.
Интересно отметить, что проблема затрагивает метод удаления, хотя технически он правильно аннотирован.
В следующих разделах мы установим для параметра methodConstraintsSupported значение true.
3.2. Только непустые методы могут быть аннотированы
Эта проблема гласит, что мы не должны украшать пустые методы проверками ограничений. Мы можем увидеть это в действии, аннотировав метод архивации в нашем классе Message:
@NotNull
public void archive() {
}
Это заставляет процессор вызывать ошибку:
[ERROR] COMPILATION ERROR :
[INFO] -------------------------------------------------------------
[ERROR] ${home}\baeldung\tutorials\javaxval\src\main\java\com\baeldung\javaxval\hibernate\validator\ap\Message.java:[45,4] error: Void methods may not be annotated with constraint annotations.
[INFO] 1 error
[INFO] -------------------------------------------------------------
[INFO] ------------------------------------------------------------------------
[INFO] BUILD FAILURE
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 4.078 s
[INFO] Finished at: 2022-01-20T21:35:08Z
[INFO] ------------------------------------------------------------------------
[ERROR] Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.6.1:compile (default-compile) on project javaxval: Compilation failure
[ERROR] ${home}\baeldung\tutorials\javaxval\src\main\java\com\baeldung\javaxval\hibernate\validator\ap\Message.java:[45,4] error: Void methods may not be annotated with constraint annotations.
3.3. Неподдерживаемый тип для аннотации
Эта последняя проблема является наиболее распространенной. Это происходит, когда целевой тип данных аннотации не соответствует целевому свойству. Чтобы увидеть его в действии в нашем классе Message, давайте добавим неправильно аннотированный атрибут String в наш класс Message:
@Past
private String createdAt;
Произойдет ошибка из-за аннотации @Past. На самом деле, только типы даты могут использовать это ограничение:
[ERROR] COMPILATION ERROR :
[INFO] -------------------------------------------------------------
[ERROR] ${home}\baeldung\tutorials\javaxval\hibernate\validator\ap\Message.java:[20,5] error: The annotation @Past is disallowed for this data type.
[INFO] 1 error
[INFO] -------------------------------------------------------------
[INFO] ------------------------------------------------------------------------
[INFO] BUILD FAILURE
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 4.892 s
[INFO] Finished at: 2022-01-20T21:29:15Z
[INFO] ------------------------------------------------------------------------
[ERROR] Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.6.1:compile (default-compile) on project javaxval: Compilation failure
[ERROR] ${home}\baeldung\tutorials\javaxval\src\main\java\com\baeldung\javaxval\hibernate\validator\ap\Message.java:[20,5] error: The annotation @Past is disallowed for this data type.
Мы получим аналогичную ошибку, если применим неправильную аннотацию к методу с неподдерживаемым типом возвращаемого значения:
@Min(3)
public boolean broadcast() {
return true;
}
Сообщение об ошибке процессора то же, что и предыдущий:
[ERROR] COMPILATION ERROR :
[INFO] -------------------------------------------------------------
[ERROR] ${home}\baeldung\tutorials\javaxval\src\main\java\com\baeldung\javaxval\hibernate\validator\ap\Message.java:[37,5] error: The annotation @Min is disallowed for the return type of this method.
[INFO] 1 error
[INFO] -------------------------------------------------------------
[INFO] ------------------------------------------------------------------------
[INFO] BUILD FAILURE
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 3.761 s
[INFO] Finished at: 2022-01-20T21:38:28Z
[INFO] ------------------------------------------------------------------------
[ERROR] Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.6.1:compile (default-compile) on project javaxval: Compilation failure
[ERROR] ${home}\baeldung\tutorials\javaxval\src\main\java\com\baeldung\javaxval\hibernate\validator\ap\Message.java:[37,5] error: The annotation @Min is disallowed for the return type of this method.
4. Заключение
В этой статье мы попробовали обработчик аннотаций Hibernate Validator.
Сначала мы установили его и настроили его параметры. Затем мы исследовали его поведение с помощью трех общих проблем с ограничениями.
Как всегда, пример кода можно найти на GitHub.