XMS.Net 2.1.0.0/1 CWSMQ0282E

2019-07-07 09:28发布

问题:

We're using XMS.Net to connect to a WebSphere MQ server V7; this has always worked fine with a V6 server but since the "other party" has upgraded to V7 we expierienced some trouble. Most of it has been fixed but now I've stumbled upon an error that I can't explain, nor find anything about:

CWSMQ0282E: A null value has been used for argument BUFFER = <> NULL within method ImportMQMDMesageBuffer(WmqSession, WmqDestination, MQMD,byte[],int,int).
The preceding method detected an invalid  null argument.
If necessary, recode the application to avoid the error condition.
Stacktrace:    at IBM.XMS.Client.WMQ.WmqReceiveMarshal.ImportMQMDMesageBuffer(MQMessageDescriptor mqmd, Byte[] buffer, Int32 dataStart, Int32 dataEnd)
   at IBM.XMS.Client.WMQ.WmqAsyncConsumerShadow.Consumer(Phconn hconn, MQMessageDescriptor mqmd, MQGetMessageOptions mqgmo, Byte[] pBuffer, MQCBC mqcbc)
   at IBM.WMQ.Nmqi.UnmanagedNmqiMQ.NmqiConsumerMethodUM(Int32 hconn, IntPtr structMqmd, IntPtr structMqgmo, IntPtr buffer, IntPtr structMqcbc)

The only thing I think I know about the cause of this error is that we sent a message and I'm expecting the CoA and CoD messages; I'm expecting these to be in the queue and when I shut down my consumer listening for these messages the rest works fine.

I have absolutely no idea what is going on...

EDIT

This is the minimum testcase:

using System;
using System.Configuration;
using System.Text;
using IBM.XMS;

namespace TestApp
{
    class Program
    {
        static void Main(string[] args)
        {
            //Setup unhandled exception "logging"
            AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(CurrentDomain_UnhandledException);

            //Change this to your own needs!
            string QueueManager = "CONTOSO";
            string Channel = "MYCOMPANY.CONTOSO.TCP";
            string Queue = "MYCOMPANY.REPORTQ";
            string HostIP = "192.168.1.29"
            int Port = 1416;

            //Create connection
            var factoryfactory = XMSFactoryFactory.GetInstance(XMSC.CT_WMQ);
            var connectionfactory = factoryfactory.CreateConnectionFactory();

            connectionfactory.SetStringProperty(XMSC.WMQ_QUEUE_MANAGER, QueueManager);
            connectionfactory.SetStringProperty(XMSC.WMQ_HOST_NAME, HostIP);
            connectionfactory.SetIntProperty(XMSC.WMQ_PORT, Port);
            connectionfactory.SetStringProperty(XMSC.WMQ_CHANNEL, Channel);
            connectionfactory.SetIntProperty(XMSC.WMQ_BROKER_VERSION, XMSC.WMQ_BROKER_V2);
            connectionfactory.SetIntProperty(XMSC.WMQ_CONNECTION_MODE, XMSC.WMQ_CM_CLIENT_UNMANAGED);

            var connection = connectionfactory.CreateConnection();
            connection.ExceptionListener = new ExceptionListener(OnXMSExceptionReceived);

            //Create session
            var session = connection.CreateSession(false, AcknowledgeMode.ClientAcknowledge);

            //Create consumer
            var queue = session.CreateQueue(string.Format("queue://{0}/{1}", QueueManager, Queue));
            queue.SetIntProperty(XMSC.WMQ_TARGET_CLIENT, XMSC.WMQ_TARGET_DEST_MQ);  //Prevent automatic RFH (or JMS) headers in messages...
            var consumer = session.CreateConsumer(queue);
            consumer.MessageListener = new MessageListener(OnMessageReceived);  //Messages received will be handled by OnMessageReceived

            //Start the connection (which starts the consumer to listen etc.)
            Console.WriteLine("Starting");
            connection.Start();
            Console.WriteLine("Started; press any key to stop");

            //Now we wait...
            Console.ReadKey();

            //Tear down the connection
            Console.WriteLine("Stopping");
            connection.Stop();
            Console.WriteLine("Stopped; press any key to end application");

            //Keep the console around
            Console.ReadKey();
        }

