この質問は、私が最もよく知っている Websphere MQ (WMQ) を使用する場合の Websphere Application Server (WAS) に主に焦点を当てています。ただし、私が話していることはすべて、より一般的にすべての Java EE アプリケーション サーバーに当てはまると思います。なぜなら、私は Java 標準インターフェースに固執しているためです。標準に関連する説明を希望しますが、WAS/WMQ に固有の回答には非常に興奮しています。
JMS 1.1 は、JMS がアプリケーション サーバーとインターフェースをとるためのメカニズムを定義します。大まかなプロセスは、キューまたはトピックを監視するために、ある時点で ConnectionConsumer が作成されることです。メッセージが表示されると、JMS 実装は ServerSessionPool から ServerSession オブジェクトを取得し、そのメッセージを ServerSession に関連付けられた Session にロードしてから、ServerSession オブジェクトで start() を呼び出します。次に、ServerSession は、アプリケーション サーバー スレッドで MDB によって処理されるようにメッセージをスケジュールする役割を果たします。MDB は onMessage() メソッドの一部としてメッセージを取得し、必要な処理を実行できます。
MDB が、受信したメッセージに応答して別のメッセージを送信することを決定するまでは、これで問題ありません。これを行うために、MDB は ConnectionFactory オブジェクトをルックアップまたは挿入し、Connection、Session、MessageProducer の順に取得し、最後にメッセージを送信する必要があります。これはすべて非常に無駄に思えます。MDB へのメッセージ配信の一部として、Connection オブジェクトと Session オブジェクトがすでに作成されています。MDB が何らかの方法でそのセッションにアクセスできる場合、余分な作業をすべて行う必要がなくなり、余分な接続をすべて作成する必要がなくなります。その余分な作業がコストとして発生します。要求メッセージに応答メッセージを送信するだけで、MDB は 2 つの接続と 2 つのセッション (メッセージを取得して応答を送信するために 1 つずつ) を使用する必要があります。グローバルトランザクションを使用する場合、これにより、アプリケーション サーバーはトランザクションを 2 フェーズ コミット トランザクションとして処理することになると思います (すべてではないにしても、少なくとも一部のアプリケーション サーバーは、1 フェーズ コミットとして処理することにより、単一のリソースのみを含むグローバル トランザクションを最適化できます)。 . トランザクションを 2 フェーズ トランザクションにすると、メッセージ処理のオーバーヘッドが大幅に増加し、あらゆる種類の新しい複雑さも導入されます (インダウト トランザクションは最大のトランザクションの 1 つです)。
JMS 1.1 仕様には次のように記されています。 MDB は、最初のメッセージを配信したセッションを使用して応答も送信します。ただし、この Session オブジェクトを MDB から標準的な方法で取得するメカニズムについては知りません。また、非標準的な方法でそれを取得するメカニズムも知りません。これに関する質問やブログ投稿がどこにも見つかりません。
では、問題は次のとおりです。JMS API は非常に複雑ですが、MDB が元のメッセージを供給したセッションを使用して、アクセスできる場合に応答を送信することを困難にするようなものは見当たりません。MDB がこの Session オブジェクトを使用できない理由はありますか? セッションにアクセスするための標準準拠の方法はありますか? 非標準に準拠した方法はありますか? アプリケーション サーバー/JMS 実装は、単一の JMS キュー マネージャー上の 2 つの接続での操作を含むグローバル トランザクションを 1 フェーズ コミット トランザクションに最適化するのが賢明ですか (標準に関する私の調査と理解では、これは不可能であることが示されているようです)。