是否可以在.NET WMQ API中读取JMSDeliveryMode属性?

时间:2012-08-06 16:26:57

标签: .net jms ibm-mq

我正在尝试使用.NET WMQ API使用.NET应用程序通过WebSphere MQ(WebSphere MQ Server v7)发送的JMS消息。我正在使用WebSphere MQ Client v7.5和amqmdnet.dll版本7.5.0.0。

JMSDeliveryMode RFH2文件夹中读取Dlv属性(jms属性)时有一些非常奇怪的行为。由JMS应用程序(WebSphere Application Server v7中托管的servlet)发送的属性值设置为Persistent(2),但我的.NET客户端始终读取1(表示Non_persistent)。我需要读取正确的值,因为我的.NET应用程序作为路由器/转发器工作,它必须转发正确配置的消息。

我尝试使用RFHUtils模拟JMS消息。当我将传送模式设置为1并将其发送到我的.NET客户端时,它再次读取1,但如果我还更改了MQMD中MQ消息的持久性,则它会读取0.看起来JMSDeliveryMode中的值根本没有使用和.NET客户端始终从Persistence属性读取值,但这是不正确的行为!这两个属性具有不同的正确值范围:

JMSDeliveryMode正确的值(来自jms.jar):

  • 1 - DeliveryMode.NON_PERSISTENT
  • 2 - DeliveryMode.PERSISTENT

Persistence正确的值(来自amqmdnet.dll):

  • 0 - MQC.MQPER_NOT_PERSISTENT
  • 1 - MQC.MQPER_PERSISTENT
  • 2 - MQC.MQPER_PERSISTENCE_AS_Q_DEF / MQC.MQPER_PERSISTENCE_AS_TOPIC_DEF

2 个答案:

答案 0 :(得分:0)

这是IBM的amqmdnet.dll中的错误。在用.NET Reflector反汇编库并检查负责读取JMS属性的代码(GetJmsProperty类的MQMessage私有方法)后,我发现了这个:

if (name.Equals("JMSDeliveryMode"))
{
   // Properties never contain the property with such name!
   if (this.properties.ContainsKey("JMSDeliveryMode"))
   {
      ...
   }
   return this.Persistence;  // Executes always
}

问题是properties集合从不包含任何以JMSDeliveryMode为关键字的属性。 properties集合包含格式为 RFH2Folder.RFH2PropertyName 的RFH2标头。 JMSDeliveryMode的正确属性名称为jms.Dlv!有趣的是,GetJmsHeader方法在属性集合中搜索时读取所有JMS属性,所有其他属性使用正确的RFH2名称!

当我检查反向操作时,情况更糟 - 来自SetJmsProperty类的私有方法MQMessage。设置JMSDeliveryMode包含以下代码:

else if (name.Equals("JMSDeliveryMode"))
{
    if (value is int)
    {
        int num2 = Convert.ToInt32(value);
        switch (num2)
        {
            // Non persistent JMS message creates persistent MQ message  
            case 1:
                this.Persistence = 1;
                break;
            // Invalid value for JMS delivery mode            
            case 0:
                this.Persistence = 0;
                break;
            // Great if I try to create persistent JMS message I will 
            // get MQRC_PERSISTENCE_ERROR exception!            
            default:
                base.throwNewMQException(2, 0x7ff);
                break;
        }

        queue.Enqueue(num2);
        // Correct RFH2 identifier is used
        this.properties.Add("jms.Dlv", queue);
    }
    else
    {
        base.throwNewMQException(2, 0x9a9);
    }
}

因此设置JMSDelivery模式将触发异常或设置无效持久性!这是重现问题的小测试:

[Test]
public void PutAndGetMessageWithDeliveryMode() {
    using (MQQueue queue = _queueManager.AccessQueue(TestQueue, MQC.MQOO_OUTPUT | MQC.MQOO_INPUT_AS_Q_DEF)) {

        MQMessage message = new MQMessage();
        message.SetInt4Property("JMSDeliveryMode", 2);
        message.WriteString("some string");
        message.Format = MQC.MQFMT_STRING;

        queue.Put(message); 

        MQMessage readMessage = new MQMessage();
        queue.Get(readMessage); 

        Assert.AreEqual(2, readMessage.GetInt4Property("JMSDeliveryMode"));

        queue.Close();
    }
}

答案 1 :(得分:0)

MQ .NET中的持久性值是正确的,您可以与cmqc.h头文件进行比较,因为amqmdnet和C MQI都是MQ本机API。

0 - MQC.MQPER_NOT_PERSISTENT
1 - MQC.MQPER_PERSISTENT
2 - MQC.MQPER_PERSISTENCE_AS_Q_DEF / MQC.MQPER_PERSISTENCE_AS_TOPIC_DEF

jms.jar DeliveryMode枚举定义了一个不同的值。我认为MQ JMS实现将在内部适当地处理它,并在MQMD和RFH2属性中设置正确的MQ特定值。

关于使用RFH2Util的测试。 MQMD选项卡和JMS中设置的值可能不同。您可以在JMS选项卡中将DeliveryMode设置为1,在MQMD选项卡中将Persistent Msg设置为No。放置消息时,MQMD.Persistence将显示为0,JMSDeliveryMode将显示为1.我通过在MQ Explorer中查看消息来确认此值。 MQ .NET API只是为您提供从消息中获得的内容。据我所知,RFHUtil是一个设置RFH属性的工具。它只是设置/获取RFH属性。它没有MQ JMS实现的智能。

在我看来,“JMSxxxx”属性最好由JMS实现处理,而不是像MQ .NET这样的本机实现。