Persistence top

Get started with Spring Data JPA through the reference Learn Spring Data JPA course:

>> CHECK OUT THE COURSE

1. Overview

It's easy to misuse bean validation constraints. For example, we might accidentally decorate a String attribute with the @Future constraint. Such mistakes can lead to unpredictable errors at runtime.

Fortunately, the Hibernate Validator Annotation Processor helps detect those issues at compile-time. Thanks to the errors it throws, we can catch these bugs earlier.

In this tutorial, we'll explore how to configure the processor, and we'll look at some common problems it can find for us.

2. Configuration

2.1. Installation

Let's start by adding the annotation processor dependency to our 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>

We should note that version 7 of this tool is only compatible with the jakarta.validation constraints:

<dependency>
    <groupId>jakarta.validation</groupId>
    <artifactId>jakarta.validation-api</artifactId>
    <version>3.0.1</version>
</dependency>

The processor also provides guidance on how to set it up for the major Java IDEs.

2.2. Compiler Options

Let's set up our processor compiler options:

<compilerArgs>
    <arg>-Averbose=true</arg>
    <arg>-AmethodConstraintsSupported=true</arg>
    <arg>-AdiagnosticKind=ERROR</arg>
</compilerArgs>

First, the diagnosticKind option targets the logging level. It's preferable to keep the default ERROR value in order to catch problems at compile-time. All allowed values are referenced in the Diagnostic.Kind enum.

Next, if we want to restrict annotation validation to getters only, we should set the methodConstraintsSupported option to false.

Here, we've set verbose to true to get more output, but we can set it to false if we don't want a lot of log output.

3. Common Constraint Problems

The annotation processor comes with a set of predefined errors to check. Let's have a closer look at three of them by using a simple Message class as an example:

public class Message {
    // constructor omitted
}

3.1. Only Getters Can Be Annotated

First, this problem shouldn't exist with the processor's default options. As the name implies, it pops up when we annotate a non-getter method. We need to set the methodConstraintsSupported option to true to allow this.

Let's add three annotated methods to our Message class:

@Min(3)
public boolean broadcast() {
    return true;
}

@NotNull
public void archive() {
}

@AssertTrue
public boolean delete() {
    return false;
}

Next, we set the methodConstraintsSupported option to false in our config:

<compilerArgs>
    <arg>AmethodConstraintsSupported=false</arg>
</compilerArgs>

Finally, the three methods will cause the processor to detect our problem:

[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.

It's interesting to notice that the delete method is affected by the issue, even though technically, it's properly annotated.

For the next sections, we'll set the methodConstraintsSupported option back to true.

3.2. Only Non-Void Methods Can Be Annotated

This problem states that we shouldn't decorate void methods with constraint validations. We can see it in action by annotating an archive method in our Message class:

@NotNull
public void archive() {
}

It causes the processor to raise an error:

[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. Unsupported Type for an Annotation

This final problem is the most common. It occurs when the annotation target data type doesn't match the target property. To see it in action in our Message class, let's add an incorrectly annotated String attribute to our Message class:

@Past 
private String createdAt;

An error will occur due to the @Past annotation. In fact, only date types can use this constraint:

[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.

We'll get a similar error if we apply the wrong annotation to a method having an unsupported  return type:

@Min(3)
public boolean broadcast() { 
    return true;
}

The processor error message is the same as the previous one:

[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. Conclusion

In this article, we tried the Hibernate Validator Annotation Processor.

First, we installed it and configured its options. Then, we explored its behavior with three common constraint problems.

As always, the example code can be found over on GitHub.

Persistence bottom
Get started with Spring Data JPA through the reference Learn Spring Data JPA course: >> CHECK OUT THE COURSE
Persistence footer banner
Comments are closed on this article!