Apache Camel × Spring Boot 入門編 〜EIP を工場ラインに例えて理解する〜

![11D7ECF8-73E4-42FD-9E58-C1536CFF5CBD.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4063686/13363c89-8a83-4b1f-8827-710fa83abd3b.png)


Apache Camel を使うと、複数のシステム間でのメッセージの流れをルール化されたパターン（EIP）として定義できます。  
これにより、処理内容が標準化され、可読性や保守性の向上、コードの共通化、再利用性の確保が可能になります。

---

## EIPとは？

EIP（Enterprise Integration Patterns）は、システム間連携における共通処理をパターンとして整理した設計手法です。  
Apache Camel はこれらをベースにメッセージの受信、分岐、加工、集約、再送などの処理を構成することができます。

---

## 処理モデルの構造：工場ラインへの対応

Camel の処理構造を、工場のベルトコンベアに例えることで、以下のように各コンポーネントの役割を整理できます。

~~~
[出荷受付]
    ↓（Exchange：箱）
[Route：ベルトコンベア]
    ↓
[各種ステーション：EIPコンポーネント]
    ↓
[最終出荷先（外部システム）]
~~~

---

## Camelコンポーネントと構造の対応表

| Camel要素 | 処理モデル上の役割 | 説明 |
|-----------|--------------------|------|
| **Exchange** | 処理対象の箱 | メッセージの本体やメタ情報を含む単位 |
| **Route** | 処理ライン（ベルト） | Exchange が処理ステップを流れる通路 |
| **Message** | Exchange 内の中身 | 本文（Body）と属性情報（Header）など |
| **Processor / Bean** | 加工ステーション | Javaコードによる加工処理。`Processor`はインターフェース実装、`Bean`はメソッド呼び出しで記述可能。 |
| **EIP 各種** | 検査・分岐・集約などの工程 | choice / split / aggregate 等 |
| **Dead Letter Channel** | 破棄・退避処理 | 処理不能な Exchange を退避させる場所 |

---

## 主要EIPと工程の対応

| EIP | 工程内容 | 説明 |
|-----|----------|------|
| `filter()` | 検品 | 条件に合わないメッセージを除外 |
| `choice()` | 分岐処理 | 条件に応じて別のルートへ送る |
| `split()` | 分割処理 | リストやCSVなどの複数項目を個別に分ける |
| `aggregate()` | 集約処理 | 複数メッセージを一定条件でまとめる |
| `recipientList()` | 宛先動的振り分け | 動的にルーティング先をリスト指定 |
| `loop()` | ループ処理 | 一定回数や条件で繰り返す処理 |
| `seda()` | 非同期ステップ | 非同期で一時キューに流す（並列・遅延処理） |
| `multicast()` | 複数出力 | 同一メッセージを複数ルートに同時送出 |
| `wireTap()` | 非同期コピー | メイン処理に影響せずコピーを別処理へ |
| `onException()` | エラーハンドリング | 例外発生時の代替処理やルート移動 |

---

## 実装イメージ（Java DSL / XML DSL / YAML DSL）

### Java DSL

~~~java
// direct:start からルート開始
from("direct:start")
  // 本文をカンマで分割し、それぞれ個別に処理
  .split(body().tokenize(","))
    .to("bean:ItemProcessor") // Java Bean で分割要素を処理
  .end()
  // メッセージを5件単位で集約し、ログ出力
  .aggregate(constant(true), new MyAggregationStrategy())
    .completionSize(5)
    .to("log:done");
~~~

### XML DSL

~~~xml
<route id="example-route">
  <from uri="direct:start" description="ルートの開始ポイント（direct:start）"/>
  <split description="カンマでメッセージを分割">
    <tokenize token=","/>
    <to uri="bean:ItemProcessor" description="分割された各要素を Java Bean で処理"/>
  </split>
  <aggregate strategyRef="myAggregationStrategy" description="5件単位でメッセージを集約">
    <completionSize>5</completionSize>
    <to uri="log:done" description="集約結果をログ出力"/>
  </aggregate>
</route>
~~~

### YAML DSL

~~~yaml
- route:
    id: example-route
    from:
      uri: direct:start  # ルートの開始ポイント

    steps:
      - split:  # カンマで分割
          tokenizer:
            token: ","
          steps:
            - to: bean:ItemProcessor  # Java Bean による処理

      - aggregate:  # 5件単位で集約
          correlationExpression:
            constant: true
          completionSize: 5
          steps:
            - to: log:done  # ログ出力
~~~

---

## 参考資料

- [Apache Camel公式サイト](https://camel.apache.org/)
- [EIP一覧（公式）](https://camel.apache.org/components/latest/eips/enterprise-integration-patterns.html)
- [Camel Examples](https://github.com/apache/camel-examples)
- [赤帽エンジニアブログ - Apache Camel 超入門](https://rheb.hatenablog.com/entry/2022/05/27/191550)


---

実業務での Camel 活用においても、このような構造的設計を意識することで、保守性・再利用性の高いルーティング設計が可能になります。