Intermediate · Harden
Build a Stable Validation & Error Contract
Separate binding, constraint violations, business conflicts, and unexpected failures without leaking internals.
Primary source: Spring Framework 6.2: MethodValidationPostProcessor
Lesson 1 of 3
1d streakThe Architectural Question
Ad-hoc error JSON per endpoint leaves clients writing bespoke parsers, and genuine regressions hide inside the format churn.
What this guide proves
- Use Jakarta Validation for deterministic request-shape rules
- Represent errors with a consistent `ProblemDetail` extension
- Map domain failures explicitly instead of catching `Exception`
How Jakarta Bean Validation intercepts incoming payloads
One validation boundary, taught once
Jakarta Bean Validation (implemented by Hibernate Validator in Spring Boot) provides declarative constraint enforcement on Java objects. Annotating a controller @RequestBody parameter with @Valid causes Spring’s RequestResponseBodyMethodProcessor to trigger validator inspection immediately after deserializing JSON.
- 01Jackson deserializes the HTTP request JSON body into a Java Record or POJO.
- 02Spring MVC detects the @Valid or @Validated annotation on the method parameter.
- 03ValidatorFactory executes registered ConstraintValidators for every annotated field.
- 04If any constraint fails, Spring constructs a BindingResult and immediately throws MethodArgumentNotValidException.
- 05The controller method body never executes, protecting domain services from invalid state.
Architectural Boundary · Do Not Confuse
@Valid (Standard Jakarta)
@Validated (Spring Specific)
@Valid is the standard Jakarta validation annotation that triggers cascading validation on nested objects and controller bodies. @Validated is a Spring-specific annotation that enables method-level parameter validation (on @Service methods) and supports Validation Groups.
Annotating wire contracts with declarative constraints
package com.example.customer.dto;
import jakarta.validation.constraints.*;
public record CreateCustomerRequest(
@NotBlank(message = "Customer name is required")
@Size(min = 2, max = 100, message = "Name must be between 2 and 100 characters")
String name,
@NotBlank(message = "Email is required")
@Email(message = "Email must be formatted properly")
String email,
@NotNull(message = "Credit limit is required")
@PositiveOrZero(message = "Credit limit cannot be negative")
Double creditLimit
) {}package com.example.customer.api;
import com.example.customer.dto.CreateCustomerRequest;
import jakarta.validation.Valid;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import java.net.URI;
@RestController
@RequestMapping("/api/customers")
public class CustomerController {
@PostMapping
public ResponseEntity<Void> create(@Valid @RequestBody CreateCustomerRequest request) {
// Method body executes only if request passes all validations
URI location = URI.create("/api/customers/42");
return ResponseEntity.created(location).build();
}
}Break it deliberately: observing MethodArgumentNotValidException
curl -i -X POST http://localhost:8080/api/customers \
-H "Content-Type: application/json" \
-d '{"name": "", "email": "invalid-email", "creditLimit": -50}'
HTTP/1.1 400 Bad Request
Content-Type: application/problem+json
{
"type": "about:blank",
"title": "Bad Request",
"status": 400,
"detail": "Validation failed for argument [0] in public ResponseEntity com.example.customer.api.CustomerController.create(...)",
"errors": [
{"field": "name", "message": "Customer name is required"},
{"field": "email", "message": "Email must be formatted properly"},
{"field": "creditLimit", "message": "Credit limit cannot be negative"}
]
}Active Recall Checkpoint
What happens if you omit the @Valid annotation on a controller @RequestBody argument?
Hint: Does Hibernate Validator inspect the object automatically without the annotation?
Show answer & explanation
Spring skips validation entirely. The deserialized object—including null or invalid fields—passes straight into your controller and service logic, risking NullPointerExceptions or corrupted database rows.
Validation rules in API design
Use it when
Apply declarative Jakarta validation annotations on every input DTO representing external HTTP, RPC, or messaging payloads.
Reconsider when
Avoid placing complex stateful business rules (e.g. checking account balance or inventory levels) in Jakarta annotations; keep those in Domain Services.
Synthesis & Production Verification
Production Acceptance Criteria
- Return identical error envelopes for invalid-email, 404, and duplicate-resource cases
- Bind field errors to JSON pointers a client can highlight
- Prove no stack traces or SQL fragments appear in any payload
Key Takeaway
Jakarta Bean Validation guards application boundaries by inspecting declarative constraints during argument resolution and halting execution on invalid payloads.
Architectural & Technical Review
Core Interview Questions
Q01How does @Valid trigger validation in a Spring controller?Show answer
Spring detects @Valid on the @RequestBody parameter and invokes ValidatorFactory, throwing MethodArgumentNotValidException if constraints fail.
Q02What HTTP status and payload structure should validation failures produce?Show answer
An HTTP 400 Bad Request with an RFC 9457 ProblemDetail document detailing each invalid field and constraint violation message.
Q03What is the distinction between @Valid and @Validated?Show answer
@Valid is standard Jakarta validation for request bodies and nested objects; @Validated is Spring-specific for service method validation and groups.
Production Pitfalls
Critical Anti-Patterns
- Pitfall: Omitting @Valid from @RequestBody parameters — Without @Valid, Spring skips validation entirely, allowing malformed or null values to propagate into domain services.
- Pitfall: Writing manual if-null validation checks inside controller methods — Manual checks duplicate boilerplate and produce inconsistent error responses compared to declarative Jakarta validation.
Primary Documentation & Specifications
Lesson Primary References
Supplementary Module Resources