Java

Exception Hierarchy Design

Well-designed exceptions are crucial for maintainable error handling. This article covers how to design exception hierarchies that communicate intent, enable proper handling, and integrate cleanly with Spring Boot.

📋 At a Glance

AspectDetails
TypesChecked vs Unchecked, Business vs Technical
Best PracticesSpecific types, meaningful messages, proper context
Spring Integration@ControllerAdvice, ResponseStatusException
Anti-patternsGeneric exceptions, empty catch, exception swallowing

🎯 What You'll Learn

  • Exception hierarchy design principles
  • Business vs technical exceptions
  • Exception context and meaningful messages
  • Spring Boot integration with @ControllerAdvice
  • Anti-patterns to avoid

Production Story: The Generic Exception Disaster

A payment system used generic exceptions everywhere:

JAVA(17 lines)
Code
Loading syntax highlighter...
Problems:
  • No way to distinguish recoverable vs fatal errors
  • Lost original cause and context
  • Generic error messages to users
  • No specific logging or metrics
  • Impossible to retry appropriately
The fix: Well-designed exception hierarchy:
JAVA(26 lines)
Code
Loading syntax highlighter...

Mental Model: Exception Hierarchy

TEXT(28 lines)
Code
Loading syntax highlighter...

🔬 Deep Dive

Pattern 1: Base Exception Design

JAVA(67 lines)
Code
Loading syntax highlighter...

Pattern 2: Domain-Specific Exceptions

JAVA(94 lines)
Code
Loading syntax highlighter...

Pattern 3: Validation Exceptions

JAVA(54 lines)
Code
Loading syntax highlighter...

Pattern 4: Technical Exceptions

JAVA(46 lines)
Code
Loading syntax highlighter...

Pattern 5: Spring Boot Integration

JAVA(122 lines)
Code
Loading syntax highlighter...

Pattern 6: Exception Factory

JAVA(43 lines)
Code
Loading syntax highlighter...

⚠️ Common Mistakes

Mistake 1: Catching and Swallowing

JAVA(22 lines)
Code
Loading syntax highlighter...

Mistake 2: Generic Exceptions

JAVA(7 lines)
Code
Loading syntax highlighter...

Mistake 3: Exception for Flow Control

JAVA(14 lines)
Code
Loading syntax highlighter...

🐛 Debug This: The Swallowed Exception

A developer reports: "Orders randomly disappear after checkout! The user sees 'Order placed successfully' but no order is created."

JAVA(34 lines)
Code
Loading syntax highlighter...
Why are orders being created with invalid state?

✅ Solution:

Three critical problems:

  1. Exception swallowed - The catch block logs but doesn't rethrow, so the transaction commits
  2. No rollback trigger - @Transactional only rolls back on uncaught exceptions (by default RuntimeException)
  3. Misleading return - User gets success message even when checkout partially failed
Correct approach:
JAVA(34 lines)
Code
Loading syntax highlighter...
The lesson: Never swallow exceptions in transactional methods. Either rethrow or throw a new exception to trigger rollback. Use rollbackFor when dealing with checked exceptions.

💻 Exercises

Exercise 1: Design Exception Hierarchy

⭐ Difficulty: Easy | ⏱️ Time: 15 minutes

Task: Design an exception hierarchy for a user management domain.
JAVA(8 lines)
Code
Loading syntax highlighter...
✅ Solution:
JAVA(77 lines)
Code
Loading syntax highlighter...

Exercise 2: Exception Handler

⭐⭐ Difficulty: Medium | ⏱️ Time: 20 minutes

Task: Create a Spring @ControllerAdvice that handles exceptions with proper logging and response formatting.
JAVA(5 lines)
Code
Loading syntax highlighter...
✅ Solution:
JAVA(100 lines)
Code
Loading syntax highlighter...

Exercise 3: Exception with Context

⭐⭐ Difficulty: Medium | ⏱️ Time: 15 minutes

Task: Create an exception that carries rich context for debugging.
JAVA(6 lines)
Code
Loading syntax highlighter...
✅ Solution:
JAVA(84 lines)
Code
Loading syntax highlighter...

Exercise 4: Exception Factory

⭐⭐⭐ Difficulty: Medium-Hard | ⏱️ Time: 20 minutes

Task: Create an exception factory with fluent API for common scenarios.
JAVA(5 lines)
Code
Loading syntax highlighter...
✅ Solution:
JAVA(91 lines)
Code
Loading syntax highlighter...

Exercise 5: Transactional Exception Handling

⭐⭐⭐⭐ Difficulty: Hard | ⏱️ Time: 25 minutes

Task: Design exception handling for a complex transactional operation with compensating actions.
JAVA(7 lines)
Code
Loading syntax highlighter...
✅ Solution:
JAVA(121 lines)
Code
Loading syntax highlighter...

🎤 Interview Questions

Q1: Checked vs Unchecked exceptions - when to use each?

Answer:
  • Checked: Recoverable conditions, caller CAN and SHOULD handle (IOException, SQLException)
  • Unchecked: Programming errors or unrecoverable (NullPointerException, IllegalArgumentException)

Modern practice: Prefer unchecked for most cases, as checked exceptions:

  • Clutter method signatures
  • Often caught and wrapped anyway
  • Don't work with lambdas/streams

Q2: How do you design exception hierarchy for an application?

Answer:
  1. Create base ApplicationException with common fields (code, context, timestamp)
  2. Split into BusinessException (4xx, user-facing) and TechnicalException (5xx, logged)
  3. Create domain-specific exceptions (OrderException, PaymentException)
  4. Use factory methods for consistent creation
  5. Integrate with global handler for uniform API responses

📝 Summary

TypePurposeHTTP StatusLog Level
BusinessExceptionUser can fix4xxWARN
ValidationExceptionInvalid input400WARN
NotFoundExceptionResource missing404WARN
TechnicalExceptionSystem issue5xxERROR

📅 Review Schedule for This Article

DayTaskTime
Day 1Review exception hierarchy mental model diagram5 min
Day 3Redo Exercise 1 (Design Exception Hierarchy)15 min
Day 7Answer interview questions without looking10 min
Day 14Redo Debug This (Swallowed Exception)15 min
Day 30Audit exception handling in one service of your codebase20 min

Next: [Part 15: Result Pattern]