Validating input
A client can send anything: an empty title, a megabyte of text, a negative number. Checking every field with if takes long, and it is easy to miss something. Jakarta Validation lets you describe the rules with annotations right on the fields — @NotBlank, @Size, @Email — and the framework does the checking. In Quarkus the standard is implemented by Hibernate Validator.
Adding the extension
In the project folder run:
./mvnw quarkus:add-extension -Dextensions="hibernate-validator"The quarkus-hibernate-validator dependency appears in pom.xml. Dev mode notices the pom.xml change and restarts the application; hibernate-validator appears in the Installed features line.
Rules on the record
The annotations go on the components of the NewPost record:
// src/main/java/com/example/blog/NewPost.java
package com.example.blog;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.Size;
public record NewPost(
@NotBlank
@Size(max = 100)
String title,
@NotBlank(message = "Post text must not be empty")
String body) {
}The title must not be blank or longer than 100 characters, the text must not be blank. message sets your own error message.
Turning validation on in the resource
To make Quarkus check the request body, put @Valid before the parameter (import jakarta.validation.Valid):
// src/main/java/com/example/blog/PostResource.java
@POST
public Response create(@Valid NewPost newPost) {
Post post = postService.create(newPost.title(), newPost.body());
return Response.created(URI.create("/posts/" + post.id()))
.entity(post)
.build();
}If the data is invalid, the method is not even called — Quarkus answers 400 at once:
curl -i -X POST http://localhost:8080/posts \
-H "Content-Type: application/json" \
-d '{"title":"","body":""}'HTTP/1.1 400 Bad Request
Content-Type: application/json
validation-exception: true
{"title":"Constraint Violation","status":400,"violations":[
{"field":"create.newPost.title","message":"must not be blank"},
{"field":"create.newPost.body","message":"Post text must not be empty"}]}
field shows the method, the parameter and the field, message the error text. The JSON is split into lines for readability.
Message language
The standard messages are translated into many languages. Quarkus picks the language from the Accept-Language header if that language is listed in the settings:
# src/main/resources/application.properties
quarkus.default-locale=en
quarkus.locales=en,ruA request with -H "Accept-Language: ru" gets the Russian text не должно быть пустым; without the header the messages are in English.
Common annotations
| Annotation | What it checks |
|---|---|
@NotNull | The value is not null |
@NotBlank | The string is not empty and not only spaces |
@Size(min, max) | The length of a string or the size of a list |
@Min, @Max | The bounds of a number |
@Email | Looks like an email address |
@Pattern(regexp) | The string matches a regular expression |
Checking parameters
The annotations also work on path and query parameters:
// src/main/java/com/example/blog/PostResource.java
@GET
public List<Post> list(@QueryParam("search") String search,
@QueryParam("limit") @DefaultValue("10") @Max(50) int limit) {
// ...
}A /posts?limit=100 request gets 400 with the message must be less than or equal to 50 for the list.limit field.
Common mistake
Without @Valid the annotations on the record check nothing. An empty post is saved silently:
curl -i -X POST http://localhost:8080/posts -H "Content-Type: application/json" -d '{"title":"","body":""}'HTTP/1.1 201 Created
{"id":3,"title":"","body":""}
The annotations on the fields only describe the rules; it is @Valid on the method parameter that runs the check.