✅ B6 · POST + @Valid: Bean Validation
B6 · POST + @Valid: Bean Validation: `@Valid` is the API's **gatekeeper**: before a POST request gets in, it checks every field in the body against rules — is `title` blank, is i
`@Valid` is the API's **gatekeeper**: before a POST request gets in, it checks every field in the body against rules — is `title` blank, is it 3-120 chars, is `reporter` a real email? A non-conforming request is turned back with 400 BEFORE it even reaches the service. But if the UI already blocks an empty title with JavaScript, why validate again on the server? Because the UI is just ONE client: a mobile app, Postman, another service, or a malicious script can hit the API directly and bypass the UI's JS check entirely — server validation is the ONLY defense line you can trust. In Java the equivalent is Bean Validation: you put `@NotBlank`, `@Size(min=3,max=120)`, `@Email` annotations on DTO fields and `@Valid` fires them; the bad request is rejected before the controller method even runs. In QA this is the antidote to the classic "false trust" trap: the assumption "the UI validates, so the API is safe" is wrong — the tester must PROVE server validation by bypassing the UI and sending invalid data straight to the API.
DTO + Bean Validation + @Valid
**🐞 Defect Birth — if the `@Valid` annotation is forgotten** **Code:** `public ResponseEntity create(@RequestBody BugRequest req)` — `@Valid` is MISSING (only `@RequestBody`). **What happens:** the `@NotBlank`/`@Size` rules on the DTO are DEFINED but never fire. `POST /api/v1/bugs { "title": "" }` returns **201 Created** instead of 400 and an empty-title bug is written to the database. **Why sneaky:** the UI's JavaScript already blocks an empty title, so manual/UI testing PASSES — the defect never shows. But when a mobile app or Postman hits the API directly, an empty record is created: "empty bug" pollution in production. The rules SIT in the code but without the gatekeeper they do nothing. **Where the tester catches it:** in Postman, bypassing the UI and sending an empty `title` — getting 201 while expecting 400. This is the direct proof of why "the UI validates" trust is wrong.
🎬 @Valid Stands at the Gate: What Happens When the UI Is Bypassed
A user clicks "Save" in the UI with an empty title. The UI's JavaScript blocks it instantly: "title cannot be empty". UI test PASSES.
But Postman (or a mobile app) bypasses the UI ENTIRELY and sends an empty title straight to the API. The UI's JS check does NOT exist here.
If @Valid EXISTS: the gatekeeper catches the empty title and turns the request back with 400. The server acts as the trustworthy last line of defense.
If @Valid is MISSING: the rules sit in code but never fire. The empty title returns 201, an empty bug is written to the database — production pollution.
The lesson — UI validation is a convenience, not a guarantee. The only trustworthy gate is @Valid on the server. The tester PROVES it by bypassing the UI.
Why Server Validation Is Mandatory
The UI is just one client…
The UI's JS check runs only in that browser; mobile, Postman, another service don't see it.
@Valid is the central gate…
Server validation runs whatever the client — the only layer you can trust.