1

最初のブロッカーを解決した後、より複雑なシナリオに移行することができ、JMS メッセージを WebSphere Application Server v7 でホストされているメッセージ駆動型 Bean に送信する .NET コンポーネントからカスタム メッセージ プロパティをラウンドトリップし、Bean が .NET コンポーネントに応答することを試みました。 . この通信は WebSphere MQ v7 を介して行われますが、.NET は WebSphere MQ Client v7.5 と amqmdnet.dll v7.5.0.0 を使用します (これは、v7 クライアントで発生した他のいくつかの問題を修正するためです: たとえば、これ)。

.NET コンポーネントから単純なブール プロパティを送信できません。

MQMessage message = new MQMessage();
message.SetBooleanProperty("TEST_BOOL", true);
queue.Put(message);

メッセージ駆動型 Bean でそのようなメッセージを受信すると、次のように失敗します。

[8/3/12 17:37:20:087 CEST] 0000003b SibMessage    W   [:] CWSJY0003W: JMSCC0110: An exception '
                       Message : com.ibm.msg.client.jms.DetailedMessageFormatException: JMSCMQ1050: The MQRFH2 header has an incorrect format. Received a message with a badly formed MQRFH2 header. Ensure that any non-JMS applications building messages with MQRFH2 headers create well-formed MQRFH2 headers.
                         Class : class com.ibm.msg.client.jms.DetailedMessageFormatException
                         Stack : sun.reflect.NativeConstructorAccessorImpl.newInstance0(NativeConstructorAccessorImpl.java:-2)
                               : sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:45)
                               : sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:39)
                               : java.lang.reflect.Constructor.newInstance(Constructor.java:515)
                               : com.ibm.msg.client.commonservices.j2se.NLSServices.createException(NLSServices.java:313)
                               : com.ibm.msg.client.commonservices.nls.NLSServices.createException(NLSServices.java:388)
                               : com.ibm.msg.client.wmq.common.internal.messages.WMQMessageBase._parseUsrFolder(WMQMessageBase.java:1984)
                               : com.ibm.msg.client.wmq.common.internal.messages.WMQReceiveMarshal.constructProviderMessageFromRFH2(WMQReceiveMarshal.java:402)
                               : com.ibm.msg.client.wmq.common.internal.messages.WMQReceiveMarshal.constructProviderMessageFromProperties(WMQReceiveMarshal.java:191)
                               : com.ibm.msg.client.wmq.common.internal.messages.WMQReceiveMarshal.createProviderMessage(WMQReceiveMarshal.java:467)
                               : com.ibm.msg.client.wmq.common.internal.messages.WMQReceiveMarshal.exportProviderMessage(WMQReceiveMarshal.java:627)
                               : com.ibm.msg.client.wmq.internal.WMQConsumerShadow.getMsg(WMQConsumerShadow.java:1318)
                               : com.ibm.msg.client.wmq.internal.WMQConsumerShadow.getMsg(WMQConsumerShadow.java:1208)
                               : com.ibm.msg.client.wmq.internal.WMQSyncConsumerShadow.receive(WMQSyncConsumerShadow.java:366)
                               : com.ibm.msg.client.wmq.internal.WMQSession.loadMessageReference(WMQSession.java:1318)
                               : com.ibm.msg.client.jms.internal.JmsSessionImpl.consume(JmsSessionImpl.java:2940)
                               : com.ibm.msg.client.jms.internal.JmsSessionImpl.run(JmsSessionImpl.java:2631)
                               : com.ibm.mq.jms.MQSession.run(MQSession.java:862)
                               : com.ibm.mq.connector.inbound.WorkImpl.run(WorkImpl.java:265)
                               : com.ibm.ejs.j2c.work.WorkProxy.run(WorkProxy.java:399)
                               : com.ibm.ws.util.ThreadPool$Worker.run(ThreadPool.java:1604)
     Caused by [1] --> Message : com.ibm.msg.client.jms.DetailedMessageFormatException: JMSCMQ0008: WebSphere MQ classes for JMS attempts to use a data type not supported by a message or attempts to read data in the wrong type. Wrong data types used to read message property types. Check that the message received and the properties to be read are of the type expected.
                         Class : class com.ibm.msg.client.jms.DetailedMessageFormatException
                         Stack : sun.reflect.NativeConstructorAccessorImpl.newInstance0(NativeConstructorAccessorImpl.java:-2)
                               : sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:45)
                               : sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:39)
                               : java.lang.reflect.Constructor.newInstance(Constructor.java:515)
                               : com.ibm.msg.client.commonservices.j2se.NLSServices.createException(NLSServices.java:313)
                               : com.ibm.msg.client.commonservices.nls.NLSServices.createException(NLSServices.java:388)
                               : com.ibm.msg.client.wmq.common.internal.messages.WMQMessageUtils.deformatTypedElement(WMQMessageUtils.java:306)
                               : com.ibm.msg.client.wmq.common.internal.messages.WMQMessageUtils.deformatElement(WMQMessageUtils.java:414)
                               : com.ibm.msg.client.wmq.common.internal.messages.WMQMessageBase._parseUsrFolder(WMQMessageBase.java:1963)
                               : com.ibm.msg.client.wmq.common.internal.messages.WMQReceiveMarshal.constructProviderMessageFromRFH2(WMQReceiveMarshal.java:402)
                               : com.ibm.msg.client.wmq.common.internal.messages.WMQReceiveMarshal.constructProviderMessageFromProperties(WMQReceiveMarshal.java:191)
                               : com.ibm.msg.client.wmq.common.internal.messages.WMQReceiveMarshal.createProviderMessage(WMQReceiveMarshal.java:467)
                               : com.ibm.msg.client.wmq.common.internal.messages.WMQReceiveMarshal.exportProviderMessage(WMQReceiveMarshal.java:627)
                               : com.ibm.msg.client.wmq.internal.WMQConsumerShadow.getMsg(WMQConsumerShadow.java:1318)
                               : com.ibm.msg.client.wmq.internal.WMQConsumerShadow.getMsg(WMQConsumerShadow.java:1208)
                               : com.ibm.msg.client.wmq.internal.WMQSyncConsumerShadow.receive(WMQSyncConsumerShadow.java:366)
                               : com.ibm.msg.client.wmq.internal.WMQSession.loadMessageReference(WMQSession.java:1318)
                               : com.ibm.msg.client.jms.internal.JmsSessionImpl.consume(JmsSessionImpl.java:2940)
                               : com.ibm.msg.client.jms.internal.JmsSessionImpl.run(JmsSessionImpl.java:2631)
                               : com.ibm.mq.jms.MQSession.run(MQSession.java:862)
                               : com.ibm.mq.connector.inbound.WorkImpl.run(WorkImpl.java:265)
                               : com.ibm.ejs.j2c.work.WorkProxy.run(WorkProxy.java:399)
                               : com.ibm.ws.util.ThreadPool$Worker.run(ThreadPool.java:1604)
