Invalid inputs are the root of all evil! Or would you run your coffee maker on rocks?
How to start ?
We need the dependency:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
When do we validate?
As a rule of thumb for REST APIs: As soon as a controller method accepts a @RequestBody, it must be preceded by a @Valid!
Valid
@Valid (Standard Jakarta Validation): Placed on method parameters (like @RequestBody) or fields to trigger validation of nested objects.
Validated
It is a Spring-specific annotation. It is used at the class level when you want to validate @PathVariable or @RequestParam directly in the controller (e.g., @Min(1) Long id), or for validation groups.
Which endpoints are we validating?
- Post Because the client send use new data.
- Put / Patch When updating, the client also sends the modified data in the body. New values must also be checked for completeness and compliance with the rules (no stones, only water).
Why not GET or DELETE?
A GET request typically does not include a JSON body. We are simply requesting data.
When deleting a resource, we usually identify it by a unique ID, no JSON is sent along with the request either.
Validation Annotations
Spring Boot’s validation system supports all standard JSR-380 annotations:
-
@NotNullField cannot be null. -
@NotBlankString must not be null and must contain at least one non-whitespace character. -
@SizeValidates string length or collection size. -
@EmailChecks for a valid email format. -
@Min,@MaxEnsures numeric bounds. -
@Positive,@NegativeChecks numeric sign. -
@Past,@FutureValidates dates relative to the present.
Example
First, define the validation constraints on your data object (ideally a DTO, or the Entity in smaller projects):
@Entity
@Table(name = "tasks")
public class Task {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@NotBlank(message = "Title cannot be blank")
@Size(min = 3, max = 100, message = "Title must be between 3 and 100 characters")
private String title;
@NotBlank(message = "Description cannot be blank")
@Size(min = 5, max = 500, message = "Description must be between 5 and 500 characters")
private String description;
// Getters and Setters
}
Pro-Tip: Use DTOs instead of validating entities directly in real-world apps
Controller
@PostMapping("/projects/{projectId}/tasks")
public ResponseEntity<Task> createTask(
@PathVariable Long projectId,
@Valid @RequestBody Task task) {
Task createdTask = taskService.createTask(projectId, task);
return ResponseEntity.status(HttpStatus.CREATED).body(createdTask);
}
What happens here?
By placing ´@valid´ before @RequestBody, you instruct Spring Boot to check the incoming JSON payload against all constraints BEFORE executing the controller method body.
What Happens When Validation Fails?
If a client sends invalid data (e.g., an empty title), Spring Boot automatically intercepts the request, blocks execution, and throws a MethodArgumentNotValidException.
By default, Spring responds with an HTTP 400 Bad Request. You can customize the exact error message directly inside the annotation or via a messages.properties file:
@NotBlank(message = "Description cannot be blank")
Conclusion & Feedback
Validating inputs right at the controller layer keeps your business logic clean and your database safe from corrupted data.
Thank you for reading this far! I wrote this article while learning Spring Boot, and I'd love to hear your thoughts, tips, or best practices in the comments below.
Happy coding! 🚀
Top comments (0)