Chain of Responsibility Pattern in Spring Application
Tags: java, spring, design, tutorial
Published: 2022-10-01 15:44:17

In this article, I'm showing you how to apply the Chain Of Responsibility pattern in your Spring application smoothly. You can find the source code in [this GitHub repository](https://github.com/SimonHarmonicMinor/spring-chain-of-responsibility-example).

![Meme article cover](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/3w3tzonjb4cx68ynamw1.png)

## Domain

Let's clarify the CoR pattern purpose. You can read its entire explanation by [this link](https://sourcemaking.com/design_patterns/chain_of_responsibility). Though now I'm sharing with you one particular example.

Imagine that we're creating a real-time enrichment service. It consumes a message, fulfils it with additional data, and produces the final enriched message as the output. Supposing we have 3 types of enrichment:

1. Phone number determination by `SESSIONID` cookie.
2. The person's age retrieving by the `userId` field.
3. The person's geolocation obtaining by their IP address.

## Development

Firstly, we need the `EnrichmentStep` interface.

```java
public interface EnrichmentStep {
    Message enrich(Message msg);
}
```

The interface accepts the current `Message` and returns the enriched one.

> In this case, the `Message` class is [immutable](https://www.geeksforgeeks.org/create-immutable-class-java/). Meaning that `EnrichmentStep` returns the new object but not the same one that is modified. Immutable classes usage is good practice because it eliminates lots of possible concurrency problems.

There are 3 types of enrichment. Therefore, we need 3 `EnrichmentStep` implementations. I'm showing you the phone number example. Though if you're curious, you can see others in [the repository](https://github.com/SimonHarmonicMinor/spring-chain-of-responsibility-example).

```java
@Service
public class PhoneNumberEnrichmentStep implements EnrichmentStep {
  private final PhoneNumberRepository phoneNumberRepository;

  @Override
  public Message enrich(Message message) {
    return message.getValue("SESSIONID")
        .flatMap(phoneNumberRepository::findPhoneNumber)
        .map(phoneNumber -> message.with("phoneNumber", phoneNumber))
        .orElse(message);
  }
}
```

> In this case, we don't care about the `PhoneNumberRepository` implementation.

OK then. Each `EnrichmentStep` might enhance the input message with additional data. But we need to proceed with all the enrichment steps to obtain the fulfilled message. The Chain of Responsibility pattern comes in handy. Let's rewrite the `EnrichmentStep` interface a bit.

```java
public interface EnrichmentStep {
  Message enrich(Message message);
  
  void setNext(EnrichmentStep step);
}
```

Each `EnrichmentStep` implementation might reference the next chain element. Take a look at the modified `PhoneNumberEnrichmentStep` implementation.

```java
@Service
public class PhoneNumberEnrichmentStep implements EnrichmentStep {
  private final PhoneNumberRepository phoneNumberRepository;
  private EnrichmentStep next;

  @Override
  public Message enrich(Message message) {
    return message.getValue("SESSIONID")
        .flatMap(phoneNumberRepository::findPhoneNumber)
        .map(phoneNumber -> next.enrich(
            message.with("phoneNumber", phoneNumber)
        ))
        .orElseGet(() -> next.enrich(message));
  }

  public void setNext(EnrichmentStep step) {
    this.next = step;
  }
}
```

Now the `PhoneNumberEnrichmentStep` works a bit differently:

1. If the message is successfully enriched, the fulfilled result proceeds to the next enrichment step.
2. Otherwise the message with no modifications goes further.

It's time to connect `EnrichmentStep` implementations into a linked list, i.e. build the Chain of Responsibility.

First of all, let's point out another essential detail. You see, the `EnrichmentStep` defines that there is always the next step. But a chain cannot be infinite. Therefore, there is a possibility that the next chain element might be absent. In this case, we have to repeat _not-null_ checks in every `EnrichmentStep`. Because any implementation might be the last step. Thankfully there is a better alternative. The `NoOpEnrichmentStep` is the implementation that just returns the same message without any actions. Take a look at the code block below.

```java
public class NoOpEnrichmentStep implements EnrichmentStep {

  @Override
  public Message enrich(Message message) {
    return message;
  }

  @Override
  public void setNext(EnrichmentStep step) {
    // no op
  }
}
```

It allows us to set this object as the last chain element. So, it guarantees that the `setNext` method is always invoked with some value and we don't have to repeat _not-null_ checks.

> The `NoOpEnrichmentStep` is actually an example of the [Null Object Design pattern](https://sourcemaking.com/design_patterns/null_object).

Now we're creating the `EnrichmentStepFacade`. Take a look at the code snippet below.

```java
@Service
public class EnrichmentStepFacade {
  private final EnrichmentStep chainHead;

  public EnrichmentStepFacade(List<EnrichmentStep> steps) {
    if (steps.isEmpty()) {
      chainHead = new NoOpEnrichmentStep();
    } else {
      for (int i = 0; i < steps.size(); i++) {
        var current = steps.get(i);
        var next = i < steps.size() - 1 ? steps.get(i + 1) : new NoOpEnrichmentStep();
        current.setNext(next);
      }
      chainHead = steps.get(0);
    }
  }

  public Message enrich(Message message) {
    return chainHead.enrich(message);
  }
}
```

The constructor accepts a list of all `EnrichmentStep` implementations that are registered as Spring beans in the current [application context](https://www.baeldung.com/spring-application-context) (the framework does this automatically). If the list is empty, then the `chainHead` is just the `NoOpEnrichmentStep` instance. Otherwise, the current element is linked to the next one. But the last chain element always references `NoOpEnrichmentStep`. Meaning that calling the first element of the provided list will execute the whole chain! What's even more exciting is that you can define the order of elements in the chain just by putting the Spring [`@Order`](https://www.baeldung.com/spring-order) annotation. The injected `List<EnrichmentStep>` collection will be sorted accordingly.

## Refactoring

### The generic chain element

Though the solution is working it's not complete yet. There are a few details to improve. Firstly, take a look at the `EnrichmentStep` definition again.

```java
public interface EnrichmentStep {
  Message enrich(Message message);

  void setNext(EnrichmentStep step);
}
```

The Chain of Responsibility is the generic pattern. Perhaps we'd apply it to another scenario. So, let's extract the `setNext` method to the separate interface. Take a look at the definition below.

```java
public interface ChainElement<T> {
  void setNext(T step);
}
```

And now the `EnrichmentStep` should extend it with the appropriate generic value.

```java
public interface EnrichmentStep extends ChainElement<EnrichmentStep> {
  Message enrich(Message message);
}
```

### Chain building encapsulation

That's a slight improvement. What else can we do? Take a look at the `EnrichmentStepFacade` definition down below again.

```java
@Service
public class EnrichmentStepFacade {

  private final EnrichmentStep chainHead;

  public EnrichmentStepFacade(List<EnrichmentStep> steps) {
    if (steps.isEmpty()) {
      chainHead = new NoOpEnrichmentStep();
    } else {
      for (int i = 0; i < steps.size(); i++) {
        var current = steps.get(i);
        var next = i < steps.size() - 1 ? steps.get(i + 1) : new NoOpEnrichmentStep();
        current.setNext(next);
      }
      chainHead = steps.get(0);
    }
  }

  public Message enrich(Message message) {
    return chainHead.enrich(message);
  }
}
```

As a matter of fact, the `EnrichmentStep` interface represents a generic chain element. So, we can encapsulate the code inside the `ChainElement` interface directly. Check out the code snippet below.

```java
public interface ChainElement<T> {
  void setNext(T step);

  static <T extends ChainElement<T>> T buildChain(List<T> elements, T lastElement) {
    if (elements.isEmpty()) {
      return lastElement;
    }
    for (int i = 0; i < elements.size(); i++) {
      var current = elements.get(i);
      var next = i < elements.size() - 1 ? elements.get(i + 1) : lastElement;
      current.setNext(next);
    }
    return elements.get(0);
  }
}
```

The `buildChain` method accepts a list of business implementations that proceed with the actual use case and the stub one as the last element (i.e. `NoOpEnrichmentStep`).

Now we can refactor the `EnrichmentStepFacade` as well. Take a look at the code example below.

```java
@Service
public class EnrichmentStepFacade {
  private final EnrichmentStep chainHead;

  public EnrichmentStepFacade(List<EnrichmentStep> steps) {
    this.chainHead = ChainElement.buildChain(steps, new NoOpEnrichmentStep());
  }

  public Message enrich(Message message) {
    return chainHead.enrich(message);
  }
}
```

Much clearer and easier to understand.

### AbstractEnrichmentStep

Anyway, there are still some caveats about the `EnrichmentStep` implementation. Take a look at the `PhoneNumberEnrichmentStep` definition below.

```java
@Service
class PhoneNumberEnrichmentStep implements EnrichmentStep {
  private final PhoneNumberRepository phoneNumberRepository;
  private EnrichmentStep next;

  @Override
  public Message enrich(Message message) {
    return message.getValue("SESSIONID")
        .flatMap(phoneNumberRepository::findPhoneNumber)
        .map(phoneNumber -> next.enrich(
            message.with("phoneNumber", phoneNumber)
        ))
        .orElseGet(() -> next.enrich(message));
  }

  public void setNext(EnrichmentStep step) {
    this.next = step;
  }
}
```

There are 2 details I want to point out:

1. The `setNext` method overriding. Each implementation has to store the reference to the next chain element.
2. The `next.enrich(...)` method is called 2 times. So, the implementation has to repeat the contract requirements over and over again.

To eliminate these code smells, we declare the `AbstractEnrichmentStep` class. Take a look at the code snippet below.

```java
public abstract class AbstractEnrichmentStep implements EnrichmentStep {
  private EnrichmentStep next;

  @Override
  public final void setNext(EnrichmentStep step) {
    this.next = step;
  }

  @Override
  public final Message enrich(Message message) {
    try {
        return enrichAndApplyNext(message)
            .map(enrichedMessage -> next.enrich(enrichedMessage))
            .orElseGet(() -> next.enrich(message));
    }
    catch (Exception e) {
        log.error("Unexpected error during enrichment for msg {}", message, e);
        return next.enrich(message);
    }
  }

  protected abstract Optional<Message> enrichAndApplyNext(Message message);
}
```

Firstly, the next `EnrichmentStep` is encapsulated within the `AbstractEnrichmentStep` and the `setNext` method is final. So, implementations don't bother about storing the further chain element.

Secondly, there is the new method `enrichAndApplyNext`. As a matter of fact, an implementation doesn't have to worry about chaining nuances at all. If enrichment is successful, then the method returns the new message. Otherwise, `Optional.empty` is retrieved.

And finally, the `enrich` method is also final. Therefore, its implementation is fixed. As you can see, we enrichment algorithm is not duplicated across multiple classes but placed within a single method. It is simple:

1. If `enrichAndApplyNext` returns the value, proceed it to the next enrichment step.
2. If no value is present, invoke the next step with the origin message.
3. If any error occurs, log it and continue the enrichment chain further normally.

The last point is crucial. We don't know how many implementations there will be and what exceptions they may throw. Nevertheless, we don't want to stop the enrichment process entirely but just skip the failed chain block execution. Take a look at the `PhoneNumberEnrichmentRepository` implementation below that extends the defined `AbstractEnrichmentStep`.

```java
@Service
class PhoneNumberEnrichmentStep extends AbstractEnrichmentStep {
  private final PhoneNumberRepository phoneNumberRepository;

  @Override
  protected Optional<Message> enrichAndApplyNext(Message message) {
    return message.getValue("SESSIONID")
        .flatMap(phoneNumberRepository::findPhoneNumber)
        .map(phoneNumber ->
            message.with("phoneNumber", phoneNumber)
        );
  }
}
```

As you see, there is no infrastructure code anymore. Just pure business logic.

## Points of improvement

If you have many enrichment steps, then certainly you want to monitor their activity.

1. What time it takes to enrich the message on the particular step?
2. What are the enrichment statistics? Which enrichments steps hit and miss most frequently?
3. Which steps fail and why?

Metrics is the answer to all of these questions. Besides, the `AbstractEnrichmentStep` declaration can also help us to record monitoring values clearer. Check out the code snippet down below.

```java
public abstract class AbstractEnrichmentStep implements EnrichmentStep {
  @Autowired
  private MetricService metricService;
  private EnrichmentStep next;

  protected abstract EnrichmentType getEnrichmentType();

  @Override
  public final void setNext(EnrichmentStep step) {
    this.next = step;
  }

  @Override
  public final Message enrich(Message message) {
    var start = System.nanoTime();
    var type = getEnrichmentType();
    try {
        return enrichAndApplyNext(message)
            .map(enrichedMessage -> {
                metricService.recordHit(type);
                return next.enrich(enrichedMessage);
            })
            .orElseGet(() -> {
                metricService.recordMiss(type);
                return next.enrich(message);
            });
    }
    catch (Exception e) {
        log.error("Unexpected error during enrichment for msg {}", message, e);
        metricService.recordError(type, e);
        return next.enrich(message);
    }
    finally {
        var duration = Duration.ofNanos(System.nanoTime() - start);
        metricService.recordDuration(type, duration);
    }
  }

  protected abstract Optional<Message> enrichAndApplyNext(Message message);
}
```

First of all, there is a new abstract method `getEnrichmentType()`. Each implementation should return its type to distinguish result metrics correctly.

Then the rules are these:
1. If the message is successfully enriched, the `recordHit` method is called.
2. If the message enrichment is skipped, the `recordMiss` goes.
3. If any error occurs, then the `recordError` comes into play.
4. Finally the whole enrichment step duration is stored by `recordDuration` invocation.

You can tune the metrics the way you want. The idea is that the implementations don't care about those details. [The Open-closed principle](https://en.wikipedia.org/wiki/Open%E2%80%93closed_principle) in action!

## Conclusion

That's all I wanted to tell you about the Chain of Responsibility implementation in the Spring ecosystem. If you have any questions or suggestions, please leave your comments down below. Thanks for reading!

## Resources

1. [The repository with the source code](https://github.com/SimonHarmonicMinor/spring-chain-of-responsibility-example)
1. [Null Object Design pattern](https://sourcemaking.com/design_patterns/null_object)
1. [Chain of Responsibility pattern explanation](https://sourcemaking.com/design_patterns/chain_of_responsibility)
1. [Immutability in Java](https://www.geeksforgeeks.org/create-immutable-class-java/)
1. [Spring Application Context](https://www.baeldung.com/spring-application-context)
1. [Spring `@Order` annotation](https://www.baeldung.com/spring-order)
1. [The Open-closed principle](https://en.wikipedia.org/wiki/Open%E2%80%93closed_principle)