DevNotes
Support
Spring Boot · Chapter 18

Bean Validation

@Valid, @Validated and Jakarta Validation — constraint annotations, @NotNull vs @NotEmpty vs @NotBlank, nested and method validation, groups, custom ConstraintValidators and error handling.

◷ 8 min read§ 18 sections? 9 interview questions{ } 19 code examples

#Introduction

Bean Validation is one of the most frequently asked Spring Boot interview topics. Almost every enterprise application validates incoming requests before processing them — user registration, login, payment APIs, banking, healthcare, e-commerce, insurance, government portals.

Interviewers frequently ask: What is @Valid? What is @Validated? What is Jakarta Bean Validation? What happens internally when validation fails? What are validation groups? How do we create custom validators? What is ConstraintValidator? What's the difference between @NotNull, @NotEmpty and @NotBlank?

#Why Validation?

Suppose the client sends:

JSON
{
  "name": "",
  "email": "abc",
  "age": 10
}
Client
Controller
Service
Database
Without validation — invalid data reaches your database
Client
Validation
Controller
Service
Database
With validation — invalid requests are rejected immediately

#What is Bean Validation?

Bean Validation is a Java specification (Jakarta Bean Validation) that defines how Java objects are validated using annotations. Spring Boot integrates with it automatically once the starter is on the classpath:

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

#First Example

Java
public class UserRequest {

    @NotBlank
    private String name;

    @Email
    private String email;

    @Min(18)
    private Integer age;
}

@PostMapping("/users")
public ResponseEntity<String> save(@Valid @RequestBody UserRequest request) {
    return ResponseEntity.ok("Saved");
}

A request with {"name": "", "email": "abc", "age": 15} fails validation → 400 Bad Request.

Complete Validation Flow

Client — JSON
@RequestBody → Jackson
Java object
@Valid → Validator
Validation success?
Controller
MethodArgumentNotValidException → @ControllerAdvice → JSON error

#What Does @Valid Do?

@Valid tells Spring: validate this object before executing the controller method.

Create object
Validate object
Valid?
Call controller
Throw exception

#Common Validation Annotations

@NotNull, @NotEmpty and @NotBlank

Java
@NotNull
private String name;    // rejects null; allows "" and " "

@NotEmpty
private String name;    // rejects null and ""; allows " "

@NotBlank
private String name;    // rejects null, "" and spaces-only — best for user-entered text

Interview favourite — this table is asked surprisingly often:

