カスタム 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 オプションなし)Get
MQQueue
MQOO_INPUT_AS_Q_DEF
- 受信したすべてのメッセージ ヘッダーを読み取る
MQMessage
GetPropertyNames("%")
すべてのメッセージ プロパティの名前を取得するために使用しますGetObjectProperty
すべてのプロパティの値を取得するために使用します- メッセージ形式が
MQSTR
本文を読み取るReadString
場合ReadBytes
送信者
- 作成します
MQMessage
- 受信したすべての意味のあるメッセージ ヘッダーを設定します
MQMessage
。たとえばMessageId
、ReplyToQueue
名前やその他のヘッダーはコピーされません。代わりに、新しい値または正しい値が使用されます。 MQMessage
を使用して受信したすべてのプロパティを設定します。.NETSetObjectProperty
API に一貫性がなく、返される値の型がGetObjectProperty
常に受け入れられるとは限らないため、この手順にはいくつかの魔法が含まれています。SetObjectProperty
通常は受信しますString
が、渡す必要があります。このステップは、JmsDestination および JmsReplyTo の宛先もオーバーライドします。int
long
WriteString
またはのいずれかでメッセージの本文を記述します。WriteBytes
Put
MQQueue
アクセスするメッセージMQOO_OUTPUT
(特別な put オプションなし)
RFH2 構造を手動で作成するのではなく、MQ インフラストラクチャに処理させます。だから私の質問: メッセージ駆動型 Bean によって受け入れられる .NET から有効な JMS メッセージを作成する方法は?
注: 私は IBM.XMS を使用したくありません。この決定は、XMS と WMQ の両方の長所と短所を説明する IBM ナレッジ ベースの記事のために、かなり前に行われました。JMS メッセージングと非 JMS メッセージングの両方をサポートする必要があります。