Learnitweb

@Valid annotation

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:

AnnotationPurpose
@NotNullField must not be null
@NotBlankNot null and not empty string
@NotEmptyNot null and not empty collection
@EmailMust 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
@PositiveValue must be > 0
@NegativeValue must be < 0