カスタム WMQ メッセージ ルーター/フォワーダーと言えるものに取り組んでいます。現時点では、MQ 経由で送信される JMS メッセージの処理に関して、非常に紛らわしい問題が発生しています。JMS を介して (MQ をトランスポートとして) Java アプリケーションから送信されたメッセージを受信できますが、JMS エンドポイントでリッスンしている Java アプリケーションにメッセージを送信できません。
テスト用のサーブレットとメッセージ駆動型 Bean があります。どちらも WebSphere Application Server 7.0 でホストされています (メッセージ転送には WebSphere MQ 7.0 が使用されています)。サーブレットは Bean と通信できますが、それらの間にフォワーダーを配置すると (メッセージを再構築して Bean に転送するフォワーダーと通信するようにサーブレットを再構成することにより)、Bean は要求を処理できません。WAS ログに次のエラーがあります。
[8/2/12 14:38:51:359 CEST] 00000031 SibMessage W [:] CWSJY0003W: JMSCC0110: An exception '
Message : java.lang.NullPointerException
Class : class java.lang.NullPointerException
Stack : com.ibm.msg.client.wmq.internal.messages.WMQMessageBase._parseMcdFolder(WMQMessageBase.java:445)
: com.ibm.msg.client.wmq.internal.messages.WMQReceiveMarshal.constructProviderMessageFromRFH2(WMQReceiveMarshal.java:341)
: com.ibm.msg.client.wmq.internal.messages.WMQReceiveMarshal.createProviderMessage(WMQReceiveMarshal.java:447)
: com.ibm.msg.client.wmq.internal.messages.WMQReceiveMarshal.exportProviderMessage(WMQReceiveMarshal.java:607)
: com.ibm.msg.client.wmq.internal.WMQConsumerShadow.getMsg(WMQConsumerShadow.java:1115)
: com.ibm.msg.client.wmq.internal.WMQSyncConsumerShadow.receive(WMQSyncConsumerShadow.java:334)
: com.ibm.msg.client.wmq.internal.WMQSession.loadMessageReference(WMQSession.java:1082)
: com.ibm.msg.client.jms.internal.JmsSessionImpl.consume(JmsSessionImpl.java:2847)
: com.ibm.msg.client.jms.internal.JmsSessionImpl.run(JmsSessionImpl.java:2549)
: com.ibm.mq.jms.MQSession.run(MQSession.java:860)
: com.ibm.mq.connector.inbound.WorkImpl.run(WorkImpl.java:172)
: com.ibm.ejs.j2c.work.WorkProxy.run(WorkProxy.java:399)
: com.ibm.ws.util.ThreadPool$Worker.run(ThreadPool.java:1604)
[8/2/12 14:38:51:781 CEST] 00000031 SibMessage W [:] CWSJY0003W: MQJCA4004: Message delivery to an MDB 'XXX' failed with exception: 'null'
このエラーの後、メッセージ エンドポイントは自動的に一時停止されます。
RFHUtils を使用して、JMS とアプリの両方から送信されたメッセージを取得し、それらを比較しました。UI に実際の違いはありません (配信モードが異なることを除いて、それは別の話です) が、メッセージをファイルに保存して比較すると、この違いが見られました (最初の RFH2 フォルダーのみ):
JMS で直接送信:
<mcd><Msd>jms_text</Msd></mcd>
アプリで送信:
<mcd><Msd dt="string" >jms_text</Msd></mcd>
RFH2 のすべての要素には型も含まれます。フォルダーの要素jmsの順序は異なりますが、例外によると、問題はフォルダーに直接あるはずmcdです。問題をより適切に診断する方法がわかりません。JMS のトレースを構成しようとしましたが、WAS でそれを行う方法がわかりません (火曜日に初めて WAS を使用しました)。標準 MQ トレースでは、それ以上の情報は提供されません。
私の .NET コード (MQ Client 7.5 を使用する WMQ API - amqmdnet.dll 7.5.0.0) は非常に複雑ですが、通常は次のようになります。
レシーバー
- アクセス時に標準呼び出しで
MQMessageメッセージを受信(特別な get オプションなし)GetMQQueueMQOO_INPUT_AS_Q_DEF - 受信したすべてのメッセージ ヘッダーを読み取る
MQMessage GetPropertyNames("%")すべてのメッセージ プロパティの名前を取得するために使用しますGetObjectPropertyすべてのプロパティの値を取得するために使用します- メッセージ形式が
MQSTR本文を読み取るReadString場合ReadBytes
送信者
- 作成します
MQMessage - 受信したすべての意味のあるメッセージ ヘッダーを設定します
MQMessage。たとえばMessageId、ReplyToQueue名前やその他のヘッダーはコピーされません。代わりに、新しい値または正しい値が使用されます。 MQMessageを使用して受信したすべてのプロパティを設定します。.NETSetObjectPropertyAPI に一貫性がなく、返される値の型がGetObjectProperty常に受け入れられるとは限らないため、この手順にはいくつかの魔法が含まれています。SetObjectProperty通常は受信しますStringが、渡す必要があります。このステップは、JmsDestination および JmsReplyTo の宛先もオーバーライドします。intlongWriteStringまたはのいずれかでメッセージの本文を記述します。WriteBytesPutMQQueueアクセスするメッセージMQOO_OUTPUT(特別な put オプションなし)
RFH2 構造を手動で作成するのではなく、MQ インフラストラクチャに処理させます。だから私の質問: メッセージ駆動型 Bean によって受け入れられる .NET から有効な JMS メッセージを作成する方法は?
注: 私は IBM.XMS を使用したくありません。この決定は、XMS と WMQ の両方の長所と短所を説明する IBM ナレッジ ベースの記事のために、かなり前に行われました。JMS メッセージングと非 JMS メッセージングの両方をサポートする必要があります。