Skip to content
Ameen Abozaid
JNR-015

Error handling

  • 6 Lessons
  • 2 h practice (estimate)
On this page 8 topics

Overview

Topics

  • Custom exceptions
  • @ControllerAdvice
  • consistent API error responses

Learn first

2 h of practice (estimate)

Learning outcomes

  1. Design a small exception hierarchy for an application (not found, conflict, business rule).
  2. Map exceptions to HTTP responses centrally with @RestControllerAdvice.
  3. Return consistent error bodies using RFC 9457 Problem Details (ProblemDetail).
  4. Avoid leaking stack traces or internals to clients while logging them server-side.

Lessons

  1. 01Errors are part of the API
  2. 02Application exception hierarchy
  3. 03@RestControllerAdvice
  4. 04Problem Details
  5. 05What not to tell the client
  6. 06Demo: centralized Problem Details error handling

Lab and exercises

Lab

JNR-015-LAB1 · Consistent errors

Outcomes: 1–4 · Time: ~2 h

  1. Create ShopException with NotFoundException, ConflictException, BusinessRuleException.
  2. Write @RestControllerAdvice mapping: validation to 400 (with a errors list of field and message), not found to 404, conflict (duplicate SKU) to 409, anything else to 500.
  3. Make all bodies ProblemDetail.
  4. Log unexpected exceptions server-side; return a generic message.
  5. Document the single error shape in the README.

Acceptance: every error matches one documented shape; no stack trace or internal message appears in any response.

Exercises (assessment: error-contract review)

IDOutcomeTask
JNR-015-EX011Draw the hierarchy for Shop: base, not found, conflict, business rule; state who throws each.
JNR-015-EX022Remove try/catch from a given controller and add the equivalent handler.
JNR-015-EX033Return a ProblemDetail for a 409 duplicate SKU, with a custom sku property.
JNR-015-EX044Review a response containing org.postgresql... duplicate key text; rewrite the handler.
JNR-015-EX053Review an error contract: a 200 with "error": true, three error shapes, one exposed stack trace; list fixes.
Show solutions
  • EX01 ShopException (base) with NotFoundException (repositories/services), ConflictException (services on duplicates), BusinessRuleException (domain rules).
  • EX02 @ExceptionHandler(NotFoundException.class) returning ProblemDetail.forStatusAndDetail(NOT_FOUND, ex.getMessage()).
  • EX03 var pd = ProblemDetail.forStatusAndDetail(CONFLICT, "SKU exists"); pd.setProperty("sku", sku); return pd;
  • EX04 Log the original exception; return ProblemDetail 409 or 500 with a safe message.
  • EX05 Use proper status codes; one shape (ProblemDetail); hide traces and log them.
  • Outcome 3 is also covered by the lab and quiz.

Quiz

Outcomes: O1 exception hierarchy · O2 central mapping · O3 Problem Details · O4 no leaks.

A self-check for you: nothing is graded, saved or sent anywhere. Choose an answer, then check it. You can try again as often as you like.

  1. 1An unknown product id should lead to HTTP:O1
  2. 2Who should pick the HTTP status?O1
  3. 3A duplicate SKU maps best to:O1
  4. 4@RestControllerAdvice is used to:O2
  5. 5Putting try/catch in every controller is:O2
  6. 6Problem Details is defined by:O3
  7. 7Its content type is:O3
  8. 8Which type does Spring provide for it?O3
  9. 9Where should a stack trace go?O4
  10. 10A 500 response for an unexpected error should contain:O4

Practical part

Five exercises JNR-015-EX01 to EX05 plus the lab. The assessment is the error-contract review (EX05). Pass: quiz at least 8/10, EX05 finds all three flaws, lab acceptance met.

Common mistakes

Try/catch in every controller; 200 with "error": true; exposing exception messages from the database.

Assessment

Error-contract review.

Career relevance

API conventions (JNR-020) and incident diagnosis.

Type to search levels, phases, modules and lessons.