ルーティングスリップ
バージョン 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ヘッダーのデフォルトの動作に移行します。