Ladislav Mrnka
Ladislav Mrnka

Reputation: 364279

Is it possible to read JMSDeliveryMode property in .NET WMQ API?

I'm trying to consume JMS messages send over WebSphere MQ (WebSphere MQ Server v7) by .NET application using .NET WMQ API. I'm using WebSphere MQ Client v7.5 and amqmdnet.dll version 7.5.0.0.

There is some very strange behavior when reading JMSDeliveryMode property (Dlv property from jms RFH2 folder). The property value send by JMS application (servlet hosted in WebSphere Application Server v7) is set to Persistent (2) but my .NET client always reads 1 (which means Non_persistent). I need to read the correct value because my .NET application works as router/forwarder and it must forward message with correct configuration.

I tried to simulate JMS messages using RFHUtils. When I set delivery mode to 1 and send it to my .NET client it again reads 1 but if I also change persistence of MQ message in MQMD it reads 0. It looks like the value in JMSDeliveryMode is not used at all and .NET client always reads value from Persistence property but it is incorrect behavior! These two properties have different ranges of correct values:

JMSDeliveryMode correct values (from jms.jar):

Persistence correct values (from amqmdnet.dll):

Upvotes: 0

Views: 2228

Answers (2)

Shashi
Shashi

Reputation: 15273

Values for Persistence in MQ .NET is correct and you can compare with cmqc.h header file as both amqmdnet and C MQI are both MQ native APIs.

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

The jms.jar DeliveryMode enumeration has defined a different value. I would imagine MQ JMS implementation would internally handle this appropriately and set correct MQ specific values in MQMD and RFH2 properties.

Regarding your test using RFH2Util. Values set in MQMD tab and JMS could be different. You can set DeliveryMode to 1 in JMS tab and Persistent Msg to No in MQMD tab. When a message is put, MQMD.Persistence will show up as 0 and JMSDeliveryMode will show up as 1. I confirmed this values by viewing message in MQ Explorer. The MQ .NET API is just giving you what it got from the message. As far as I know RFHUtil is a tool to set RFH properties. It simply sets/gets RFH properties. It does not have the intelligence of a MQ JMS implementation.

In my opinion "JMSxxxx" properties are best handled by a JMS implementation and not by a native implementation like MQ .NET.

Upvotes: 0

Ladislav Mrnka
Ladislav Mrnka

Reputation: 364279

It is again bug in IBM's amqmdnet.dll. After disassembling the library with .NET Reflector and checking the code responsible for reading JMS properties (GetJmsProperty private method of MQMessage class) I found this:

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

The problem is that properties collection never contains any property with JMSDeliveryMode as a key. properties collection contains RFH2 headers in format RFH2Folder.RFH2PropertyName. The correct property name for JMSDeliveryMode is jms.Dlv! Interestingly GetJmsHeader method reads all JMS properties and all other properties use correct RFH2 name when searching in properties collection!

The situation was even worse when I checked the reverse operation - private method SetJmsProperty from MQMessage class. Setting JMSDeliveryMode contains this code:

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);
    }
}

So setting JMSDelivery mode will either fire exception or set invalid persistence! Here is small test for reproducing the problem:

[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();
    }
}

Upvotes: 0

Related Questions