Annotationnull""" "
@NotNull✗ rejected✓ allowed✓ allowed
@NotEmpty✗ rejected✗ rejected✓ allowed
@NotBlank✗ rejected✗ rejected✗ rejected

Strings

Java
@Size(min = 3, max = 20)
private String username;   // length 3–20

Email

Java
@Email
private String email;

abc@gmail.com is valid; abc, abc@ and gmail.com are invalid. (Hibernate Validator's @Email also accepts abc@gmail — add a @Pattern if you need a stricter rule.)

Numbers

Java
@Min(18)
private Integer age;

@Max(60)
private Integer retirementAge;

Decimals

Java
@DecimalMin("1000.00")
private BigDecimal minSalary;

@DecimalMax("9999999.99")
private BigDecimal maxSalary;

Useful for money values.

Booleans

A primitive boolean active can't be null; a wrapper Boolean active can. Validate it with @NotNull private Boolean active;.

Regex

Java
@Pattern(regexp = "^[A-Z]{5}[0-9]{4}[A-Z]{1}{{main}}quot;)
private String pan;   // e.g. ABCDE1234F

Dates

Java
@Past
private LocalDate dob;

@Future
private LocalDate expiryDate;

// also: @PastOrPresent, @FutureOrPresent

#Nested Validation

Java
public class UserRequest {

    @Valid
    private Address address;
}

public class Address {

    @NotBlank
    private String city;
}

Without @Valid on the field inside UserRequest, the nested Address is not validated.

Collections

Java
public class UserRequest {

    @Valid
    private List<Address> addresses;   // every address is validated
}

#Validation Messages

Java
@NotBlank(message = "Name is mandatory")
private String name;
JSON
{
  "message": "Name is mandatory"
}

#Method Parameter Validation

Java
@RestController
@Validated
public class UserController {

    @GetMapping("/{id}")
    public User get(@Min(1) @PathVariable Long id) {
    }
}

#@Valid vs @Validated

One of the most common interview questions.

@Valid — a Jakarta Bean Validation annotation. Validates an object and cascades into nested objects:

Java
@Valid @RequestBody UserRequest dto

@Validated — a Spring annotation. Adds validation groups and method-level validation (class-level activation):

Java
@Validated
@Service
public class UserService {
}

#Validation Groups

Java
public interface Create {}
public interface Update {}

public class UserRequest {

    @Null(groups = Create.class)
    @NotNull(groups = Update.class)
    private Long id;
}

@PostMapping
public void create(@Validated(Create.class) @RequestBody UserRequest dto) {
}

Only the Create group is evaluated — useful for different rules on create vs update.

#Custom Validation Annotation

Java
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = PanValidator.class)
public @interface ValidPan {

    String message() default "Invalid PAN";
    Class<?>[] groups() default {};
    Class<? extends Payload>[] payload() default {};
}
Java
public class PanValidator implements ConstraintValidator<ValidPan, String> {

    @Override
    public boolean isValid(String value, ConstraintValidatorContext context) {
        return value != null && value.matches("^[A-Z]{5}[0-9]{4}[A-Z]{{main}}quot;);
    }
}
Java
@ValidPan
private String pan;

ConstraintValidator

An interview favourite — this is how custom validation works internally:

@ValidPan
ConstraintValidator.isValid()
true / false

#Validation Exceptions

Validation ofException
@Valid @RequestBodyMethodArgumentNotValidException
Method parameters (@Validated beans)ConstraintViolationException
Controller parameters (Spring 6.1+)HandlerMethodValidationException

Know the difference.

Global Exception Handler

Java
@RestControllerAdvice
public class GlobalHandler {

    @ExceptionHandler(MethodArgumentNotValidException.class)
    public ResponseEntity<?> handle(MethodArgumentNotValidException ex) {
        // extract errors from ex.getBindingResult()
    }
}

Returning Validation Errors

JSON
{
  "timestamp": "2026-07-25T12:30:00",
  "status": 400,
  "errors": [
    { "field": "name", "message": "Name is mandatory" },
    { "field": "email", "message": "Invalid email address" }
  ]
}

Much more useful than a single error string.

#Internal Spring Components

JSON
Jackson
DTO
LocalValidatorFactoryBean
Hibernate Validator
ConstraintValidator
Success / failure

Important classes: LocalValidatorFactoryBean, SpringValidatorAdapter, ConstraintValidator and MethodValidationPostProcessor (for method validation).

#Common Mistakes

  • Forgetting @Valid — @RequestBody UserRequest dto alone performs no validation. Use @Valid @RequestBody UserRequest dto.
  • Forgetting @Validated on services (or on controllers before Spring 6.1) — parameter constraints like @Min(1) won't run.
  • Using @NotNull for strings — it allows " ". Use @NotBlank.
  • No custom messages — prefer @NotBlank(message = "Name cannot be blank").
  • Skipping nested @Valid — without @Valid private Address address;, nested validation is skipped.

#Enterprise Architecture

React — JSON request
@RequestBody → Jackson
DTO
@Valid
Hibernate Validator → ConstraintValidator
Controller
Service
Repository
Database

#Interview Questions

Q1What is Bean Validation?

A standard Java specification (Jakarta Bean Validation) for validating Java objects using annotations.

Q2What is the default validation implementation in Spring Boot?

Hibernate Validator.

Q3What is the difference between @Valid and @Validated?
@Valid@Validated
Jakarta ValidationSpring Framework
Object validation, cascades into nested objectsObject + method-level validation
No group selectionSupports validation groups
Q4Difference between @NotNull, @NotEmpty and @NotBlank?
AnnotationRejects nullRejects ""Rejects " "
@NotNull✓✗✗
@NotEmpty✓✓✗
@NotBlank✓✓✓
Q5What exception is thrown when @RequestBody validation fails?

MethodArgumentNotValidException.

Q6What exception is thrown during method parameter validation?

ConstraintViolationException (for @Validated beans; controllers on Spring 6.1+ throw HandlerMethodValidationException).

Q7Which class creates the Spring Validator?

LocalValidatorFactoryBean.

Q8What is ConstraintValidator?

The interface you implement to create custom validation logic for a custom constraint annotation.

Q9Why are validation groups used?

To apply different validation rules for different operations, such as create, update or admin workflows.

#Key Takeaways

  • Bean Validation rejects invalid data before business logic executes.
  • @Valid validates objects; @Validated adds method validation and groups.
  • @NotBlank is generally the best choice for required text fields.
  • Use nested @Valid to validate child objects and collections.
  • Implement ConstraintValidator for reusable custom rules.
  • Handle validation exceptions globally with @RestControllerAdvice.
  • LocalValidatorFactoryBean and Hibernate Validator power Spring Boot's validation.