1

カスタム 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。たとえばMessageIdReplyToQueue名前やその他のヘッダーはコピーされません。代わりに、新しい値または正しい値が使用されます。
  • MQMessageを使用して受信したすべてのプロパティを設定します。.NET SetObjectPropertyAPI に一貫性がなく、返される値の型がGetObjectProperty常に受け入れられるとは限らないため、この手順にはいくつかの魔法が含まれています。SetObjectProperty通常は受信しますStringが、渡す必要があります。このステップは、JmsDestination および JmsReplyTo の宛先もオーバーライドします。intlong
  • WriteStringまたはのいずれかでメッセージの本文を記述します。WriteBytes
  • PutMQQueueアクセスするメッセージMQOO_OUTPUT(特別な put オプションなし)

RFH2 構造を手動で作成するのではなく、MQ インフラストラクチャに処理させます。だから私の質問: メッセージ駆動型 Bean によって受け入れられる .NET から有効な JMS メッセージを作成する方法は?

注: 私は IBM.XMS を使用したくありません。この決定は、XMS と WMQ の両方の長所と短所を説明する IBM ナレッジ ベースの記事のために、かなり前に行われました。JMS メッセージングと非 JMS メッセージングの両方をサポートする必要があります。

4

1 に答える 1

1

WebSphere トレースを有効にし、 Java Decompilerを使用して一部の WebSphere .jar パッケージをチェックした後、エラーの原因を偶然見つけました。

_parseMcdFolderトレースは、失敗したメソッドに渡される値を示しています。

[8/3/12 12:16:00:199 CEST] 0000003a  > UOW= source=com.ibm.msg.client.wmq.internal.messages.WMQMessageBase method=_parseMcdFolder(String,String,String) (com.ibm.msg.client.wmq.internal.messages.WMQMessageBase) [:] org=IBM prod=WebSphere component=Application Server thread=[WMQJCAResourceAdapter : 0]
          Entry parm0=<mcd><Msd dt="string" >jms_text</Msd></mcd>  parm1=jms_text parm2=<null>
[8/3/12 12:16:00:199 CEST] 0000003a  3 UOW= source=com.ibm.msg.client.jms.internal.JmsSessionImpl org=IBM prod=WebSphere component=Application Server thread=[WMQJCAResourceAdapter : 0]
          (com.ibm.msg.client.jms.internal.JmsSessionImpl) [:/50d450d4] Caught exception: java.lang.NullPointerException in class: com.ibm.msg.client.jms.internal.JmsSessionImpl method: run() <exitIndex: 2>
[8/3/12 12:16:00:199 CEST] 0000003a  1 UOW= source=com.ibm.msg.client.jms.internal.JmsSessionImpl org=IBM prod=WebSphere component=Application Server thread=[WMQJCAResourceAdapter : 0]
          (com.ibm.msg.client.jms.internal.JmsSessionImpl) [:/50d450d4] Tracing exception:
java.lang.NullPointerException
    at com.ibm.msg.client.wmq.internal.messages.WMQMessageBase._parseMcdFolder(WMQMessageBase.java:445)
    at com.ibm.msg.client.wmq.internal.messages.WMQReceiveMarshal.constructProviderMessageFromRFH2(WMQReceiveMarshal.java:341)
    at com.ibm.msg.client.wmq.internal.messages.WMQReceiveMarshal.createProviderMessage(WMQReceiveMarshal.java:447)
    at com.ibm.msg.client.wmq.internal.messages.WMQReceiveMarshal.exportProviderMessage(WMQReceiveMarshal.java:607)
    at com.ibm.msg.client.wmq.internal.WMQConsumerShadow.getMsg(WMQConsumerShadow.java:1115)
    at com.ibm.msg.client.wmq.internal.WMQSyncConsumerShadow.receive(WMQSyncConsumerShadow.java:334)
    at com.ibm.msg.client.wmq.internal.WMQSession.loadMessageReference(WMQSession.java:1082)
    at com.ibm.msg.client.jms.internal.JmsSessionImpl.consume(JmsSessionImpl.java:2847)
    at com.ibm.msg.client.jms.internal.JmsSessionImpl.run(JmsSessionImpl.java:2549)
    at com.ibm.mq.jms.MQSession.run(MQSession.java:860)
    at com.ibm.mq.connector.inbound.WorkImpl.run(WorkImpl.java:172)
    at com.ibm.ejs.j2c.work.WorkProxy.run(WorkProxy.java:399)
    at com.ibm.ws.util.ThreadPool$Worker.run(ThreadPool.java:1604)

したがって、渡されるパラメーター_parseMcdFolderは次のとおりです。

parm0=<mcd><Msd dt="string" >jms_text</Msd></mcd>  parm1=jms_text parm2=<null>

に格納されている WMQ リソース アダプタ パッケージを逆コンパイルし%WAS_INSTALL%\lib\WMQ\ra\wmq.jmsra.rarてメソッドを確認しました_parseMcdFolder。驚いたことに、例外から報告された行とメソッド コードが一致しませんでした (別のメソッドがありました)。また、メソッドのコードは、渡されたパラメーターを正しく解析する必要があります。

しばらくして、WAS インストール ディレクトリ全体を確認したところ、アンパックされたリソース アダプタが 2 つ見つかりました。1 つはルートInstalledComponentsディレクトリにあり、2 つ目はInstalledComponentsサーバー プロファイルのディレクトリにありました。これらのリソース アダプタには異なるバージョンがありました。

  • グローバル: 7.0.1.4-k701-104-110104
  • プロファイル: 7.0.0.0-k700-L080820

バージョン 7.0.0.0-k700-L080820 のコードを逆コンパイルした後、実際にバグがあることがわかりました - 初期化されていないメッセージにアクセスしています:

static WMQMessage _parseMcdFolder(String s, String fbClass, String forcedMessageClass)
    throws JMSException
{
    WMQMessage newMessage = null;

    // 350+ lines of code trying to parse s and initialize newMessage
    // but no fallback so newMessage could be null after the processing

    newMessage.isNullMessage = isNullMsgFlag;  // Line 445 - BOOM!
    return newMessage;
}

このバグは、アダプターの次のバージョンで修正されましたが、この問題に関連するドキュメントが見つからなかったため、通知されませんでした。

新しいバージョンのアダプターを使用した後、問題は解決されました (実際には別の問題に移動しました)。

于 2012-08-06T10:53:20.387 に答える