ルーティングスリップ
バージョン 4.1 から、Spring Integration はルーティングスリップ (英語) エンタープライズ統合パターンの実装を提供します。outputChannel
がエンドポイントに指定されていない場合、routingSlip
メッセージヘッダーとして実装され、AbstractMessageProducingHandler
インスタンスの次のチャネルを決定するために使用されます。このパターンは、メッセージフローを決定するために複数のルーターを構成することが困難になる複雑で動的な場合に役立ちます。output-channel
を持たないエンドポイントにメッセージが到着すると、routingSlip
が調べられて、メッセージが送信される次のチャネルが決定されます。ルーティングスリップがなくなると、通常の replyChannel
処理が再開されます。
ルーティングスリップの構成は、HeaderEnricher
オプションとして提示されます。これは、次の例に示すように、path
エントリを含むセミコロンで区切られたルーティングスリップです。
<util:properties id="properties">
<beans:prop key="myRoutePath1">channel1</beans:prop>
<beans:prop key="myRoutePath2">request.headers[myRoutingSlipChannel]</beans:prop>
</util:properties>
<context:property-placeholder properties-ref="properties"/>
<header-enricher input-channel="input" output-channel="process">
<routing-slip
value="${myRoutePath1}; @routingSlipRoutingPojo.get(request, reply);
routingSlipRoutingStrategy; ${myRoutePath2}; finishChannel"/>
</header-enricher>
上記の例には次のものがあります。
ルーティングスリップ
path
のエントリを解決可能なキーとして指定できることを示すための<context:property-placeholder>
構成。<header-enricher>
<routing-slip>
サブエレメントは、RoutingSlipHeaderValueMessageProcessor
をHeaderEnricher
ハンドラーに移入するために使用されます。RoutingSlipHeaderValueMessageProcessor
は、解決されたルーティングスリップpath
エントリのString
配列を受け入れ、key
としてpath
を、routingSlipIndex
として0
を含むsingletonMap
を(processMessage()
から)返します。
ルーティングスリップ path
エントリには、MessageChannel
Bean 名、RoutingSlipRouteStrategy
Bean 名、および Spring 式(SpEL)を含めることができます。RoutingSlipHeaderValueMessageProcessor
は、最初の processMessage
呼び出しで、各ルーティングスリップ path
エントリを BeanFactory
に対してチェックします。エントリ(アプリケーションコンテキストの Bean 名ではない)を ExpressionEvaluatingRoutingSlipRouteStrategy
インスタンスに変換します。RoutingSlipRouteStrategy
エントリは、null または空の String
を返すまで複数回呼び出されます。
ルーティングスリップは getOutputChannel
プロセスに関係しているため、リクエスト / 応答コンテキストがあります。RoutingSlipRouteStrategy
は、requestMessage
および reply
オブジェクトを使用する次の outputChannel
を決定するために導入されました。この戦略の実装は、アプリケーションコンテキストで Bean として登録する必要があり、その Bean 名はルーティングスリップ path
で使用されます。ExpressionEvaluatingRoutingSlipRouteStrategy
実装が提供されます。SpEL 式を受け入れ、内部 ExpressionEvaluatingRoutingSlipRouteStrategy.RequestAndReply
オブジェクトが評価コンテキストのルートオブジェクトとして使用されます。これは、各 ExpressionEvaluatingRoutingSlipRouteStrategy.getNextPath()
呼び出しの EvaluationContext
作成のオーバーヘッドを回避するためです。これは、Message<?> request
と Object reply
の 2 つのプロパティを持つ単純な Java Bean です。この式の実装では、SpEL(たとえば @routingSlipRoutingPojo.get(request, reply)
および request.headers[myRoutingSlipChannel]
)を使用してルーティングスリップ path
エントリを指定し、RoutingSlipRouteStrategy
に Bean を定義しないようにすることができます。
requestMessage 引数は常に Message<?> です。コンテキストに応じて、応答オブジェクトは Message<?> 、AbstractIntegrationMessageBuilder 、任意のアプリケーションドメインオブジェクト(たとえば、サービスアクティベータによって呼び出された POJO メソッドによって返される場合)です。最初の 2 つのケースでは、SpEL(または Java 実装)を使用すると、通常の Message プロパティ(payload および headers )が利用可能です。任意のドメインオブジェクトの場合、これらのプロパティは使用できません。このため、結果が次のパスの決定に使用される場合、POJO メソッドと一緒に回覧先を使用する場合は注意してください。 |
ルーティングスリップが分散環境に関係している場合、ルーティングスリップ path にインライン式を使用しないことをお勧めします。この推奨事項は、クロス JVM アプリケーションなどの分散環境、メッセージブローカー(AMQP サポートまたは JMS サポートなど)を介した request-reply の使用、または統合フローでの永続的な MessageStore (メッセージストア)の使用に適用されます。フレームワークは RoutingSlipHeaderValueMessageProcessor を使用して ExpressionEvaluatingRoutingSlipRouteStrategy オブジェクトに変換し、routingSlip メッセージヘッダーで使用されます。このクラスは Serializable ではないため(BeanFactory に依存するため、そうではありません)、Message 全体がシリアライズ不可能になり、分散操作では NotSerializableException になります。この制限を克服するには、ExpressionEvaluatingRoutingSlipRouteStrategy Bean を希望の SpEL に登録し、ルーティングスリップ path 構成でその Bean 名を使用します。 |
Java 構成の場合、次の例に示すように、RoutingSlipHeaderValueMessageProcessor
インスタンスを HeaderEnricher
Bean 定義に追加できます。
@Bean
@Transformer(inputChannel = "routingSlipHeaderChannel")
public HeaderEnricher headerEnricher() {
return new HeaderEnricher(Collections.singletonMap(IntegrationMessageHeaderAccessor.ROUTING_SLIP,
new RoutingSlipHeaderValueMessageProcessor("myRoutePath1",
"@routingSlipRoutingPojo.get(request, reply)",
"routingSlipRoutingStrategy",
"request.headers[myRoutingSlipChannel]",
"finishChannel")));
}
エンドポイントが応答を生成し、outputChannel
が定義されていない場合、ルーティングスリップアルゴリズムは次のように機能します。
routingSlipIndex
は、ルーティングスリップpath
リストから値を取得するために使用されます。routingSlipIndex
の値がString
の場合、BeanFactory
から Bean を取得するために使用されます。返された Bean が
MessageChannel
のインスタンスである場合、次のoutputChannel
として使用され、routingSlipIndex
は応答メッセージヘッダーでインクリメントされます(ルーティングスリップpath
エントリは変更されません)。返された Bean が
RoutingSlipRouteStrategy
のインスタンスであり、そのgetNextPath
が空のString
を返さない場合、その結果は次のoutputChannel
の Bean 名として使用されます。routingSlipIndex
は変更されません。RoutingSlipRouteStrategy.getNextPath
が空のString
またはnull
を返す場合、routingSlipIndex
はインクリメントされ、getOutputChannelFromRoutingSlip
は次のルーティングスリップpath
アイテムに対して再帰的に呼び出されます。次のルーティングスリップ
path
エントリがString
でない場合、RoutingSlipRouteStrategy
のインスタンスでなければなりません。routingSlipIndex
がルーティングスリップpath
リストのサイズを超えると、アルゴリズムは標準replyChannel
ヘッダーのデフォルトの動作に移行します。