        private static void OnMessageReceived(IMessage message)
        {
            Console.WriteLine("Message received");
            if (message is IBytesMessage)
            {
                var bytesmsg = (IBytesMessage)message;
                var data = new byte[bytesmsg.BodyLength];
                Console.WriteLine(Encoding.UTF8.GetString(data));
            }
            else
            {
                //The message is not an IBytesMessage, check to see if it is a Feedback-type message
                if (message.PropertyExists(XMSC.JMS_IBM_FEEDBACK))
                {
                    //Figure out which type of feedback message this is
                    int feedback = message.GetIntProperty(XMSC.JMS_IBM_FEEDBACK);
                    switch (feedback)
                    {
                        case MQC.MQFB_COA:
                            Console.WriteLine("COA received");
                            break;
                        case MQC.MQFB_COD:
                            Console.WriteLine("COD received");
                            break;
                        default:
                            //Unknown feedback type
                            Console.WriteLine("Unknown feedback");
                            break;
                    }
                }
                else
                {
                    //The message is not a feedback message; we don't know what this is so it's unexpected.
                    Console.WriteLine("Unexpected message received");
                }
            }

            Console.WriteLine("Acknowledging");
            message.Acknowledge();
            Console.WriteLine("Acknowledged");
        }

        private static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
        {
            //Uh oh
            Console.WriteLine("*** UnhandledException ***");
            Console.WriteLine((e.ExceptionObject as Exception).Message);
            Console.WriteLine("******************************");
        }

        private static void OnXMSExceptionReceived(Exception ex)
        {
            //Uh oh
            Console.WriteLine("*** OnXMSExceptionReceived ***");
            Console.WriteLine(ex.Message);
            Console.WriteLine("******************************");
        }
    }
}

Create a new (console)project, add a reference to IBM.XMS.dll (C:\Program Files (x86)\IBM\WebSphere MQ\Tools\Lib\IBM.XMS.dll) and run the project. Put any message in the report queue and see what happens.

When connected to a V6 server everything is fine, V7 results in the exception being thrown.

Also we tried updating to 2.1.0.1 but to no avail...

EDIT

Here's what I'm seeing:

This is my trace log (Sorry, can't add it here since my message will be >30000 chars long) and here is an even more detailed log (traceSpecification "all" instead of "debug").

I also tried switching the (test)application to .Net V2.0.50727.5456 but that doesn't help either.

EDIT

I seem to have narrowed it down to "empty" CoA's and CoD's; when messages are sent with the MQRO_COA_WITH_DATA or MQRO_COA_WITH_FULL_DATA (same for CoD) as opposed to MQRO_COA then the CWSMQ0282E error doesn't occur. So XMS.Net seems to crash on empty bodies for CoA's and CoD's. I need to confirm some things to ensure it's not caused by other stuff in my project interfering but I'm quite sure this is the cause.

回答1:

The exception appears to be because the received message does not have message body. If the message received is because of either MQRO_COD or MQRC_COA option (set when the original message was sent) would not have any message body. When XMS tries to process messages without any body, it's getting into trouble.

I am puzzled as to how this was working when using MQ v6. You may want to check if the application that's sending the original message has been changed off late.

Also for XMS to process any message, the incoming message must contain required JMS headers. MQRO_COD/MQRO_COA are automatically generated by the queue manager and will not contain JMS headers.

Few other suggestions on the code snippet above:

1) An instance of IPEndpoint is not really required. You can simply set hostname or IP address as a string and port number as integer.

2) XMSC.RTT_BROKER_PING_INTERVAL need not be set when connecting WMQ.

3) Since you have usedAcknowledgeMode.AutoAcknowledgewhile creating a session, no need to call message.Acknowledge() in OnMessageReceivedmethod.



回答2:

As far as I can determine this exception, indeed, occurs on "empty" CoA's en CoD's. When messages are sent with the MQRO_COA_WITH_DATA / MQRO_COD_WITH_DATA (or even bulkier MQRO_COA_WITH_FULL_DATA / MQRO_COD_WITH_FULL_DATA) the exception doesn't occur. We will file a "PMR" with IBM to confirm.



标签: c# .net ibm-mq