Spring IntegrationでChainからChainを呼び出す

### 開発環境
- Java 1.8.0
- TERASOLUNA Server Framework for Java 5.3.1.RELEASE
 - Spring core 4.3.5.RELEASE
- Spring Integration 4.3.6.RELEASE

### chainとは？
`Spring Integration`では処理と処理を`channel`でつないで開発しますが、複数の処理を1つの処理としてまとめたい場合には`chain`を利用すると便利です。

具体的なビーン定義は省きますが、以下のようなフロー定義した場合に

```xml:chain適用前
<beans xmlns="http://www.springframework.org/schema/beans"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xmlns:int="http://www.springframework.org/schema/integration"

  xsi:schemaLocation="http://www.springframework.org/schema/beans 
   http://www.springframework.org/schema/beans/spring-beans.xsd
   http://www.springframework.org/schema/integration http://www.springframework.org/schema/integration/spring-integration.xsd
   ">

  <!--メッセージングゲートウェイ-->
  <int:gateway id="gateway" default-request-channel="wwwChannel"
    service-interface="com.example.WwwGateway">

  <int:filter input-channel="wwwChannel" output-channel="xxxChannel"/>

  <int:transformer input-channel="xxxChannel" output-channel="yyyChannel" />

  <int:service-activator input-channel="yyyChannel" output-channel="zzzChannel" />
```

`chain`を使うと……

```xml:chain適用後
<beans xmlns="http://www.springframework.org/schema/beans"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xmlns:int="http://www.springframework.org/schema/integration"

  xsi:schemaLocation="http://www.springframework.org/schema/beans 
   http://www.springframework.org/schema/beans/spring-beans.xsd
   http://www.springframework.org/schema/integration http://www.springframework.org/schema/integration/spring-integration.xsd
   ">

  <!--メッセージングゲートウェイ-->
  <int:gateway id="gateway" default-request-channel="wwwChannel"
    service-interface="com.example.WwwGateway">

  <int:chain input-channel="wwwChannel" output-channel="zzzChannel">
    <int:filter/>
    <int:transformer />
    <int:service-activator />
  </chain>
```

と書けます！
フロー定義が`channel`だらけになるのを防げる利点もあります:blush:。

### chainからchainを呼び出す
で、ここからが本題です。
複雑なアプリケーションを開発していると、複数の処理をまとめた`chain`をまとめる`chain`がほしくなりますよね。
`chain`の書き方から考えて、直感的に↓のように書きました。

```xml:chainをまとめてみた
<beans xmlns="http://www.springframework.org/schema/beans"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xmlns:int="http://www.springframework.org/schema/integration"

  xsi:schemaLocation="http://www.springframework.org/schema/beans 
   http://www.springframework.org/schema/beans/spring-beans.xsd
   http://www.springframework.org/schema/integration http://www.springframework.org/schema/integration/spring-integration.xsd
   ">

  <!--メッセージングゲートウェイ-->
  <int:gateway id="gateway" default-request-channel="wwwChannel"
    service-interface="com.example.WwwGateway">

  <!--処理Aと処理Bをまとめるchain-->
  <int:chain input-channel="wwwChannel" output-channel="zzzChannel">
    <int:chain id="aProcess"/>
    <int:chain id="bProcess"/>
  </chain>

  <!--処理A-->
  <int:chain id="aProcess">
    <int:filter/>
    <int:transformer />
    <int:service-activator />
  </chain>

  <!--処理B-->
  <int:chain id="bProcess">
    <int:filter/>
    <int:transformer />
    <int:service-activator />
  </chain>
```

で、実行した結果、実行時エラー……:disappointed_relieved:
処理Aの`chain`と処理Bの`chain`に適当な`input-channel`を指定したり、処理Aと処理Bをまとめる`chain`の中で処理Aの`chain`をべた書きしてもダメでした。

### Gatewayを挟むことで解決
しばらく悩んでいたのですが、ふとドキュメントを読み返したら方法が書いてありました:sweat:。

[6.6.2 Configuring a Chain](https://docs.spring.io/spring-integration/reference/htmlsingle/#chain-namespace)の下の方の`Calling a Chain from within a Chain`で、

> Sometimes you need to make a nested call to another chain from within a chain and then come back and continue execution within the original chain. To accomplish this you can utilize a Messaging Gateway by including a <gateway> element.

なるほど……

処理Aと処理Bをまとめる`chain`で`<int:gateway>`タグを書き、`request-channel`属性に処理A・処理Bの`input-channel`を記述したところ想定する動作になりました!
やったね！

```xml:修正後
<beans xmlns="http://www.springframework.org/schema/beans"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xmlns:int="http://www.springframework.org/schema/integration"

  xsi:schemaLocation="http://www.springframework.org/schema/beans 
   http://www.springframework.org/schema/beans/spring-beans.xsd
   http://www.springframework.org/schema/integration http://www.springframework.org/schema/integration/spring-integration.xsd
   ">

  <!--メッセージングゲートウェイ-->
  <int:gateway id="gateway" default-request-channel="wwwChannel"
    service-interface="com.example.WwwGateway">

  <!--処理Aと処理Bをまとめるchain-->
  <int:chain input-channel="wwwChannel" output-channel="zzzChannel">
    <int:gateway request-channel="aChannel" />
    <int:gateway request-channel="bChannel" />
  </chain>

  <!--処理A-->
  <int:chain id="aProcess" input-channel="aChannel">
    <int:filter/>
    <int:transformer />
    <int:service-activator />
  </chain>

  <!--処理B-->
  <int:chain id="bProcess" input-channel="bChannel">
    <int:filter/>
    <int:transformer />
    <int:service-activator />
  </chain>
```

### 最後に
ドキュメントは読もう:joy: