Jakarta Validation
About
Bean Validation is a standard framework for declaring and enforcing validation rules on JavaBeans (POJOs) using annotations. It provides a way to validate the state of objects either automatically (e.g., during web requests in Spring) or manually (programmatically).
It originated as JSR-303, evolved to JSR-380 (Bean Validation 2.0), and now resides under the Jakarta EE umbrella as jakarta.validation
.
This API does not implement validation logic itself. It defines metadata (annotations) and interfaces. The actual logic is implemented by a provider, most commonly Hibernate Validator.
Why is Jakarta Bean Validation important in Spring ?
It integrates seamlessly with Spring Web MVC and Spring Boot.
It supports both automatic validation of controller inputs and manual validation in service layers.
It enables declarative and reusable constraint definitions.
It standardizes validation across frameworks and layers.
Jakarta Bean Validation Components
1. Constraint Annotations
These are placed on class fields or method parameters:
@NotNull
: Value must not be null.@NotEmpty
: Value must not be null or empty (for strings, collections).
2. Meta Annotations
@Constraint
: Used when defining custom constraints.@Valid
: Triggers recursive validation on associated objects or collections.
3. Interfaces
jakarta.validation.Validator
: The core interface to validate beans.jakarta.validation.ConstraintValidator<A extends Annotation, T>
: Interface for implementing custom constraint logic.jakarta.validation.ConstraintViolation<T>
: Represents a single validation error.
4. Bootstrap API
Validation.buildDefaultValidatorFactory()
creates aValidatorFactory
which provides aValidator
.
How Spring Integrates with Jakarta Validation ?
When jakarta.validation
(or javax.validation
) API and a provider like Hibernate Validator is on the classpath, Spring Boot auto-configures:
LocalValidatorFactoryBean
: A SpringValidator
that delegates to Jakarta Validator.MethodValidationPostProcessor
: Enables method-level validation using@Validated
.
Dependencies
Spring Boot starter spring-boot-starter-web
includes Hibernate Validator by default.
Spring Validation Flow
Spring integrates with the Jakarta Bean Validation API via the LocalValidatorFactoryBean
and auto-wires it as a global validator.
There are two major validation triggers in Spring:
Method-level validation (Spring MVC controllers, service beans, etc.)
Manual (programmatic) validation using
Validator
Spring internally:
Detects the
@Valid
or@Validated
annotationsDelegates to the
jakarta.validation.Validator
interface (via Hibernate Validator)Collects
ConstraintViolation
s and throws exceptions like:MethodArgumentNotValidException
(for body-bound beans)ConstraintViolationException
(for method parameter validation)BindException
(for form data)
1. Controller-level Validation on @RequestBody
DTO
@RequestBody
DTOInternal Workflow:
Deserialization: JSON request body is deserialized into
UserDto
using Jackson.Validation Trigger: Spring detects
@Valid
on the parameter.Validator Bean: Calls
validator.validate(userDto)
usingLocalValidatorFactoryBean
.Hibernate Validator executes all constraints like
@NotBlank
,@Email
.Failure: If constraints fail:
Spring throws
MethodArgumentNotValidException
.Handled globally with
@ExceptionHandler
or@ControllerAdvice
.
Example:
Response:
2. Controller-level Validation on @RequestParam
, @PathVariable
@RequestParam
, @PathVariable
Internal Workflow:
Uses method-level validation.
Triggers via Spring’s
MethodValidationPostProcessor
.Detects
@Validated
on the class or method.Calls
executableValidator.validateParameters(...)
If invalid: throws
ConstraintViolationException
.
Important: @Validated
must be applied at class level for method parameter validation:
3. Nested (Recursive) Validation with @Valid
@Valid
Internal Workflow:
During traversal, Spring checks if a field has
@Valid
.If yes, it descends into that object and applies all constraints.
Recursion happens automatically.
If one ItemDto
has null name
, it’s picked up as a nested constraint violation.
4. Service-layer (Method-level) Validation using @Validated
@Validated
Service-layer validation using @Validated
allows us to validate method parameters or return values in any Spring-managed bean—especially in the service layer, where we might not rely on Spring MVC controller-level validation. It’s part of the Method Validation feature provided by Jakarta Bean Validation and integrated into Spring via proxies.
When we annotate a class with @Validated
, Spring uses AOP (Aspect-Oriented Programming) to create a proxy that intercepts method calls and performs validation before the actual method runs. Internally, Spring uses the MethodValidationPostProcessor
bean which wraps beans with a proxy capable of method validation.
Execution Flow:
Spring boot automatically registers a
MethodValidationPostProcessor
.We annotate our class with
@Validated
.Spring creates a proxy of the class.
Before executing our method, Spring uses the
ExecutableValidator
to:Validate method parameters
Optionally validate the return value
If validation fails, Spring throws a
ConstraintViolationException
.
Example
Calling code:
Result:
Spring will throw a ConstraintViolationException
because:
name
is blank (@NotBlank
)age
is less than 18 (@Min(18)
)
5. Validation Groups Internally
How It Works:
Spring detects group classes passed in
@Validated(Update.class)
Passes these group classes to the validator:
Only the constraints in that group are applie
6. Manual Validation using Validator
When and How Validation is Triggered ?
If I Add Jakarta Validation Annotations to a DTO and Populate It — Will Constraints Be Checked Automatically?
No, the constraints will not be checked automatically just because we annotated our DTO with validation annotations (like @NotBlank
, @Email
, etc.).
They are only enforced when explicitly triggered — either:
By Spring (e.g., using
@Valid
,@Validated
)Or manually by calling
Validator.validate(...)
Example
1. DTO With Constraints
2. Populating DTO Manually
What Happens Here?
Nothing is validated at this point.
Java doesn't throw errors just because annotations exist — they’re metadata.
The validation must be explicitly triggered.
if you have a custom class (e.g., an entity or DTO) annotated with Jakarta validation constraints, those constraints do nothing unless validation is explicitly triggered.
How to Trigger Validation ?
Option A: Manual Trigger
This will print:
Option B: Automatically via Spring
When used in a Spring controller or service, Spring triggers validation for us.
Controller:
Spring will call
validator.validate(userDto)
If any violation, it throws
MethodArgumentNotValidException
Validation Groups
By default, all validations belong to the Default group. Groups allow conditional or staged validation.
Define Marker Interfaces
Apply to Fields
Validate with Groups
Spring uses @Validated
(from org.springframework.validation.annotation
) to support groups. @Valid
does not support groups.
Custom Constraints
1. Define annotation
2. Implement logic
3. Use it in our bean
Last updated
Was this helpful?