Start Learning
Javaneer
Back to stage
Module 2·Building Web APIs

Validating Input

Bean Validation with @Valid and constraint annotations, and turning failures into helpful responses.

16 min readIntermediate
On this page

Never trust input. A client might POST a book with a blank title, a negative copy count, or a malformed ISBN. Checking every field by hand in every controller is tedious and easy to get wrong. Bean Validation lets you declare the rules once, as annotations, and have Spring enforce them automatically.

Add the starter

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

Declare constraints on the DTO

Annotate the request record's components with constraints:

record CreateBookRequest(
    @NotBlank @Pattern(regexp = "\\d{3}-\\d{10}", message = "must be an ISBN-13")
    String isbn,

    @NotBlank @Size(max = 200)
    String title,

    @NotBlank
    String author,

    @Min(1) @Max(1000)
    int copies
) {}

Common constraints: @NotNull, @NotBlank, @Size, @Min/@Max, @Email, @Pattern, @Positive. Each carries an optional message.

Trigger it with @Valid

A constraint annotation does nothing until you ask Spring to validate. Add @Valid to the @RequestBody parameter:

@PostMapping
ResponseEntity<BookResponse> add(@Valid @RequestBody CreateBookRequest request) {
    // reached only if `request` is valid
    ...
}

If validation fails, Spring throws MethodArgumentNotValidException before your method runs - the invalid data never reaches your logic. By default that becomes a 400 Bad Request. In the next lesson you'll shape that into a helpful error body.

Validation is the bouncer at the door

Your controller is the club; the guests are incoming requests. A bouncer checks IDs at the door so nobody underage ever gets inside - the club staff never have to worry about it. @Valid is that bouncer: bad requests are turned away at the boundary, so your business logic only ever deals with data it can trust.

Validate at the edge, trust within

Do validation once, at the web boundary. Everything past a validated @RequestBody can assume the data is well-formed, so your service and domain code stay free of defensive null checks and re-validation.

Guard the create endpoint

BookVault's CreateBookRequest must reject: a blank title, an ISBN that isn't 13 digits in the NNN-NNNNNNNNNN form, and a copies value below 1. Which constraint annotation handles each, and what one annotation on the controller parameter makes Spring enforce them?

What makes Spring actually enforce a DTO's @NotBlank/@Size constraints on a request body?

Key takeaways

  • Bean Validation declares input rules as annotations (@NotBlank, @Size, @Min, @Pattern…) on DTO fields.
  • spring-boot-starter-validation enables it.
  • @Valid on a @RequestBody parameter triggers validation; failures throw MethodArgumentNotValidException (a 400) before your method runs.
  • Validate once at the web boundary so downstream code can trust its inputs.
  • Each constraint can carry a custom message for clearer error responses.
Was this lesson helpful?
Edit this page on GitHub