S2JMS 開発記 続 MessageEndpoint
コミットしますた.
S2JCA-ActiveMQ の activemq/bin/activemq.bat
を実行しておいて,org.seasar.jca.mi.jms.ActiveMQTest
で動作確認ができます.
量が多いので分かりにくいですが,コンソール出力を見ると複数のスレッドで受信メッセージをバッサバッサと捌いている様子が窺えるはず.
ちょっと気になったことがあって,ActiveMQ は受信メッセージの処理が一定回数以上失敗に終わる (MessageLister#onMessage(Message)
から例外がスローされる) と,そのコネクションからのメッセージ配信を中断してしまうようです.
これは特定のメッセージを何回失敗したらということではなく,コネクション単位で数えているっぽい.
自分の環境だと,連続じゃなくても通算 11 回 (たしか) 失敗するとそれ以降メッセージが来なくなります.
そうなると,その MessageEndpoint
にはもはやメッセージが届かないため,受信アプリケーションとしては全くの役立たずになってしまうということに.
そんなわけで (どんなわけで?),その状況になったら MessageEndpoint
を非アクティブ化して,新しい MessageEndpoint
をアクティブ化すべきのような気のせいがしますが,その状況になっていることを知る手段ってある?
JCA 仕様には見当たらないような...
例外を伝えず単にロールバックするだけだと,そのメッセージは 5 回ばかり再配信される (通算 6 回 MessageListener#onMessage(Message)
が呼び出される) っぽい.
この場合は何回ロールバックしてもコネクションは配信を続けてくれる模様.500 回くらいしか試してないけど.
そんなわけで (どんなわけで?),ActiveMQ に例外が伝わらないようにすればいいのかとも思ったのですが,JCA 仕様ではアプリケーションで発生した例外はリソースアダプタに渡せと書いてあるような.
ってことは,S2JMS-Container (JCA 仕様的にはアプリの一部) で例外をハンドリングすればいいのかも.
トランザクショナルなメッセージに限ると,本当のアプリケーションから例外が飛んできたら,S2JMS-Container は TransactionManager#setRollbackOnly()
を呼び出して例外を捨ててしまえばいい,みたいな (もちろんロギングくらいはする).
そうすると ActiveMQ のデフォルトでは 5 回までリトライできるよ,と.
OracleAQ なんかもロールバックされたメッセージをリトライする上限を設定できるので,こういう場合は S2JMS-Container でリトライの制御をする必要はないわけですが,そうじゃない JMS 実装のことも一応考えておくテスト.