このバージョンはまだ開発中であり、まだ安定しているとは見なされていません。最新の安定バージョンについては、Spring Integration 6.4.3 を使用してください!

メッセージ履歴

メッセージングアーキテクチャの主な利点は、参加しているコンポーネントが相互の認識を維持できないように、疎結合です。この事実だけで、アプリケーションは非常に柔軟になり、残りのフローに影響を与えずにコンポーネントを変更したり、メッセージングルートを変更したり、メッセージ消費スタイルを変更したりできます(ポーリングとイベントドリブン)。しかし、この控えめなスタイルのアーキテクチャは、物事がうまくいかない場合には難しいことがわかります。デバッグするときは、おそらくメッセージに関する情報(その発信元、通過したチャネル、その他の詳細)をできるだけ多く取得する必要があります。

メッセージ履歴は、デバッグまたは監査証跡を維持するために、メッセージパスの認識レベルを維持するオプションを提供することで役立つパターンの 1 つです。Spring 統合は、メッセージにヘッダーを追加し、メッセージが追跡対象コンポーネントを通過するたびにそのヘッダーを更新することにより、メッセージフローを設定してメッセージ履歴を維持する簡単な方法を提供します。

メッセージ履歴の構成

メッセージ履歴を有効にするには、次の例に示すように、構成で message-history 要素 (または @EnableMessageHistory) を定義するだけで済みます。

  • Java

  • XML

@Configuration
@EnableIntegration
@EnableMessageHistory
<int:message-history/>

これで、すべての名前付きコンポーネント ( "id" が定義されている) が追跡されます。フレームワークは、メッセージに「履歴」ヘッダーを設定します。その値は List<Properties> です。

次の構成例を検討してください。

  • Java

  • XML

@MessagingGateway(defaultRequestChannel = "bridgeInChannel")
public interface SampleGateway {
   ...
}

@Bean
@Transformer(inputChannel = "enricherChannel", outputChannel="filterChannel")
HeaderEnricher sampleEnricher() {
    HeaderEnricher enricher =
           new HeaderEnricher(Collections.singletonMap("baz", new StaticHeaderValueMessageProcessor("baz")));
    return enricher;
}
<int:gateway id="sampleGateway"
    service-interface="org.springframework.integration.history.sample.SampleGateway"
    default-request-channel="bridgeInChannel"/>

<int:header-enricher id="sampleEnricher" input-channel="enricherChannel" output-channel="filterChannel">
    <int:header name="baz" value="baz"/>
</int:header-enricher>

上記の構成により、単純なメッセージ履歴構造が生成され、出力は次のようになります。

[{name=sampleGateway, type=gateway, timestamp=1283281668091},
 {name=sampleEnricher, type=header-enricher, timestamp=1283281668094}]

メッセージ履歴にアクセスするには、MessageHistory ヘッダーにアクセスするだけで済みます。次の例は、その方法を示しています。

Iterator<Properties> historyIterator =
    message.getHeaders().get(MessageHistory.HEADER_NAME, MessageHistory.class).iterator();
assertTrue(historyIterator.hasNext());
Properties gatewayHistory = historyIterator.next();
assertEquals("sampleGateway", gatewayHistory.get("name"));
assertTrue(historyIterator.hasNext());
Properties chainHistory = historyIterator.next();
assertEquals("sampleChain", chainHistory.get("name"));

すべてのコンポーネントを追跡したくない場合があります。名前に基づいて履歴を特定のコンポーネントに限定するには、tracked-components 属性を指定し、追跡するコンポーネントに一致するコンポーネント名とパターンのコンマ区切りリストを指定します。次の例は、その方法を示しています。

  • Java

  • XML

@Configuration
@EnableIntegration
@EnableMessageHistory("*Gateway", "sample*", "aName")
<int:message-history tracked-components="*Gateway, sample*, aName"/>

前の例では、'Gateway' で終わる、'sample' で始まる、または名前 'aName' と完全に一致するコンポーネントに対してのみ、メッセージ履歴が保持されます。

さらに、MessageHistoryConfigurer Bean が IntegrationMBeanExporter によって JMX MBean として公開され ( MBean エクスポーターを参照)、実行時にパターンを変更できるようになりました。ただし、パターンを変更するには、Bean を停止 (メッセージ履歴をオフにする) する必要があることに注意してください。この機能は、システムを分析するために履歴を一時的にオンにするのに役立つ場合があります。MBean のオブジェクト名は <domain>:name=messageHistoryConfigurer,type=MessageHistoryConfigurer です。

1 つの @EnableMessageHistory (または <message-history/>) のみを、コンポーネント追跡構成の単一ソースとしてアプリケーションコンテキストで宣言する必要があります。MessageHistoryConfigurer に汎用 Bean 定義を使用しないでください。
バージョン 6.3 より前のバージョンでは、メッセージ履歴ヘッダーは不変 (履歴を書き換えることはできません) でした。すべての単一トラックで、MessageHistory の新しいインスタンスだけでなく、完全に新しいメッセージコピーが作成されました。現在は追加専用モードで動作します。最初のトラックは、新しい MessageHistory コンテナーを使用して新しいメッセージを作成します。残りのすべての MessageHistory.write() 呼び出しでは、既存のヘッダーに新しいエントリが追加されますが、新しいメッセージは作成されません。これにより、アプリケーションのパフォーマンスが大幅に向上します。同じメッセージを複数のコンシューマー (PublishSubscribeChannelAbstractMessageRouterWireTap など) に送信できる、またはスプリッターが入力メッセージに基づいて複数の出力を生成できるフレームワーク内のすべてのコンポーネントは、既存の MessageHistory ヘッダーをそれらの新しいメッセージに複製するようになりました。フレームワークの範囲外のその他の複数生成のユースケースでは、並列ダウンストリームサブフローが独自のメッセージ履歴トレースにコントリビュートするように、AbstractIntegrationMessageBuilder.cloneMessageHistoryIfAny() API を使用することをお勧めします。