1. What is @Valid in Spring Boot?
The @Valid annotation is part of the Java Bean Validation (JSR-380) standard, implemented by libraries like Hibernate Validator. It is used to trigger validation on a Java object’s fields based on annotations such as @NotNull, @Size, @Email, etc.
2. Dependencies Required
Spring Boot starter automatically includes Hibernate Validator if you use the spring-boot-starter-web dependency.
But if you’re building a custom setup, add:
<!-- Maven -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
Or if you’re not using Spring Boot starter:
<dependency>
<groupId>jakarta.validation</groupId>
<artifactId>jakarta.validation-api</artifactId>
</dependency>
<dependency>
<groupId>org.hibernate.validator</groupId>
<artifactId>hibernate-validator</artifactId>
</dependency>
3. Simple Example: Validating a REST API Input
Step 1: Create a DTO class with validation constraints
import jakarta.validation.constraints.*;
public class UserRequest {
@NotBlank(message = "Name is required")
private String name;
@Email(message = "Email should be valid")
private String email;
@Min(value = 18, message = "Age should be at least 18")
@Max(value = 100, message = "Age should not be more than 100")
private int age;
// Getters and Setters
}
Step 2: Use @Valid in your controller
import org.springframework.web.bind.annotation.*;
import org.springframework.http.ResponseEntity;
import jakarta.validation.Valid;
@RestController
@RequestMapping("/api/users")
public class UserController {
@PostMapping
public ResponseEntity<String> createUser(@RequestBody @Valid UserRequest request) {
return ResponseEntity.ok("User is valid!");
}
}
3. How Validation Errors Are Handled
If the validation fails, Spring Boot will throw a MethodArgumentNotValidException automatically.
Default response (without custom handler):
{
"timestamp": "2025-07-12T10:00:00.123+00:00",
"status": 400,
"errors": [
"Name is required",
"Age should be at least 18"
]
}
4. Customize Error Response Using @ControllerAdvice
You can customize the error response by writing a global exception handler.
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import java.util.*;
import java.util.stream.Collectors;
@RestControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(MethodArgumentNotValidException.class)
public ResponseEntity<Map<String, Object>> handleValidationException(MethodArgumentNotValidException ex) {
List<String> errors = ex.getBindingResult()
.getFieldErrors()
.stream()
.map(error -> error.getField() + ": " + error.getDefaultMessage())
.collect(Collectors.toList());
Map<String, Object> response = new HashMap<>();
response.put("status", HttpStatus.BAD_REQUEST.value());
response.put("errors", errors);
return new ResponseEntity<>(response, HttpStatus.BAD_REQUEST);
}
}
5. Validating Path Variables and Request Parameters
You can also use @Valid or @Validated with query parameters or path variables.
import jakarta.validation.constraints.Min;
import org.springframework.validation.annotation.Validated;
@RestController
@Validated
public class ProductController {
@GetMapping("/products/{id}")
public String getProductById(@PathVariable @Min(1) Long id) {
return "Product ID: " + id;
}
}
Note: For validation of primitives or simple types, use @Validated at the class level instead of @Valid.
6. Nested Object Validation with @Valid
public class OrderRequest {
@NotNull
private String orderId;
@Valid
private UserRequest user; // Validates this nested object
// Getters and Setters
}
7. Supported Bean Validation Annotations
Here are some commonly used constraints from the Bean Validation API:
| Annotation | Purpose |
@NotNull | Field must not be null |
@NotBlank | Not null and not empty string |
@NotEmpty | Not null and not empty collection |
@Email | Must be a valid email |
@Size(min, max) | Length of string or size of list |
@Min(value) | Number must be ≥ value |
@Max(value) | Number must be ≤ value |
@Pattern(regex) | Must match regex pattern |
@Positive | Value must be > 0 |
@Negative | Value must be < 0 |
