Ah, the joys of writing applications for IBM MQ and inevitable customer support that goes with it. 🙂
Late last week, a customer contacted me with an issue with MQ Visual Edit (MQVE) saying after adding Named Properties (i.e. mcd.Msd, etc.) to a regular message which should turn it into a JMS message, they could no longer edit the message.
In MQVE, the user has ‘Show message properties as Named Properties’ set rather than ‘Show message properties as an MQRFH2 structure in message body’ under ‘MQ General’ settings for Preferences.
I followed their description and was able to reproduce it. Near the bottom of the MQVE logfile, I found the following:
np.getName()=JMSPriority MQJE001: Completion Code '2', Reason '2471'. np.getName()=JMSDestination MQJE001: Completion Code '2', Reason '2471'.
Reason Code of 2471 is MQRC_PROPERTY_NOT_AVAILABLE.
The error message was only written to the logfile because the exception happened in the ‘model’ code of the standard Model-View-Controller design pattern.
I know I tested this feature several years ago when I was beta testing MQVE version 2, I started to wonder what has changed. Of course, MQVE is now built against a different release of IBM MQ (a light slowly starts to brighten over my head).
MQVE is a Java (non-JMS) application but I treat my Java code just like my C code. I purchased and use Excelsior Jet to create native applications from my Java code. I have makefiles that do builds of my code using Excelsior Jet’s compiler which turns MQVE into a native executable. I do this for Windows, Linux and macOS (Mac OS X). I’ve upgraded MQ (and applied FixPacks) since my original beta testing.
So, why was MQVE getting Reason Code of 2471 for the Named Properties ‘JMSPriority’ and ‘JMSDestination’? A quick Google search took me to the MQ Knowledge Center’s Property name restrictions page. There are 15 Named Properties on that page that are restricted and of course, ‘JMSPriority’ and ‘JMSDestination’ are on the list. I don’t understand why the MQ Library would use a Named Property that the application could not reuse – more on this later.
I have many releases (not all) of MQ Java JAR files for compatibility testing. Since, my testing was years ago, I would have been testing against some MQ version of either v7.1 or v7.5. No matter what release of MQ I tried, MQVE always received ‘JMSPriority’ and ‘JMSDestination’ Named Properties. I started to bang my head against the wall!!! I know I tested JMS messages but I cannot recreate my tests. Ahhhhhh!
And to make matters worst, with MQ v7.1 and MQ v7.5 JAR files, now I was getting another exception: Reason Code of 6114 which is MQRC_INSUFFICIENT_DATA. My day was just getting better and better, NOT!!!
From the MQ Knowledge Center:
There is insufficient data after the data pointer to accommodate the request. This Reason Code occurs in the IBM MQ C++ environment.
MQVE is a Java application not C++ and it is connecting in ‘client mode’ to the remote queue manager, so there is NO native MQ code being executed locally.
Oh, the other weird part of the Reason Code of 6114 was that there was no exception being thrown by MQ. The MQ library was simply writing ‘MQJE001: Completion Code ‘2’, Reason ‘6114’.’ to stderr (standard error).
Anther weird thing I noticed was that the message’s Encoding was set to 1 (rather than 273) and the CCSID was set to 1208 (rather than 819).
Reason Code of 6114 only happened when I used MQ JAR files from either v7.1 and/or v7.5 (MQ v8 & v9 was fine). I figured I better fix the original error and maybe the rest would go away (spoiler alert – it didn’t).
I have no clue why the MQ Library has a need to use restricted name properties for a non-JMS Java application. I mean, I understand why IBM is restricting applications from using ‘JMS****’ as a Named Property and that is fine with me. But why in the world, would the MQ Library pass ‘JMSPriority’ and ‘JMSDestination’ Named Properties to a non-JMS Java application. It is just odd, really, really odd. The MQ Library could have simply used ‘jms.Pri’ and ‘jms.Dst’ rather than ‘JMSPriority’ and ‘JMSDestination’.
So, I created a simple lookup tables for the reserved property names (aka Named Properties) and their synonyms as per the web page from the MQ Knowledge Center.
In case anyone else ever has a need to update a message (ok, there is no such thing as update but rather MQGET, transfer data to new MQMessage then MQPUT), here is some simple code that you can put in your application’s Constants.java file (or whatever you call your constants file).
/** * Keys must be in sorted order. */ private static final String JMSRestrictedProperties[] = { "JMSCorrelationID", "JMSDeliveryMode", "JMSDestination", "JMSExpiration", "JMSMessageID", "JMSPriority", "JMSRedelivered", "JMSReplyTo", "JMSTimestamp", "JMSType", "JMSXAppID", "JMSXDeliveryCount", "JMSXGroupID", "JMSXGroupSeq", "JMSXUserID", }; private static final String JMSSynonyms[] = { "jms.Cid", "jms.Dlv", "jms.Dst", "jms.Exp", "Root.MQMD.MsgId", "jms.Pri", "Root.MQMD.BackoutCount", "jms.Rto", "jms.Tms", "mcd.Type", "Root.MQMD.PutApplName", "Root.MQMD.BackoutCount", "jms.Gid", "jms.Seq", "Root.MQMD.UserIdentifier", }; /** * Get the JMS synonym for the JMS Restricted Property * * @param key * @return synonym */ public static String getJMSSynonym(String key) { String synonym = null; int x = Arrays.binarySearch(JMSRestrictedProperties, key); if (x >= 0) synonym = JMSSynonyms[x]; return synonym; }
So, if you put the above code in your Constants.java file then to transfer the Named Properties from an old MQMessage to a new MQMessage then you would do:
MQMessage newMsg = new MQMessage(); try { Enumeration<String> props = oldMsg.getPropertyNames("%"); if (props != null) { String propName = null; String synonymName = null; while (props.hasMoreElements()) { propName = props.nextElement(); try { synonymName = Constants.getJMSSynonym(propName); if (synonymName != null) newMsg.setObjectProperty(synonymName, oldMsg.getObjectProperty(propName)); else newMsg.setObjectProperty(propName, oldMsg.getObjectProperty(propName)); } catch (MQException e) { System.err.println(e.getLocalizedMessage()); } } } } catch (MQException e) { System.err.println(e.getLocalizedMessage()); }
So, after updating the code in MQVE, the original error was fixed and everything was fine when I tested MQVE against MQ Java JAR files from V8 and V9 but I still received the Reason Code of 6114 (including incorrect Encoding & CCSID values) when I did the tests against MQ Java JAR files for V7.1 and V7.5.
The only conclusion that I can draw is that since MQVE (non-JMS) Java application is explicitly creating a JMS message by setting the Named Property values for ‘mcd.Msd’, ‘jms.Pri’ (aka ‘JMSPriority’) and ‘jms.Dst’ (aka ‘JMSDestination’) that there is some bug in the MQ Java JAR files for V7.1 and V7.5 that was fixed in V8 because MQ V8 and V9 Java JAR files do not produce this issue.
Finally, MQ V7.1 and V7.5 are no longer supported by IBM, therefore, there is no point in complaining and opening a PMR. Food for thought, if you are using MQ V7.1 or V7.5 with a non-JMS Java application that is explicitly creating a JMS message.
And the funniest part is that after MQVE updates a JMS message using the JMS Synonyms, when the MQVE display is refreshed, the JMS messages are again using the restricted JMS Named Properties. 🙂
Regards,
Roger Lacroix
Capitalware Inc.
3 Responses to IBM MQ JMS Message Named Property Issues