{"id":998,"date":"2016-06-16T22:05:31","date_gmt":"2016-06-16T22:05:31","guid":{"rendered":"http:\/\/blog.paranoidprofessor.com\/?p=998"},"modified":"2016-07-14T21:04:54","modified_gmt":"2016-07-14T21:04:54","slug":"ibm-websphere-mq-manipulations-part-iii","status":"publish","type":"post","link":"https:\/\/blog.paranoidprofessor.com\/index.php\/2016\/06\/16\/ibm-websphere-mq-manipulations-part-iii\/","title":{"rendered":"IBM Websphere MQ manipulations &#8211; part III"},"content":{"rendered":"<h2>The curse of technology<\/h2>\n<p>The cool thing about technology demos is how everything just works, well unless you are demoing it to the boss.\u00a0 The equipment is usually quite new, the scope is simple enough and there are never any complications.\u00a0 The real world has a tendency to be more complicated.<\/p>\n<p>Once a system goes live, the environment tends to be more static.\u00a0 The hardware which was so good on day one doesn&#8217;t get any faster as the system utilization gets higher as the system is used by more users or departments.\u00a0 To improve performance there may be some minor upgrades of larger disks or more memory, but even these tend offset by other software upgrades.<\/p>\n<p>Depending on the size of the organization, this will continue like this until performance is unacceptable.\u00a0 Then either the computer will be replaced or the entire system will be upgraded with new hardware and software.<\/p>\n<p>Yet in a complicated environment it can be difficult to upgrade everything at once.\u00a0 This might be because of lack of time or other resources to do the job but it could also be be due to incompatibilities between systems.<\/p>\n<p>Vendors validate that their software works with certain versions of middleware, databases, operating systems just to name a few.\u00a0 It simply not feasible for them to ensure that every version of their software can work with every version of every other software package including those not yet released.<\/p>\n<p>Which brings me to the problem that I encountered.\u00a0 The system we were dealing with was pretty old and was only validated to work with MQ 6, yet most of the rest of the organization was using MQ 7.\u00a0 This wasn&#8217;t a problem at the beginning when the only goal was sending simple messages from place to place.<\/p>\n<p>When accounting wanted us to send some additional meta data along with our messages was when our problems began.\u00a0 The real problem was not because our system couldn&#8217;t support MQ 7 but because we were limited to Java 6 and the new MQ libraries were dependent on Java 7.\u00a0 This meant that we couldn&#8217;t use the classes IBM wrote to help out.<\/p>\n<h2>Old School<\/h2>\n<p>Back in the olden days when editors didn&#8217;t have syntax coloring and object oriented programming was an idea new developers simply wrote out streams of bytes, manipulated memory or cast void pointers to get around type checking. It gets the job done but is less understandable by those who follow.<\/p>\n<p>To do this task we were stuck between a rock and a hard place, most of the organization had upgraded to MQ version 7.5 but our department was stuck with an application that could only use version 6 of Java which could not use the 7.5 libraries (which were for java 7).<\/p>\n<p>The solution we had to implement was to write out the data in the same structure as IBM would have.\u00a0 This would allow us to write out the data into a MQ version 6 using its standard\u00a0libraries and read it out and the other end with version 7 libraries.<\/p>\n<p>The good news is that we don&#8217;t really need to work very hard to provide this solution.<\/p>\n<p>I am not going to describe the format of the header as the source code actually does a fairly good job of that.\u00a0 I have commented the code showing which bytes it is actually outputting.<\/p>\n<h1>MQ Version 6<\/h1>\n<h2>Putting a message with a RFH2 header<\/h2>\n<pre><code>import java.io.IOException;\r\n\r\nimport com.ibm.mq.MQC;\r\nimport com.ibm.mq.MQEnvironment;\r\nimport com.ibm.mq.MQException;\r\nimport com.ibm.mq.MQMessage;\r\nimport com.ibm.mq.MQQueue;\r\nimport com.ibm.mq.MQQueueManager;\r\n\r\npublic class OldSchool {\r\n\r\n    String mqHostName;\r\n    String mqQueueManagerName;\r\n    String mqQueueChannel;\r\n    String mqQueueName;\r\n    int mqQueuePort;\r\n\r\n    String filenametoput;\r\n    String inputpath;\r\n\r\n    String userdefdata = \"pink\";\r\n\r\n    private final int encoding = MQC.MQENC_NATIVE;\r\n    private final int codedCharSetId = 0xfffffffe; \/\/ MQC.MQCCSI_DEFAULT;\r\n    private final static String RFH2_FORMAT = \"MQHRF2  \";\r\n    private final int STRUC_LENGTH = 36;\r\n\r\n    private MQQueueManager mqQueueManager; \/\/ for QMGR object\r\n    private MQQueue queue; \/\/ for Queue object\r\n\r\n    public OldSchool() {\r\n    }\r\n    private void displayException(MQException mex, String action)\r\n    {\r\n        System.out.println(\"Error while \" + action);\r\n        System.out.println(\"QMGR Name : \" + mqQueueManagerName);\r\n        System.out.println(\"Queue Name : \" + mqQueueName);\r\n        System.out.println(\"CC   : \" + mex.completionCode);\r\n        System.out.println(\"RC   : \" + mex.reasonCode);\r\n    }\r\n\r\n\tpublic void init(String host, String managername, String channel, String queuename, int queueport)\r\n\t{\r\n\t\tmqHostName \t\t= host;\r\n\t\tmqQueueManagerName \t= managername;\r\n\t\tmqQueueChannel  \t= channel;\r\n\t\tmqQueueName    \t\t= queuename;\r\n\t\tmqQueuePort     \t= queueport;\r\n\r\n\t\t\/\/ validity checking left off.\r\n\t}\r\n\r\n    public void connect()  \r\n    { \r\n        try {\r\n            MQEnvironment.hostname = mqHostName;\r\n            MQEnvironment.channel = mqQueueChannel;\r\n            MQEnvironment.port = mqQueuePort;\r\n\r\n            mqQueueManager = new MQQueueManager(mqQueueManagerName);\r\n        } \r\n        catch (MQException mqExp) \r\n        {\r\n            displayException(mqExp,\"doing queue manager connect\");\r\n            System.exit(1);\r\n        }\r\n    }\r\n    public void disconnect()  \r\n    { \r\n        try {\r\n            mqQueueManager.disconnect();\r\n        } \r\n        catch (MQException mqExp) \r\n        {\r\n            displayException(mqExp,\"doing queue manager disconnect\");\r\n            System.exit(1);\r\n        }\r\n    }\r\n    public void open()\r\n    {\r\n        int openOption = MQC.MQOO_OUTPUT;\r\n\r\n        try {\r\n            queue = mqQueueManager.accessQueue(mqQueueName, openOption, null, null, null);\r\n        } \r\n        catch (MQException e)         \r\n        {\r\n            displayException(e,\"doing queue open\");\r\n            System.exit(1);\r\n        }\r\n    }\r\n    public void close()  \r\n    {\r\n        try {\r\n            queue.close();\r\n        } \r\n        catch (MQException mqExp) \r\n        {\r\n            displayException(mqExp,\"closing queue\");\r\n            System.exit(1);\r\n        }\r\n    }\r\n\r\n    private void putMessageWithHeader(String messageTextToSend)  \r\n    {\r\n        try {\r\n            \/\/ create message\r\n            MQMessage mqm = new MQMessage();\r\n            mqm.format = MQC.MQFMT_STRING;\r\n                        \r\n            \/\/ setup our rfh2 header, one byte a at a time\r\n\r\n            \/\/ our properties will be sent out in xml format \r\n            \/\/ oldschool\r\n            String areas = userdefdata;\r\n\r\n            while (areas.length() % 4 != 0)\r\n            {\r\n                areas = areas + \" \";\r\n            }\r\n            int  areasLen = areas.getBytes(\"UTF-8\").length;\r\n            System.out.println(\"folder areas lengths = \" + (areasLen));\r\n\r\n            int structuralLen = areasLen + STRUC_LENGTH + 4;\r\n            System.out.println(\"complete length = \" + structuralLen);\r\n\r\n            \/\/ prepare a header\r\n            mqm.seek(0);\r\n            mqm.format = RFH2_FORMAT;                \r\n            mqm.writeString(\"RFH \");                \/\/ 52 46 48 20                - header name    \r\n            mqm.writeInt(2);                        \/\/ 00 00 00 02                - version\r\n            mqm.writeInt(structuralLen);            \/\/ 00 00 00 54                - length\r\n            mqm.writeInt(encoding);                 \/\/ 00 00 01 11                - encoding\r\n            mqm.writeInt(codedCharSetId);           \/\/ FF FF FF FE                - codedcharsetid\r\n            mqm.writeString(\"        \");            \/\/ 20 20 20 20 20 20 20 20    - format\r\n            mqm.writeInt(0);                        \/\/ 00 00 00 00                - flags\r\n\r\n            \/\/ CCSID 1208 -- UTF-8\r\n            mqm.writeInt(1208);                     \/\/ 00 00 04 B8                - nameValueCodedCharSetId\r\n\r\n            \/\/ actually write out \r\n            \/\/ our folder stuff.    \r\n            mqm.writeInt(areasLen);                 \/\/ 00 00 00 2C                - how big is properties area (usr,jms,...)\r\n\r\n            \/\/ properties section here\r\n            mqm.write(areas.getBytes(\"UTF-8\"));     \r\n                                                    \/\/ 3C 75 73 72 3E 3C 63 6F   o\r\n                                                    \/\/ 6C 64 73 63 68 6F 6F 6C   ldschool\r\n                                                    \/\/ 3C 2F 63 6F 64 65 62 61   ...I.ta\r\n                                                    \/\/ 74 20 49 20 74 61 77 20   t.I.taw.\r\n                                                    \/\/ 61 20 70 75 64 64 79 20   a.puddy.\r\n                                                    \/\/ 74 61 74                  tat             \r\n\r\n            \/\/ now process our actual message\r\n\r\n            \/\/ the byte array could be contents of a file, but we \r\n            \/\/ will keep this simple.\r\n            byte[] bytearray;\r\n            bytearray = messageTextToSend.getBytes();\r\n            mqm.write(bytearray);                  \r\n\r\n            \/\/ then finish the job.\r\n            \/\/ send it out.\r\n            \/\/dumpMessage(mqm);\r\n            queue.put(mqm);\r\n\r\n            System.out.println(\"Message sent\");\r\n        } \r\n        catch (MQException mqExp) \r\n        {\r\n            displayException(mqExp,\"sending message\");\r\n            System.exit(1);        \r\n        } \r\n        catch (IOException e) \r\n        {\r\n            System.out.println(\"sending message, write byte array error\");\r\n            System.exit(1);        \r\n        }\r\n    }\r\n\r\n    public void putHeaderMessage(String args[])\r\n    {\r\n    \tinit(args[0],args[1],args[2],args[3],Integer.parseInt(args[4]));\r\n\t\tconnect();\r\n        open();\r\n        putMessageWithHeader(\"I tat I taw a puddy tat\");\r\n        close();\r\n        disconnect();\r\n    }\r\n\r\n    public static void main(String[] args) \r\n    {\r\n        OldSchool myputter;\r\n        myputter = new OldSchool();\r\n        myputter.putHeaderMessage(args);\r\n    }\r\n}\r\n<\/code><\/pre>\n<h2>Dumping message<\/h2>\n<p>Sure, I could have looked\u00a0around on the Internet to find a solution but as long as I\u00a0can produce a message using the new libraries we can dump it to ensure we can create the same structure by hand with the old libraries.<\/p>\n<pre><code>\tdump message\r\n\t\t\t\t  \r\n\t 1. 52 46 48 20 00 00 00 02   RFH.....\r\n\t 2. 00 00 00 54 00 00 01 11   ...T....\r\n\t 3. FF FF FF FE 20 20 20 20   ........\r\n\t 4. 20 20 20 20 00 00 00 00   ........\r\n\t 5. 00 00 04 B8 00 00 00 2C   .......,\r\n\t 6. 3C 75 73 72 3E 3C 63 6F   o\r\n\t 8. 6C 64 73 63 68 6F 6F 6C   ldschool\r\n\t 9. 3C 2F 63 6F 64 65 62 61   ...I.ta\r\n\t12. 74 20 49 20 74 61 77 20   t.I.taw.\r\n\t13. 61 20 70 75 64 64 79 20   a.puddy.\r\n\t14. 74 61 74                  tat \r\n<\/code><\/pre>\n<p>It is possible that the entire solution could have been done easier. \u00a0It would have been much easier if we had access to the standard MQ tools but that is a story for another time.<\/p>\n<p>The key piece of code for this task was to dump out the two different messages before putting them into the queue. \u00a0This is the code I\u00a0used.<\/p>\n<pre><code>public void dumpMessage(MQMessage msg)\r\n{\r\n\tint mLen;\r\n\tSystem.out.println(\"dump message\");\r\n\r\n\ttry {\r\n\t\tmsg.seek(0);\r\n\t\tmLen = msg.getTotalMessageLength();\r\n\t\tbyte binMessage[] = new byte[mLen];\r\n\t\tmsg.readFully(binMessage);\r\n\r\n\t\tStringBuilder sb = new StringBuilder();\r\n\t\tStringBuilder sbascii = new StringBuilder();\r\n\t\tint lineno = 0;\r\n\r\n\t\tint idx = 0;\r\n\t\tfor (idx = 0; idx &lt; mLen; idx++)\r\n\t\t{\r\n\t\t\tif (idx % 8 == 0 )\r\n\t\t\t{\r\n\t\t\t\tsb.append(\"  \" + sbascii.toString());\r\n\t\t\t\tSystem.out.println(sb.toString());\r\n\t\t\t\tsb = new StringBuilder();\r\n\t\t\t\tsbascii = new StringBuilder();\r\n\r\n\t\t\t\tlineno++;\r\n\t\t\t\tif (lineno &lt; 10) { sb.append(\" \" + lineno + \". \"); } else { sb.append(lineno + \". \"); } } sb.append(String.format(\"%02X \", binMessage[idx])); if (binMessage[idx] &gt; 32 &amp;&amp; binMessage[idx] &lt; 127)\r\n\t\t\t\tsbascii.append(String.format(\"%c\", binMessage[idx]));\r\n\t\t\telse\r\n\t\t\t\tsbascii.append(\".\");\r\n\t\t}\r\n\r\n\t\tsb.append(\"  \" + sbascii.toString() + \" \\n\");\r\n\r\n\t\tSystem.out.println(sb.toString());            \r\n\r\n\t} catch (IOException e) {\r\n\t\t\/\/ TODO Auto-generated catch block\r\n\t\te.printStackTrace();\r\n\t}\r\n}\r\n<\/code><\/pre>\n<h2 class=\"yiv1864657405MsoNormal\">Plenty -o- reference materials<\/h2>\n<p id=\"yui_3_16_0_1_1455829701924_29823\" class=\"yiv1864657405MsoNormal\"><a id=\"yui_3_16_0_1_1455829701924_29822\" href=\"https:\/\/www-01.ibm.com\/support\/knowledgecenter\/SSFKSJ_7.1.0\/com.ibm.mq.javadoc.doc\/WMQJavaClasses\/com\/ibm\/mq\/MQMessage.html\" target=\"_blank\" rel=\"nofollow\">https:\/\/www-01.ibm.com\/support\/knowledgecenter\/SSFKSJ_7.1.0\/com.ibm.mq.javadoc.doc\/WMQJavaClasses\/com\/ibm\/mq\/MQMessage.html<\/a><\/p>\n<p id=\"yui_3_16_0_1_1455829701924_29809\" class=\"yiv1864657405MsoNormal\"><span id=\"yui_3_16_0_1_1455829701924_29808\" lang=\"EN-US\"><a id=\"yui_3_16_0_1_1455829701924_29807\" href=\"http:\/\/www.ibm.com\/developerworks\/websphere\/library\/techarticles\/1001_xiao\/1001_xiao.html\" target=\"_blank\" rel=\"nofollow\">http:\/\/www.ibm.com\/developerworks\/websphere\/library\/techarticles\/1001_xiao\/1001_xiao.html<\/a><\/span><\/p>\n<div id=\"yui_3_16_0_1_1455829701924_38305\">\n<div id=\"yui_3_16_0_1_1455829701924_38304\" class=\"yiv6229478553WordSection1\">\n<p id=\"yui_3_16_0_1_1455829701924_38303\" class=\"yiv6229478553MsoNormal\"><a id=\"yui_3_16_0_1_1455829701924_38302\" href=\"http:\/\/www.redbooks.ibm.com\/Redbooks.nsf\/portals\/WebSphere?Open&amp;page=popular&amp;start=61&amp;count=20\" target=\"_blank\" rel=\"nofollow\">http:\/\/www.redbooks.ibm.com\/Redbooks.nsf\/portals\/WebSphere?Open&amp;page=popular&amp;start=61&amp;count=20<\/a><\/p>\n<p id=\"yui_3_16_0_1_1455829701924_38309\" class=\"yiv6229478553MsoNormal\"><a id=\"yui_3_16_0_1_1455829701924_38333\" href=\"http:\/\/timjansen.github.io\/jarfiller\/guide\/jms\/browsing.xhtml\" target=\"_blank\" rel=\"nofollow\">http:\/\/timjansen.github.io\/jarfiller\/guide\/jms\/browsing.xhtml<\/a><\/p>\n<\/div>\n<\/div>\n","protected":false},"excerpt":{"rendered":"<p>The curse of technology The cool thing about technology demos is how everything just works, well unless you are demoing it to the boss.\u00a0 The equipment is usually quite new, the scope is simple enough and there are never any &hellip; <a href=\"https:\/\/blog.paranoidprofessor.com\/index.php\/2016\/06\/16\/ibm-websphere-mq-manipulations-part-iii\/\">Continue reading <span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[20,3],"tags":[12,58],"_links":{"self":[{"href":"https:\/\/blog.paranoidprofessor.com\/index.php\/wp-json\/wp\/v2\/posts\/998"}],"collection":[{"href":"https:\/\/blog.paranoidprofessor.com\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blog.paranoidprofessor.com\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blog.paranoidprofessor.com\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/blog.paranoidprofessor.com\/index.php\/wp-json\/wp\/v2\/comments?post=998"}],"version-history":[{"count":2,"href":"https:\/\/blog.paranoidprofessor.com\/index.php\/wp-json\/wp\/v2\/posts\/998\/revisions"}],"predecessor-version":[{"id":1000,"href":"https:\/\/blog.paranoidprofessor.com\/index.php\/wp-json\/wp\/v2\/posts\/998\/revisions\/1000"}],"wp:attachment":[{"href":"https:\/\/blog.paranoidprofessor.com\/index.php\/wp-json\/wp\/v2\/media?parent=998"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.paranoidprofessor.com\/index.php\/wp-json\/wp\/v2\/categories?post=998"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.paranoidprofessor.com\/index.php\/wp-json\/wp\/v2\/tags?post=998"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}