A Tip for Handling Java/MQ Internal Message Class

Here’s an interesting head-scratcher. I was writing some Java code to handle an MQ message and in this particular case, it was an MQRFH2 message. The code below was working fine until I decided to dump (output) the message in hexadecimal.

int openOptions = CMQC.MQOO_INQUIRE + CMQC.MQOO_FAIL_IF_QUIESCING;
MQGetMessageOptions gmo = new MQGetMessageOptions();
gmo.options = CMQC.MQGMO_NO_WAIT + CMQC.MQGMO_FAIL_IF_QUIESCING;
MQQueueManager _qMgr = null;
MQQueue queue = null;
MQMessage receiveMsg = null;
MQRFH2 rfh2;
byte[] b;
boolean getMore = true;

try
{
   _qMgr = new MQQueueManager(qManager);
   queue = _qMgr.accessQueue(inputQName, openOptions);

   while(getMore)
   {
      receiveMsg = new MQMessage();
      try
      {
         queue.get(receiveMsg, gmo);

         printMsgHex(receiveMsg);

         if (CMQC.MQFMT_RF_HEADER_2.equals(receiveMsg.format))
         {
            rfh2 = new MQRFH2(receiveMsg);
         }

         b = new byte[receiveMsg.getDataLength()];
         receiveMsg.readFully(b);
         System.out.println("Message data-> " + new String(b));
      }
      catch (com.ibm.mq.MQException e)
      {
         System.err.println("CC=" +e.completionCode + " : RC=" + e.reasonCode);
         getMore = false;
      }
      catch (java.io.IOException ioex)
      {
         System.err.println("ioex=" +ioex);
         getMore = false;
      }
      catch (MQDataException e)
      {
         System.err.println("CC=" +e.completionCode + " : RC=" + e.reasonCode);
         getMore = false;
      }
   }
}
catch (com.ibm.mq.MQException mqex)
{
   System.err.println("CC=" +mqex.completionCode + " : RC=" + mqex.reasonCode);
}
finally
{
   try
   {
      if (queue != null)
         queue.close();
   }
   catch (com.ibm.mq.MQException mqex2)
   {
      System.err.println("CC=" +mqex2.completionCode + " : RC=" + mqex2.reasonCode);
   }
   finally
   {
      try
      {
         if (_qMgr != null)
            _qMgr.disconnect();
      }
      catch (com.ibm.mq.MQException mqex3)
      {
         System.err.println("CC=" +mqex3.completionCode + " : RC=" + mqex3.reasonCode);
      }
   }
}

The printMsgHex() method is a simple method to retrieve the message and output.

byte[] b = new byte[msg.getMessageLength()];
msg.readFully(b);
etc...

When I would run the code, I would get the following error:

CC=2 : RC=6114

The MQ Knowledge Center says the following:

6114 (X'17E2') MQRC_INSUFFICIENT_DATA

Explanation:
There is insufficient data after the data pointer to accommodate the request. This reason code occur s in the WebSphere MQ C++ environment.

Completion Code:
MQCC_FAILED

I scratched my head and said WTF. I’m coding in Java but it is giving me a C++ error message. I commented out the printMsgHex() method and the code would work. I have used the printMsgHex() method for years. I looked at the code and nothing stood out. The only thing different about this code and the other code was the use of the MQRFH2 class.

I sat and stared at the code (we all know that works) and I could not see anything wrong with the code. As I sat scratching my head, I started thinking about the MQMessage class and it occurred to me that IBM implemented it like RandomAccessFile class. Then the light went on. I wondered if the MQRFH2 class reset the cursor position. So I added the following line before the call to the MQRFH2 class and bingo, everything started to work as expected.

receiveMsg.seek(0);

So, the bottom-line is if your code is going to mess around with the message then before using an internal message header class like MQRFH, MQRFH2, MQCIH, MQDEAD, MQIIH or MQXMIT, make sure you update the message’s cursor position to the correct location before passing the message to the class.

if (CMQC.MQFMT_RF_HEADER_2.equals(receiveMsg.format))
{
   receiveMsg.seek(0);
   rfh2 = new MQRFH2(receiveMsg);
}

Regards,
Roger Lacroix
Capitalware Inc.

This entry was posted in IBM i (OS/400), IBM MQ, Java, Linux, macOS (Mac OS X), Programming, Unix, Windows.

Comments are closed.