' was caught while processing a message for delivery to a message driven bean.
4

3 に答える 3

1

RFHUtilsを使用して、.NET コンポーネントから送信されたメッセージを取得しました。usrRFH2 フォルダーには、次の定義が含まれています。

TEST_BOOL(dt='boolean')=True

1の代わりに値を変更し、TrueRFHUtils を使用してメッセージを送信すると、正しく処理されます。逆コンパイルされたリソース アダプター (私はJD-GUIを使用しています) も、ブール値の JMS プロパティの値のみ0を期待していることを示しました。1

static Object deformatTypedElement(int datatype, String value)
    throws JMSException
{
    Object result = null;
    switch (datatype) {
        ...
        case 1:
            if (value.equals("1")) {
                result = new Boolean(true);
            }
            else if (value.equals("0")) {
                result = new Boolean(false);
            }
            else {
                JMSException je = (JMSException)NLSServices.createException("JMSCMQ0008", null); // Line 306 - BOOM!
                throw je;
            }

            // There is also no break here but I think it is a problem of decompiler
       ...
    }
}

.NET 用の amqmdnet.dll ライブラリの逆コンパイルされたコード (私は.NET Reflectorを使用しています) は、ブール値をメッセージに渡す前に変換しないことを示しました。それは単に値を使用ToString()します:

internal class MQMarshalMessageForPut : MQBaseObject
{
   ...

   private void SetContent(RFH2Folder element, object value)
   {
       ...

       if (value is bool)
       {
           element.SetContent(value.ToString(), 1);
       }

       ...
    }
} 

しかしToStringboolタイプの戻り値TrueまたはFalse!

メッセージ駆動型 Bean から .NET アプリケーションへの応答は、文字列と値の両方でGetBoolProperty動作するように準備されているため、問題なく動作します。TrueFalse01

private bool ParseBoolean(object obj) 
{
    ...

    if ((string.Compare(strA, "true", true) == 0) || (strA == "1"))
    {
        strA = bool.TrueString;
    }
    else if ((string.Compare(strA, "false", true) == 0) || (strA == "0"))
    {
        strA = bool.FalseString;
    }


    ...
}

これは、IBM の amqmdnet.dll ライブラリーのバグだと思います。

于 2012-08-06T11:37:33.333 に答える
0

TrueBooleanとには異なる定義がありますFalse。一部の言語では、True を 1、False を 0 として表し、False を 0 として定義し、ゼロ以外 (1 と -1 を含む) を True として定義する言語もあります。Ruby のように、True を 0 と定義するものもあります。そのため、True を 1、False を 0 と明確に言うことはできません。そのため、MQ .NET と Java API はブール値をTrueそれFalse自体として設定し、受信アプリケーションはそれを言語仕様に従って解釈できます。

ただし、メッセージの受信中、MQ .NET および Java API は 1 を真として認識し、0 を偽として認識します。以上が使いやすさのポイントです。メッセージの送信中に同じことを適用することはできません。常に一貫した値を設定する必要があり、1 を設定できない場合と True を設定できない場合があります。

于 2012-08-07T04:52:46.013 に答える