LearnAI ToolsCareerPractice BuildsPlayContact
Lesson 1918 min read

Validation with @Valid

Add Bean Validation annotations like @NotNull and @Size to your entity classes, and enforce them automatically in controllers with @Valid.

Introduction

Right now, your CRUD API accepts absolutely anything a client sends: an empty name, a malformed email, a negative age. Manually checking every field at the top of every controller method quickly becomes repetitive and error-prone. Bean Validation is a Java standard that lets you declare constraints directly on your model classes, and Spring Boot enforces them automatically the moment you add one annotation to a controller parameter: @Valid.

What You Will Learn
  • How to add the Bean Validation starter to your project.
  • The most commonly used validation annotations.
  • How @Valid triggers validation automatically before your method body runs.
  • What Spring Boot's default response looks like when validation fails.

Adding the Validation Starter

Bean Validation is not included in spring-boot-starter-web by default in recent Spring Boot versions, so add spring-boot-starter-validation explicitly.

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

Common Validation Annotations

These annotations come from the jakarta.validation.constraints package and are placed directly on entity or request model fields.

AnnotationRule
@NotNullValue must not be null
@NotBlankString must not be null and must contain at least one non-whitespace character
@NotEmptyCollection or String must not be null or empty
@Size(min, max)String or collection length must fall within the given range
@EmailString must be a syntactically valid email address
@Min / @MaxNumeric value must be at least / at most the given value
@PositiveNumeric value must be greater than zero
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.validation.constraints.Email;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.Size;
@Entity
public class Student {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@NotBlank(message = "Name is required")
@Size(min = 2, max = 100, message = "Name must be between 2 and 100 characters")
private String name;
@NotBlank(message = "Email is required")
@Email(message = "Email must be a valid address")
private String email;
// getters and setters
public Long getId() { return id; }
public void setId(Long id) { this.id = id; }
public String getName() { return name; }
public void setName(String name) { this.name = name; }
public String getEmail() { return email; }
public void setEmail(String email) { this.email = email; }
}

Triggering Validation with @Valid

Adding these annotations to the class does nothing by itself — Spring only runs the checks when you mark the @RequestBody parameter with @Valid.

@PostMapping
public ResponseEntity<Student> createStudent(@Valid @RequestBody Student student) {
Student saved = studentRepository.save(student);
return ResponseEntity.status(HttpStatus.CREATED).body(saved);
}

@Valid must come before @RequestBody, or immediately alongside it — Spring reads it as a signal to run validation on that parameter's value before the method body executes at all. If validation fails, your method body never runs.

What Happens on Failure

When validation fails, Spring Boot throws a MethodArgumentNotValidException, which its default exception handling converts into a 400 Bad Request response describing exactly which fields failed and why.

Example Request and Response

Click Run to see what this code prints.

Customizing the Error Format

The exact shape of this error response is Spring Boot's default, and it isn't very client-friendly on its own. The next lesson covers @ControllerAdvice and @ExceptionHandler, which let you catch MethodArgumentNotValidException and shape the response exactly how you want.

Common Mistakes

Avoid These Mistakes
  • Adding validation annotations to a class but forgetting @Valid on the controller parameter — without it, nothing is ever checked.
  • Confusing @NotNull with @NotBlank on a String field — @NotNull allows an empty string "" to pass, which is rarely what you want for required text fields.
  • Forgetting to add spring-boot-starter-validation, causing @Valid to be silently ignored in newer Spring Boot versions.
  • Putting validation only on the entity and not on separate request DTOs, once your project grows to use DTOs instead of exposing entities directly.

Best Practices

  • Always pair validation annotations on a model class with @Valid on every controller parameter that accepts one.
  • Use @NotBlank rather than @NotNull for required String fields, since it also rejects empty and whitespace-only values.
  • Write clear, specific messages on each constraint annotation — they surface directly in error responses.
  • Handle validation failures centrally with @ControllerAdvice rather than checking BindingResult manually in every method.

Frequently Asked Questions

Not by default in the same way. For method-level validation of simple parameters, you annotate the controller class itself with @Validated (from org.springframework.validation.annotation.Validated) and add constraints directly on the parameters.

@Valid is the standard Bean Validation annotation and is what you use on @RequestBody parameters. @Validated is a Spring-specific annotation that additionally supports validation groups and enables method-level parameter validation on a class.

Yes, using @Constraint together with a class implementing ConstraintValidator. This is useful for rules that don't fit the built-in annotations, like checking a username is unique.

Before. @Valid runs as part of Spring's request-handling pipeline, prior to your controller method body executing, so invalid data never reaches your service or repository layer.

Key Takeaways

  • Bean Validation annotations like @NotBlank, @Size, and @Email are declared directly on model fields.
  • @Valid on a @RequestBody parameter triggers those checks automatically before the controller method runs.
  • Failed validation throws MethodArgumentNotValidException, which Spring Boot converts into a 400 Bad Request by default.
  • @Validated extends validation support to path variables and request parameters at the class level.

Summary

Your API now rejects invalid data automatically, before it ever reaches your database. Next, you'll learn how to take full control of error responses — including validation failures — using @ControllerAdvice and @ExceptionHandler.

Next Lesson →

Global Exception Handling