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

AspectDetails
Patterns CoveredChain of Responsibility, Pipeline, Middleware
Primary BenefitDecoupled processing, easy to extend
Use CasesValidation, request handling, data transformation
Java FeaturesLambdas, 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)
Code
Loading syntax highlighter...
The fix: Validation chain:
JAVA(16 lines)
Code
Loading syntax highlighter...

Mental Model: Chain vs Pipeline

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

🔬 Deep Dive

Pattern 1: Classic Chain of Responsibility

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

Pattern 2: Functional Chain (Modern Approach)

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

Pattern 3: Validation Chain

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

Pattern 4: Pipeline Pattern

JAVA(39 lines)
Code
Loading syntax highlighter...
Pipeline with error handling:
JAVA(72 lines)
Code
Loading syntax highlighter...

Pattern 5: Middleware Pattern

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

Pattern 6: Spring Integration

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

⚠️ Common Mistakes

Mistake 1: Missing Termination

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

Mistake 2: Tight Coupling in Chain

JAVA(25 lines)
Code
Loading 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)
Code
Loading 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)
Code
Loading syntax highlighter...
The fix:
JAVA(9 lines)
Code
Loading syntax highlighter...
Better approach - use Template Method to prevent this bug:
JAVA(16 lines)
Code
Loading 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)
Code
Loading syntax highlighter...
✅ Solution:
JAVA(61 lines)
Code
Loading 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)
Code
Loading syntax highlighter...
✅ Solution:
JAVA(67 lines)
Code
Loading syntax highlighter...

Exercise 3: Middleware Chain

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

Task: Implement HTTP middleware pattern with before/after hooks.
JAVA(7 lines)
Code
Loading syntax highlighter...
✅ Solution:
JAVA(87 lines)
Code
Loading 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)
Code
Loading syntax highlighter...
✅ Solution:
JAVA(56 lines)
Code
Loading 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)
Code
Loading syntax highlighter...
✅ Solution:
JAVA(121 lines)
Code
Loading 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

PatternUse When
Chain of ResponsibilityMultiple potential handlers, one processes
PipelineSequential transformations
MiddlewareRequest/response processing
Validation ChainMultiple validators, error accumulation
Spring InterceptorsHTTP request processing

📅 Review Schedule for This Article

DayTaskTime
Day 1Review Chain vs Pipeline mental model5 min
Day 3Redo Exercise 2 (Validation Pipeline)20 min
Day 7Answer interview questions without looking10 min
Day 14Redo Debug This (Broken Chain)15 min
Day 30Identify one chain/pipeline opportunity in your codebase20 min

Next: [Part 13: Template Method & Hooks]