開発環境
- 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
を利用すると便利です。
具体的なビーン定義は省きますが、以下のようなフロー定義した場合に
<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
を使うと……
<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
だらけになるのを防げる利点もあります。
chainからchainを呼び出す
で、ここからが本題です。
複雑なアプリケーションを開発していると、複数の処理をまとめたchain
をまとめるchain
がほしくなりますよね。
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>
で、実行した結果、実行時エラー……
処理Aのchain
と処理Bのchain
に適当なinput-channel
を指定したり、処理Aと処理Bをまとめるchain
の中で処理Aのchain
をべた書きしてもダメでした。
Gatewayを挟むことで解決
しばらく悩んでいたのですが、ふとドキュメントを読み返したら方法が書いてありました。
6.6.2 Configuring a Chainの下の方の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 element.
なるほど……
処理Aと処理Bをまとめるchain
で<int:gateway>
タグを書き、request-channel
属性に処理A・処理Bのinput-channel
を記述したところ想定する動作になりました!
やったね!
<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>
最後に
ドキュメントは読もう