Spring Boot Chain of Responsibility Pattern Example
By Ercan - 26/09/2025 - 0 comments
The Chain of Responsibility is a behavioral design pattern that allows us to process a request through a sequence of handlers. Each handler decides whether it can process the request or pass it along to the next handler in the chain.
In this article, we will demonstrate how this pattern can be applied in a Spring Boot application to resolve which hashing algorithm was used for a given hash.
Problem to Solve
Given a plain text string and its hashed value, we want to determine which algorithm (MD5, SHA1, SHA256, etc.) generated the hash.
The API
Our project provides a simple API:
Request:
curl --location 'http://localhost:8080/hash/resolve' \ --header 'Content-Type: application/json' \ --data '{ "text": "hello world", "hash": "5eb63bbbe01eeed093cb22bb8f5acdc3" }'
Response:
{ "algorithm": "MD5" }
Applying the Chain of Responsibility
Instead of writing a complex if-else
or switch-case
block for each hashing algorithm, we used the Chain of Responsibility Pattern:
- Each algorithm is represented by a dedicated Chain Step class.
- If a step can resolve the hash, it returns the result.
- Otherwise, it forwards the request to the next step in the chain.
This structure makes the system open for extension (adding a new algorithm is easy) but closed for modification (no need to touch existing logic).
The Role of HashResolveChainHandler
At the core of this implementation lies the HashResolveChainHandler
.
This class is responsible for managing and executing the chain:
- It defines the entry point for the chain execution.
- It invokes the first step and ensures the request flows through the chain.
- If none of the steps can resolve the hash, it throws an exception.
By isolating the chain handling logic in one place, the code becomes clean, reusable, and easy to test.
@Component @RequiredArgsConstructor public class HashResolveChainHandler { private final ListhashResolveChainImplementations; private HashResolveChainStep resolveChain; @PostConstruct public void prepareResolveChain() { HashResolveChainStep current = null; List sortedList = hashResolveChainImplementations.stream() .sorted(Comparator.comparingInt(o -> o.getHashType().getHexStringLength())) .toList(); for (HashResolveChainStep chainStep : sortedList) { if (Objects.isNull(resolveChain)) { resolveChain = chainStep; } if (Objects.nonNull(current)) { current.setNext(chainStep); } current = chainStep; } } public HashResolveChainStep resolve(String text, String hash) { return resolveChain.matches(text, hash); } }
Benefits of This Approach
- Scalability – Adding a new algorithm requires only a new chain step class.
- Separation of Concerns – Each step handles only its own algorithm.
- Maintainability – The
HashResolveChainHandler
centralizes chain execution, avoiding duplication.
Conclusion
The Chain of Responsibility pattern provides a clean and extensible way to handle multiple possible operations without cluttering code with conditionals.
In this Spring Boot project, we applied it to build a Hash Algorithm Resolver, which can easily be extended with new hashing algorithms.
The result is a flexible, testable, and production-ready structure that demonstrates the power of design patterns in modern applications.
👉 You can explore the full source code on GitHub:
https://github.com/ercansormaz/chain-of-responsibility-pattern
Tags: spring boot, design pattern, chain of responsibility pattern, java