22. HTTP Response Semantics & Custom Exceptions

HTTP Response Anatomy & ResponseEntity

Master HTTP response structure, status code taxonomy (200, 201, 204, 400, 404, 409, 500), decision matrices, and ResponseEntity construction.

HTTP Response Anatomy & ResponseEntity

In a production REST API, returning data is only half the contract. The application must explicitly communicate the protocol-level outcome of an operation using standard HTTP semantics.


1. Mental Model: The Emergency Department

Think of a Spring Boot REST application as a hospital Emergency Department:

EMERGENCY DEPARTMENT ANALOGY:
├── Client                  ──► Patient arriving at hospital
├── HTTP Request            ──► Intake / Complaint Form
├── Controller              ──► Reception / Triage Desk
├── Service Layer           ──► Doctor performing diagnosis
├── Repository              ──► Medical Records Archive
├── Custom Exception        ──► Specific Clinical Diagnosis (e.g., ResourceNotFound)
├── @RestControllerAdvice   ──► Central Emergency Response Coordinator
└── Error DTO               ──► Standardized Medical Incident Report

Core Principle: The doctor (Service) diagnoses the problem; the central emergency coordinator (@RestControllerAdvice) decides how that diagnosis is communicated externally to the patient (Client).


2. HTTP Response Anatomy

An HTTP response consists of three fundamental components:

HTTP Response Structure:
├── Status Code (Machine-readable protocol classification, e.g. 200 OK, 404 Not Found)
├── Headers     (Metadata key-value pairs, e.g. Content-Type, Location)
└── Body        (Representation payload formatted as JSON, XML, or plain text)

3. HTTP Status Code Taxonomy & Decision Matrix

HTTP StatusCategoryMeaningTypical Trigger
200 OK2xx SuccessStandard success response with bodyGET fetch or PUT update succeeded
201 Created2xx SuccessResource created; includes Location headerPOST resource creation succeeded
204 No Content2xx SuccessOperation succeeded; no response body returnedDELETE operation succeeded
400 Bad Request4xx Client ErrorSyntax error, invalid payload, or type mismatchValidation failure or malformed JSON
404 Not Found4xx Client ErrorRequested resource ID does not existResource missing in database
409 Conflict4xx Client ErrorValid request conflicts with existing stateDuplicate unique email or username
500 Internal Error5xx Server ErrorUnexpected server-side system failureUncaught exception or DB crash

4. ResponseEntity: Explicit Response Construction

Rather than returning plain Java objects and relying on implicit framework defaults, ResponseEntity<T> provides explicit control over the HTTP status code, headers, and payload body.

1. 200 OK Response

@GetMapping("/{id}")
public ResponseEntity<StudentResponseDto> getStudentById(@PathVariable Long id) {
    StudentResponseDto student = service.getStudentById(id);
    return ResponseEntity.ok(student);
}

2. 201 Created Response with Location Header

@PostMapping
public ResponseEntity<StudentResponseDto> createStudent(@Valid @RequestBody StudentRequestDto request) {
    StudentResponseDto savedStudent = service.createStudent(request);
    
    // Construct URI pointing to the newly created resource
    URI location = URI.create("/api/students/" + savedStudent.getId());
    
    return ResponseEntity.created(location).body(savedStudent);
}

3. 204 No Content Response

@DeleteMapping("/{id}")
public ResponseEntity<Void> deleteStudent(@PathVariable Long id) {
    service.deleteStudent(id);
    return ResponseEntity.noContent().build();
}

❓ Knowledge Check

Knowledge Check

Why is returning HTTP 200 OK with a null body for missing resources an anti-pattern?

Knowledge Check

What is the function of the Location header in an HTTP 201 Created response?

On this page