# How to Implement Chain of Responsibility for Request Handling Pipelines in Java

> Implement Chain of Responsibility in Java to build flexible request handling pipelines. Decouple senders from receivers and pass requests through a sequence of handlers.

- Repository: [Ilkka Seppälä/java-design-patterns](https://github.com/iluwatar/java-design-patterns)
- Tags: how-to-guide
- Published: 2026-02-27

---

**The Chain of Responsibility pattern decouples senders from receivers by routing requests through a sequence of handlers, each deciding whether to process the request or pass it to the next handler in the pipeline.**

The **Chain of Responsibility** pattern is essential for building flexible request handling pipelines where multiple objects can process a request without hard-coding the receiver. In the **java-design-patterns** repository by iluwatar, the `chain-of-responsibility` module demonstrates a robust implementation that separates request objects from handler logic using priority-based routing. This guide walks through the source code architecture and provides a complete implementation strategy for production Java applications.

## Understanding the Chain of Responsibility Pattern

The pattern creates a **loosely coupled pipeline** where a request traverses a chain of handler objects until one capable handler processes it. Each handler implements a common interface exposing `canHandleRequest()` for capability checking and `handle()` for execution. The chain structure allows dynamic handler registration and reordering without modifying client code.

## Core Components in the java-design-patterns Implementation

### The Request Object

Located in [[`Request.java`](https://github.com/iluwatar/java-design-patterns/blob/main/Request.java)](https://github.com/iluwatar/java-design-patterns/blob/master/chain-of-responsibility/src/main/java/com/iluwatar/chain/Request.java), this immutable data class encapsulates request metadata including `RequestType` and description, plus a mutable `handled` flag tracked via `isHandled()` and `markHandled()` methods.

### The Handler Interface

[[`RequestHandler.java`](https://github.com/iluwatar/java-design-patterns/blob/main/RequestHandler.java)](https://github.com/iluwatar/java-design-patterns/blob/master/chain-of-responsibility/src/main/java/com/iluwatar/chain/RequestHandler.java) defines the contract with four essential methods:

- `boolean canHandleRequest(Request)` – checks processing capability
- `int getPriority()` – determines execution order (lower values execute first)
- `void handle(Request)` – executes business logic
- `String name()` – identifies the handler for logging/debugging

### Concrete Handler Implementations

The repository provides three concrete implementations demonstrating type-specific handling:

- **OrcSoldier** ([[`OrcSoldier.java`](https://github.com/iluwatar/java-design-patterns/blob/main/OrcSoldier.java)](https://github.com/iluwatar/java-design-patterns/blob/master/chain-of-responsibility/src/main/java/com/iluwatar/chain/OrcSoldier.java)) – handles `COLLECT_TAX` requests with priority 1
- **OrcCommander** ([[`OrcCommander.java`](https://github.com/iluwatar/java-design-patterns/blob/main/OrcCommander.java)](https://github.com/iluwatar/java-design-patterns/blob/master/chain-of-responsibility/src/main/java/com/iluwatar/chain/OrcCommander.java)) – handles `DEFEND_CASTLE` requests with priority 2  
- **OrcOfficer** ([[`OrcOfficer.java`](https://github.com/iluwatar/java-design-patterns/blob/main/OrcOfficer.java)](https://github.com/iluwatar/java-design-patterns/blob/master/chain-of-responsibility/src/main/java/com/iluwatar/chain/OrcOfficer.java)) – handles `TORTURE_PRISONER` requests with priority 3

### The Chain Orchestrator

[[`OrcKing.java`](https://github.com/iluwatar/java-design-patterns/blob/main/OrcKing.java)](https://github.com/iluwatar/java-design-patterns/blob/master/chain-of-responsibility/src/main/java/com/iluwatar/chain/OrcKing.java) serves as the client that constructs the handler pipeline. It stores handlers in a `List<RequestHandler>` and processes requests by streaming through the list, sorting by `getPriority()`, filtering for the first capable handler via `canHandleRequest()`, and invoking `handle()`.

## Step-by-Step Implementation Guide

1. **Define the Request Model** – Create an immutable class containing request data and a mutable processed flag to prevent duplicate handling.

2. **Create the Handler Interface** – Declare methods for capability checking, priority retrieval, processing logic, and identification.

3. **Implement Concrete Handlers** – Build specialized handlers that override `canHandleRequest()` to filter by request type or business rules, assigning appropriate priority values.

4. **Build the Pipeline** – Collect handlers into a collection; the execution order is determined by sorting `getPriority()` values rather than insertion order.

5. **Process Requests** – Iterate the sorted handler chain, route to the first capable handler, and execute its `handle()` method.

6. **Enable Runtime Extensibility** – Expose methods to append handlers dynamically or inject them via dependency injection frameworks like Spring.

## Practical Java Implementation Example

The following standalone example mirrors the repository's architecture while demonstrating a minimal logging pipeline:

```java
import java.util.*;
import java.util.Objects;

// 1. Request model
public final class Request {
  private final RequestType type;
  private final String description;
  private boolean handled;

  public Request(RequestType type, String description) {
    this.type = Objects.requireNonNull(type);
    this.description = Objects.requireNonNull(description);
  }
  
  public RequestType getType() { return type; }
  public String getDescription() { return description; }
  public boolean isHandled() { return handled; }
  public void markHandled() { this.handled = true; }
}

enum RequestType {
  COLLECT_TAX, DEFEND_CASTLE, TORTURE_PRISONER
}

// 2. Handler contract
interface RequestHandler {
  boolean canHandle(Request request);
  int getPriority();
  void handle(Request request);
  String name();
}

// 3. Concrete handler
class LoggingHandler implements RequestHandler {
  public boolean canHandle(Request r) { return true; }
  public int getPriority() { return 10; }
  public void handle(Request r) {
    System.out.println("Logging request: " + r.getDescription());
    r.markHandled();
  }
  public String name() { return "Logger"; }
}

// 4. Pipeline builder
class RequestPipeline {
  private final List<RequestHandler> handlers;

  public RequestPipeline(RequestHandler... hs) {
    this.handlers = Arrays.asList(hs);
  }

  public void process(Request request) {
    handlers.stream()
            .sorted(Comparator.comparingInt(RequestHandler::getPriority))
            .filter(h -> h.canHandle(request))
            .findFirst()
            .ifPresentOrElse(
                h -> h.handle(request),
                () -> System.out.println("No handler for " + request.getDescription())
            );
  }
}

// 5. Usage
public class ChainDemo {
  public static void main(String[] args) {
    Request taxRequest = new Request(RequestType.COLLECT_TAX, "collect tax");
    RequestPipeline pipeline = new RequestPipeline(new LoggingHandler());
    pipeline.process(taxRequest);
  }
}

```

## Key Source Files in the Repository

The **java-design-patterns** implementation consists of these critical files:

- **[[`Request.java`](https://github.com/iluwatar/java-design-patterns/blob/main/Request.java)](https://github.com/iluwatar/java-design-patterns/blob/master/chain-of-responsibility/src/main/java/com/iluwatar/chain/Request.java)** – Immutable data class containing `RequestType`, description, and the `handled` flag with `markHandled()` state management.

- **[[`RequestType.java`](https://github.com/iluwatar/java-design-patterns/blob/main/RequestType.java)](https://github.com/iluwatar/java-design-patterns/blob/master/chain-of-responsibility/src/main/java/com/iluwatar/chain/RequestType.java)** – Enumeration defining supported request types (`DEFEND_CASTLE`, `COLLECT_TAX`, `TORTURE_PRISONER`).

- **[[`RequestHandler.java`](https://github.com/iluwatar/java-design-patterns/blob/main/RequestHandler.java)](https://github.com/iluwatar/java-design-patterns/blob/master/chain-of-responsibility/src/main/java/com/iluwatar/chain/RequestHandler.java)** – Interface defining `canHandleRequest()`, `getPriority()`, `handle()`, and `name()` methods that all chain members must implement.

- **[[`OrcKing.java`](https://github.com/iluwatar/java-design-patterns/blob/main/OrcKing.java)](https://github.com/iluwatar/java-design-patterns/blob/master/chain-of-responsibility/src/main/java/com/iluwatar/chain/OrcKing.java)** – Client class that aggregates handlers into a `List<RequestHandler>` and executes the routing logic using Java Streams.

- **[[`OrcCommander.java`](https://github.com/iluwatar/java-design-patterns/blob/main/OrcCommander.java)](https://github.com/iluwatar/java-design-patterns/blob/master/chain-of-responsibility/src/main/java/com/iluwatar/chain/OrcCommander.java)** – Concrete handler processing `DEFEND_CASTLE` requests with priority level 2.

- **[[`OrcOfficer.java`](https://github.com/iluwatar/java-design-patterns/blob/main/OrcOfficer.java)](https://github.com/iluwatar/java-design-patterns/blob/master/chain-of-responsibility/src/main/java/com/iluwatar/chain/OrcOfficer.java)** – Concrete handler processing `TORTURE_PRISONER` requests with priority level 3.

- **[[`OrcSoldier.java`](https://github.com/iluwatar/java-design-patterns/blob/main/OrcSoldier.java)](https://github.com/iluwatar/java-design-patterns/blob/master/chain-of-responsibility/src/main/java/com/iluwatar/chain/OrcSoldier.java)** – Concrete handler processing `COLLECT_TAX` requests with priority level 1.

- **[[`App.java`](https://github.com/iluwatar/java-design-patterns/blob/main/App.java)](https://github.com/iluwatar/java-design-patterns/blob/master/chain-of-responsibility/src/main/java/com/iluwatar/chain/App.java)** – Demonstration entry point that instantiates the king and dispatches sample requests.

## Summary

- The **Chain of Responsibility** pattern eliminates tight coupling between request senders and receivers by introducing a dynamic handler pipeline.
- The **java-design-patterns** implementation uses a priority-based sorting mechanism via `getPriority()` to determine handler execution order rather than hard-coded link references.
- Each handler explicitly declares its capabilities through `canHandleRequest()`, enabling type-specific routing without conditional logic in the client.
- The `OrcKing` client demonstrates modern Java practices by using Streams to filter and select the first capable handler from the chain.

## Frequently Asked Questions

### What is the main advantage of using Chain of Responsibility for request handling?

The primary advantage is **decoupling**—the client that sends a request does not need to know which specific object will handle it. This allows handler chains to be reorganized, extended with new handlers, or modified at runtime without changing the client code in [`OrcKing.java`](https://github.com/iluwatar/java-design-patterns/blob/main/OrcKing.java) or the request originator.

### How does the java-design-patterns implementation differ from traditional linked-list chain structures?

Unlike traditional implementations that use `setSuccessor()` to link handlers into a chain, the **java-design-patterns** version stores handlers in a `List<RequestHandler>` and uses Java Streams to sort by `getPriority()` and filter by `canHandleRequest()`. This approach leverages functional programming patterns and makes the execution order data-driven rather than structurally hard-coded.

### Can handlers pass requests to multiple successors or stop processing entirely?

Yes, handlers can modify the request state and continue the chain, or they can terminate processing by not calling subsequent handlers. In the provided implementation, once `handle()` is invoked on the first capable handler, the stream terminates via `findFirst()`, but you could modify [`OrcKing.java`](https://github.com/iluwatar/java-design-patterns/blob/main/OrcKing.java) to iterate through all handlers for logging or auditing purposes by removing the `findFirst()` short-circuit.

### What happens if no handler in the chain can process a request?

If no handler returns `true` from `canHandleRequest()`, the `findFirst()` operation returns an empty Optional, and the `ifPresentOrElse()` block executes the fallback action—typically logging a warning or throwing an exception. You should always provide a default handler or empty handler check to prevent silent request drops in production pipelines.