はじめに
今回紹介するMessage Historyパターンは、Eneterprise Integration Patternsの1つになります。
Camelではコンポーネントやプロセッサー間はメッセージを介しており疎結合になっています。
そのため、具体的にメッセージがどのようなフローでルートを通ってきたかが分からなくなります。
Message Historyパターンではメッセージに履歴(足跡みたいなもの)をつけていくことで、デバッグや解析に役立てることができます。
画像の出典:Enterprise Integration Patterns - Message History
例外発生時のMessage History
Camelで開発していてMessage Historyを見る機会の代表例は例外発生時です。
CamelではMessage Historyパターンが自動で適用され、例外発生時にデフォルトでMessage Historyが表示されるようになっています。
以下のXMLはルートの途中で強制的にRuntimeExceptionを発生させています。
<route>
<from uri="timer:trigges?repeatCount=1" />
<to uri="direct:a" />
<to uri="direct:b" />
<log message="body: ${body}" />
</route>
<route>
<from uri="direct:a" />
<log message="route a" />
</route>
<route>
<from uri="direct:b" />
<throwException exceptionType="java.lang.RuntimeException" message="test exception" />
<log message="route b" />
</route>
このルートを実行すると以下のログが出力されます。
"Message History"の文字列以下がMessage Historyの表示です。
メッセージが通った順番にRoute Id, Processor Id, Processorと実行時間(Elapsed)が表示されています。また、今回は例外のため、Exchange中のStackTraceの情報も表示されています。
[2019-02-14 22:15:52.294], [ERROR], o.a.c.p.DefaultErrorHandler, Camel (camel-1) thread #1 - timer://trigges, org.apache.camel.processor.DefaultErrorHandler, Failed delivery for (MessageId: ID-mky-PC-1550150150431-0-2 on ExchangeId: ID-mky-PC-1550150150431-0-1). Exhausted after delivery attempt: 1 caught: java.lang.RuntimeException: test exception
Message History
---------------------------------------------------------------------------------------------------------------------------------------
RouteId ProcessorId Processor Elapsed (ms)
[route1 ] [route1 ] [timer://trigges?repeatCount=1 ] [ 16]
[route1 ] [to1 ] [direct:a ] [ 8]
[route2 ] [log2 ] [log ] [ 5]
[route1 ] [to2 ] [direct:b ] [ 0]
[route3 ] [throwException1 ] [throwException[ref:null] ] [ 1]
Stacktrace
---------------------------------------------------------------------------------------------------------------------------------------
java.lang.RuntimeException: test exception
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) ~[?:1.8.0_172]
~省略~
XML DSLでMessage Historyを表示する
最初の例は例外発生時にMessage Historyを表示させることを確認しましたが、明示的にMessage Historyを表示させるやり方を見ていきましょう。
XML DSLでMessage Historyを明示的に表示するには、messageHistoryプロパティを使用します。
messageHistoryプロパティを使用したルートの例は以下のようになります。
<route>
<from uri="timer:trigges?repeatCount=1" />
<to uri="direct:a" />
<to uri="direct:b" />
<log message="body: ${body}" />
</route>
<route>
<from uri="direct:a" />
<log message="route a" />
</route>
<route>
<from uri="direct:b" />
<log message="${messageHistory}" />
<log message="route b" />
</route>
このルートを実行すると以下のようにMessage Historyが表示されます。
例外発生時のMessage Historyとほぼ同じ内容ですが、今回は例外ではないためStackTraceは表示されません。
Message History
---------------------------------------------------------------------------------------------------------------------------------------
RouteId ProcessorId Processor Elapsed (ms)
[route1 ] [route1 ] [timer://trigges?repeatCount=1 ] [ 14]
[route1 ] [to1 ] [direct:a ] [ 7]
[route2 ] [log2 ] [log ] [ 4]
[route1 ] [to2 ] [direct:b ] [ 0]
[route3 ] [log3 ] [log ] [ 0]
Exchange
---------------------------------------------------------------------------------------------------------------------------------------
Exchange[
Id ID-mky-PC-1550150269136-0-1
ExchangePattern InOnly
Headers {breadcrumbId=ID-mky-PC-1550150269136-0-1, firedTime=Thu Feb 14 22:17:50 JST 2019}
BodyType null
Body [Body is null]
Java DSLでMessage Historyを表示する
次にJava DSLでも明示的にMessage Historyを表示してみます。
こちらもmessageHistoryプロパティを使用するだけです。出力されるMessage HistoryはXML DSLと同じであるため省略します。
from("timer:trigger?repeatCount=1")
.to("direct:a")
.to("direct:b")
.log("Body-before: ${body}")
.log("Body-after: ${body}");
from("direct:a")
.log("route a");
from("direct:b")
.log("${messageHistory}")
.log("route b");
プロセッサ中でMessage Historyを表示する
プロセッサ中でMessage Historyを出力するには、MessageHelperクラスのdumpMessageHistoryStacktraceメソッドを使用します。dumpMessageHistoryStacktraceメソッドを使用することで整形された文字列でMessage Historyを取得することができます。
以下はプロセッサーのprocessメソッドでdumpMessageHistoryStacktraceメソッドを使用して、Message Historyを標準出力に表示した例になります。
public void process(Exchange exchange) {
String msgHist = MessageHelper.dumpMessageHistoryStacktrace(exchange, new DefaultExchangeFormatter(), false);
System.out.println(msgHist);
}
dumpMessageHistoryStacktraceメソッドの3番目の引数はStackTraceを表示するかどうかのフラグです。
trueにしておくと例外発生時にStackTraceが一緒に表示されるようになります。この例中では"false"に設定しています。