Java
Chain of Responsibility and Pipelines
When processing requires multiple steps or multiple handlers might process a request, Chain of Responsibility and Pipeline patterns provide clean solutions. This article covers classic chains, middleware patterns, and type-safe pipelines.
📋 At a Glance
| Aspect | Details |
|---|---|
| Patterns Covered | Chain of Responsibility, Pipeline, Middleware |
| Primary Benefit | Decoupled processing, easy to extend |
| Use Cases | Validation, request handling, data transformation |
| Java Features | Lambdas, Generics, Records |
🎯 What You'll Learn
- Chain of Responsibility for handler delegation
- Pipeline Pattern for sequential transformations
- Middleware Pattern (request/response chains)
- Spring integration with interceptors and filters
- When to use chains vs simple conditionals
Production Story: The Validation Spaghetti
An e-commerce checkout had validation scattered everywhere:
JAVA(29 lines)CodeLoading syntax highlighter...
The fix: Validation chain:
JAVA(16 lines)CodeLoading syntax highlighter...
Mental Model: Chain vs Pipeline
TEXT(34 lines)CodeLoading syntax highlighter...
🔬 Deep Dive
Pattern 1: Classic Chain of Responsibility
JAVA(71 lines)CodeLoading syntax highlighter...
Pattern 2: Functional Chain (Modern Approach)
JAVA(37 lines)CodeLoading syntax highlighter...
Pattern 3: Validation Chain
JAVA(85 lines)CodeLoading syntax highlighter...
Pattern 4: Pipeline Pattern
JAVA(39 lines)CodeLoading syntax highlighter...
Pipeline with error handling:
JAVA(72 lines)CodeLoading syntax highlighter...
Pattern 5: Middleware Pattern
JAVA(80 lines)CodeLoading syntax highlighter...
Pattern 6: Spring Integration
JAVA(99 lines)CodeLoading syntax highlighter...
⚠️ Common Mistakes
Mistake 1: Missing Termination
JAVA(21 lines)CodeLoading syntax highlighter...
Mistake 2: Tight Coupling in Chain
JAVA(25 lines)CodeLoading syntax highlighter...
🐛 Debug This: The Broken Chain
A developer reports: "Our validation chain works for some requests but silently skips validation for others!"
JAVA(54 lines)CodeLoading syntax highlighter...
Why does the email validation get skipped?
✅ Solution:
The bug is in
RequiredFieldsValidator - when validation passes (name is not null), it returns ValidationResult.ok() without calling passToNext(). This breaks the chain completely.JAVA(11 lines)CodeLoading syntax highlighter...
The fix:
JAVA(9 lines)CodeLoading syntax highlighter...
Better approach - use Template Method to prevent this bug:
JAVA(16 lines)CodeLoading syntax highlighter...
The lesson: When implementing Chain of Responsibility, ensure chain continuation is enforced by the base class, not left to subclass implementations.
💻 Exercises
Exercise 1: Simple Handler Chain
⭐ Difficulty: Easy | ⏱️ Time: 15 minutes
Task: Implement a discount handler chain for e-commerce.
JAVA(9 lines)CodeLoading syntax highlighter...
✅ Solution:
JAVA(61 lines)CodeLoading syntax highlighter...
Exercise 2: Validation Pipeline
⭐⭐ Difficulty: Medium | ⏱️ Time: 20 minutes
Task: Create a validation pipeline that collects all errors (not fail-fast).
JAVA(7 lines)CodeLoading syntax highlighter...
✅ Solution:
JAVA(67 lines)CodeLoading syntax highlighter...
Exercise 3: Middleware Chain
⭐⭐ Difficulty: Medium | ⏱️ Time: 25 minutes
Task: Implement HTTP middleware pattern with before/after hooks.
JAVA(7 lines)CodeLoading syntax highlighter...
✅ Solution:
JAVA(87 lines)CodeLoading syntax highlighter...
Exercise 4: Type-Safe Pipeline
⭐⭐⭐ Difficulty: Medium-Hard | ⏱️ Time: 25 minutes
Task: Create a type-safe pipeline where each step transforms the type.
JAVA(8 lines)CodeLoading syntax highlighter...
✅ Solution:
JAVA(56 lines)CodeLoading syntax highlighter...
Exercise 5: Pipeline with Error Handling
⭐⭐⭐⭐ Difficulty: Hard | ⏱️ Time: 30 minutes
Task: Create a pipeline with Result type for error propagation.
JAVA(11 lines)CodeLoading syntax highlighter...
✅ Solution:
JAVA(121 lines)CodeLoading syntax highlighter...
🎤 Interview Questions
Q1: When use Chain of Responsibility vs simple if-else?
Answer:
Use Chain when:
- Handlers are independent and reusable
- Need to add/remove handlers at runtime
- Different configurations need different chains
- Handlers are in different modules/teams
Use if-else when:
- Logic is simple (2-3 cases)
- Conditions are tightly coupled
- No reuse needed
Q2: Difference between Chain of Responsibility and Pipeline?
Answer:
- Chain: Handler decides if it should process; request may be handled by 0, 1, or many handlers
- Pipeline: All steps execute in sequence; transforms data step by step
Chain = "who should handle this?" Pipeline = "process this through all steps"
📝 Summary
| Pattern | Use When |
|---|---|
| Chain of Responsibility | Multiple potential handlers, one processes |
| Pipeline | Sequential transformations |
| Middleware | Request/response processing |
| Validation Chain | Multiple validators, error accumulation |
| Spring Interceptors | HTTP request processing |
📅 Review Schedule for This Article
| Day | Task | Time |
|---|---|---|
| Day 1 | Review Chain vs Pipeline mental model | 5 min |
| Day 3 | Redo Exercise 2 (Validation Pipeline) | 20 min |
| Day 7 | Answer interview questions without looking | 10 min |
| Day 14 | Redo Debug This (Broken Chain) | 15 min |
| Day 30 | Identify one chain/pipeline opportunity in your codebase | 20 min |
Next: [Part 13: Template Method & Hooks]