21. Bean Validation & API Contract Enforcement

Error Contracts, Anti-Patterns & Refactoring

Master structured validation error contracts, production anti-patterns, and refactoring entity-coupled CRUD APIs.

Error Contracts, Anti-Patterns & Refactoring

Returning clear, structured validation error responses when clients submit invalid inputs improves API usability and frontend integration.


1. Structured Validation Error Response Contracts

By default, Spring Boot returns a generic MethodArgumentNotValidException response. In production systems, a custom @RestControllerAdvice translates validation exceptions into a structured JSON error contract:

{
  "success": false,
  "message": "Validation failed for request payload",
  "errors": {
    "name": "Student name is mandatory and cannot be blank",
    "email": "Student email must be a valid email format",
    "age": "Student age must be at least 18"
  }
}
// Standard production error DTO structure
public class ValidationErrorResponseDto {
    private boolean success = false;
    private String message;
    private Map<String, String> errors;

    public ValidationErrorResponseDto(String message, Map<String, String> errors) {
        this.message = message;
        this.errors = errors;
    }

    public boolean isSuccess() { return success; }
    public String getMessage() { return message; }
    public Map<String, String> getErrors() { return errors; }
}

2. Production Anti-Patterns Matrix

Production Anti-PatternOperational RiskRecommended Solution
1. Direct @Entity ParametersMass assignment & sensitive data leakageUse explicit StudentRequestDto & StudentResponseDto
2. Single DTO for All OpsLeaks unmodifiable fields during update operationsCreate specific CreateStudentDto & UpdateStudentDto
3. Missing @Valid TriggerDTO constraint annotations are ignored completelyAdd @Valid to @RequestBody parameters in Controllers
4. Validation inside ServicePollutes business logic with basic string checksEnforce input constraints on DTOs via Bean Validation
5. Returning HTTP 500 for Bad InputConfuses client developers & misleads monitoringReturn HTTP 400 Bad Request for validation failures

3. Production Design Checklist

Before marking a REST API implementation complete, verify:

  • Request payloads use explicit Request DTOs (no Entities accepted at API boundary)
  • Response payloads use explicit Response DTOs (no Entities returned to clients)
  • DTO field validation uses appropriate constraints (@NotBlank, @NotNull, @Min)
  • Controllers specify @Valid @RequestBody to trigger validation
  • Invalid requests return HTTP 400 Bad Request short-circuiting Service execution
  • Service layer performs DTO ↔ Entity mapping explicitly

❓ Interactive Self-Assessment

Knowledge Check

Why should validation failures return HTTP 400 Bad Request instead of HTTP 500 Internal Server Error?

Refactoring an Entity-Coupled CRUD API

A legacy controller method accepts a raw @Entity Student directly and returns @Entity Student:

@PostMapping
public Student createStudent(@RequestBody Student student) {
    return studentService.save(student);
}

Refactor this endpoint using DTOs, explicit mapping, and Bean Validation constraints.

On this page