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
| Aspect | Details |
|---|---|
| Types | Checked vs Unchecked, Business vs Technical |
| Best Practices | Specific types, meaningful messages, proper context |
| Spring Integration | @ControllerAdvice, ResponseStatusException |
| Anti-patterns | Generic 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)CodeLoading syntax highlighter...
- 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
JAVA(26 lines)CodeLoading syntax highlighter...
Mental Model: Exception Hierarchy
TEXT(28 lines)CodeLoading syntax highlighter...
š¬ Deep Dive
Pattern 1: Base Exception Design
JAVA(67 lines)CodeLoading syntax highlighter...
Pattern 2: Domain-Specific Exceptions
JAVA(94 lines)CodeLoading syntax highlighter...
Pattern 3: Validation Exceptions
JAVA(54 lines)CodeLoading syntax highlighter...
Pattern 4: Technical Exceptions
JAVA(46 lines)CodeLoading syntax highlighter...
Pattern 5: Spring Boot Integration
JAVA(122 lines)CodeLoading syntax highlighter...
Pattern 6: Exception Factory
JAVA(43 lines)CodeLoading syntax highlighter...
ā ļø Common Mistakes
Mistake 1: Catching and Swallowing
JAVA(22 lines)CodeLoading syntax highlighter...
Mistake 2: Generic Exceptions
JAVA(7 lines)CodeLoading syntax highlighter...
Mistake 3: Exception for Flow Control
JAVA(14 lines)CodeLoading 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)CodeLoading syntax highlighter...
Three critical problems:
- Exception swallowed - The catch block logs but doesn't rethrow, so the transaction commits
- No rollback trigger -
@Transactionalonly rolls back on uncaught exceptions (by default RuntimeException) - Misleading return - User gets success message even when checkout partially failed
JAVA(34 lines)CodeLoading syntax highlighter...
rollbackFor when dealing with checked exceptions.š» Exercises
Exercise 1: Design Exception Hierarchy
ā Difficulty: Easy | ā±ļø Time: 15 minutes
JAVA(8 lines)CodeLoading syntax highlighter...
JAVA(77 lines)CodeLoading syntax highlighter...
Exercise 2: Exception Handler
āā Difficulty: Medium | ā±ļø Time: 20 minutes
@ControllerAdvice that handles exceptions with proper logging and response formatting.JAVA(5 lines)CodeLoading syntax highlighter...
JAVA(100 lines)CodeLoading syntax highlighter...
Exercise 3: Exception with Context
āā Difficulty: Medium | ā±ļø Time: 15 minutes
JAVA(6 lines)CodeLoading syntax highlighter...
JAVA(84 lines)CodeLoading syntax highlighter...
Exercise 4: Exception Factory
āāā Difficulty: Medium-Hard | ā±ļø Time: 20 minutes
JAVA(5 lines)CodeLoading syntax highlighter...
JAVA(91 lines)CodeLoading syntax highlighter...
Exercise 5: Transactional Exception Handling
āāāā Difficulty: Hard | ā±ļø Time: 25 minutes
JAVA(7 lines)CodeLoading syntax highlighter...
JAVA(121 lines)CodeLoading syntax highlighter...
š¤ Interview Questions
Q1: Checked vs Unchecked exceptions - when to use each?
- 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?
- Create base
ApplicationExceptionwith common fields (code, context, timestamp) - Split into
BusinessException(4xx, user-facing) andTechnicalException(5xx, logged) - Create domain-specific exceptions (OrderException, PaymentException)
- Use factory methods for consistent creation
- Integrate with global handler for uniform API responses
š Summary
| Type | Purpose | HTTP Status | Log Level |
|---|---|---|---|
| BusinessException | User can fix | 4xx | WARN |
| ValidationException | Invalid input | 400 | WARN |
| NotFoundException | Resource missing | 404 | WARN |
| TechnicalException | System issue | 5xx | ERROR |
š Review Schedule for This Article
| Day | Task | Time |
|---|---|---|
| Day 1 | Review exception hierarchy mental model diagram | 5 min |
| Day 3 | Redo Exercise 1 (Design Exception Hierarchy) | 15 min |
| Day 7 | Answer interview questions without looking | 10 min |
| Day 14 | Redo Debug This (Swallowed Exception) | 15 min |
| Day 30 | Audit exception handling in one service of your codebase | 20 min |