【问题标题】:Is it possible to read JMSDeliveryMode property in .NET WMQ API?是否可以在 .NET WMQ API 中读取 JMSDeliveryMode 属性?
【发布时间】:2012-08-03 15:47:02
【问题描述】:

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

读取JMSDeliveryMode 属性(jms RFH2 文件夹中的Dlv 属性)时出现一些非常奇怪的行为。 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

【问题讨论】:

    标签: .net jms ibm-mq


    【解决方案1】:

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

    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 名称!

    当我检查反向操作时情况更糟 - 来自MQMessage 类的私有方法SetJmsProperty。设置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();
        }
    }
    

    【讨论】:

      【解决方案2】:

      MQ .NET 中 Persistence 的值是正确的,您可以与 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 这样的本机实现处理。

      【讨论】:

      • MQ .NET API 没有给出我在消息中得到的信息。它甚至不允许我发送正确的值。如果 MQ.NET API 是“本机”实现,它应该给我一个完全的控制权。我不明白为什么上层 (JMS) 的行为直接在传输层 (MQ) 中硬编码。这应该在某些桥接器中单独定义。
      猜你喜欢
      • 2012-07-25
      • 2013-06-24
      • 2013-02-07
      • 2022-01-01
      • 2010-11-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多