Encodera

Thanks for reading!

Donate to the site — we work hard for you.

Contents

Validating data

A client may send an empty title or a thousand-page text. Checking every field with if is tedious. The Jakarta Validation standard lets you describe the rules as annotations right on the DTO fields, and Spring checks them before calling the controller method. An invalid request gets a 400 response, and the method never even starts.

Setup

Validation is a separate module. Add the starter to pom.xml (on start.spring.io it is called Validation):

<!-- pom.xml -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-validation</artifactId>
</dependency>

The starter brings in Hibernate Validator — the most widely used implementation of the standard.

Rules on fields

// src/main/java/com/example/blog/NewPostRequest.java
package com.example.blog;
 
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.Size;
 
public record NewPostRequest(
        @NotBlank @Size(max = 120) String title,
        @NotBlank String body,
        @NotBlank String author) {
}

@NotBlank rejects null, an empty string and a string of spaces only. @Size(max = 120) limits the title length.

Switching the check on

// src/main/java/com/example/blog/PostController.java
@PostMapping
public ResponseEntity<Post> create(@Valid @RequestBody NewPostRequest request) {
    Post post = postService.create(request);
    return ResponseEntity.created(URI.create("/api/posts/" + post.id())).body(post);
}

The @Valid annotation (from the jakarta.validation package) triggers the check. Add it to the update method too.

What the client gets

curl -i -X POST http://localhost:8080/api/posts \
  -H "Content-Type: application/json" \
  -d '{"title":"","body":"x"}'
HTTP/1.1 400
 
{"timestamp":"2026-10-04T08:50:07.790Z","status":400,"error":"Bad Request","path":"/api/posts"}

The post was not created. Spring writes the details only to the log (line shortened):

WARN ... Resolved [org.springframework.web.bind.MethodArgumentNotValidException: Validation failed for argument [0] ... with 2 errors: [Field error in object 'newPostRequest' on field 'author' ...

The client, though, needs to know which fields are wrong. In the next lesson we will return a list of errors per field.

Common annotations

AnnotationChecks
@NotNullThe value is not null
@NotBlankA string is not empty and not just spaces
@Size(min, max)String length or list size
@Min, @MaxNumber bounds
@EmailLooks like an email address
@Pattern(regexp)The string matches a regular expression
@Past, @FutureA date in the past or future

Your own message

Every annotation has a message parameter:

@NotBlank(message = "Title is required") String title

Without it Hibernate Validator uses a standard text in the language from the request's Accept-Language header, or the system language when there is no header: must not be blank for English, не должно быть пустым for Russian.

Common mistake

If you forget @Valid before @RequestBody, the field annotations do nothing. There is no error — a post with an empty title is quietly saved. After adding rules, always test them with an invalid request and make sure a 400 comes back.

Thanks for reading!

Donate to the site — we work hard for you.