urlopen.open() formats for IBM MQ messages

The urlopen.open() API can send and receive IBM® MQ messages within a GatewayScript action either dynamically or statically. You can use a URL dynamically created by various properties that are defined in the options parameter of the urlopen.open() API specific to IBM MQ protocols. You can also use a fully specified URL that can be defined in the options parameter of the urlopen.open() API or the nonoptions specification.

Syntax

var urlopen = require('urlopen');
var options =
{
  target:URL,
  data:message,
  headers:headers, 
  agent:agent,
  parameter1:value1,
  parameter2:value2,
  :
  parameterN: valueN};
var mqHeader = { "MQMD" : {
                    "Version":{$,"1"},
                    "Format":{$,"MQSTR"}
               }};
urlopen.open(options,callback);
var urlopen = require('urlopen');
urlopen.open(URL,callback);

Parameters

headers
The headers identifies one or more header_name properties (such as MQMD) and an associated header value, which contains a set of header_fields related to the specified header. The header can be specified as a JSON object or as an XML string.
URL
The name of the IBM MQ URL for this urlopen call. The protocol can be dpmq, idgmq, or mq. If targetURL is specified as a JSON property, the URL can be complete or partial. Parameter properties in the JSON object provide more specifications.
agent
A UserAgent object that can initiate a request for a local service to establish a connection to the specified target server.
options
The properties to specify IBM MQ behavior. The properties for GatewayScript are the same as correspondent attributes of the dp:url-open extension element, which includes static and dynamic attributes for an IBM MQ queue manager. The list of properties is defined in the documentation for the dp:url-open IBM MQ extension element.
callback
The asynchronous function to call after the urlopen.open() connects, sends the data to the target, and the response header is parsed. The callback is in the function(error,response){} form.

Guidelines

  • The IBM MQ disconnection is based on the cache timeout property of the queue manager.
  • In GatewayScript, the options parameter takes the form of a JSON object that specifies a keyword and a value (parameter: value). The properties in options are not case-sensitive. In XSLT, the properties in options take the form of parameters assigned values (parameter=value). For some properties contained in options, any value for the property defines its behavior. To not use this behavior, do not include this property. For more information, see the dp:url-open() IBM MQ extension element topic.
  • The nonoptions form is provided for consistency with other urlopen.open protocols. However, it has limited usefulness because of the default MQMD header and an inability to specify message content.
  • GatewayScript uses the camel case name format for attributes and parameters. The parameters are for static and dynamic IBM MQ URLs. The attributes specify queue manager connection properties for dynamic IBM MQ URLs. For a list and description of these parameters, see the url-open documentation.
    Attributes
    userName, channelName, channelTimeout, channelLimit, size, mqcspUserId, mqcspPassword.
    Parameters
    requestQueue, replyQueue, timeOut, transactional, sync, gmo, pmo, parseHeaders, setReplyTo, asyncPut, browse, contentTypeHeader, contentTypeXPath, parseProperties, publishTopicString, selector, subscribeTopicString, subscriptionName.
  • If the MQMD header is not defined in the options.headers, then a default MQMD header is used. The MQMD default has a MsgType field of 8. This usage implies that a datagram is used and no reply is expected.
  • The options parameter can be specified either individually or on the target URL. For example, the following options definitions are equivalent.
    • options = { target: 'idgmq://' + session.parameters.qm + '/?',
         requestQueue: session.parameters.requestQAlwaysReply,
           replyQueue: session.parameters.replyQ,
        transactional: true,
                 sync: true,
              timeOut: 10000,
              headers: { ... },
                 data: putData };
    • 
      options = { target: 'idgmq://' + session.parameters.qm + '/?RequestQueue=' 
          + session.parameters.requestQAlwaysReply + ';ReplyQueue=' + session.parameters.replyQ 
          + ';Transactional=true;Sync=true;TimeOut=10000',
        headers: { ... },
          data: putData };

    Specifying a property both individually and on the target URL results in an exception.

  • Status codes that are returned by IBM MQ.
    0
    Successful return.
    2xxx
    Error return.

Guidelines specific to IBM MQ headers

  • The IBM MQ protocol headers for a transaction must be read or manipulated like other service-specific protocol headers. A require('header-metadata') statement is needed for access to the headers. You must have a require statement specifically in two cases.
    • For messages that are read by the IBM MQ handler.
    • For messages where the request rule routing destination is an IBM MQ URL.

    Headers for a urlopen.open() statement are specified within an options JSON object and they do not require the header-metadata statement.

  • No nonoptions format for setting IBM MQ headers.
  • IBM MQ headers that you specify must confirm for the structure of the header that is being addressed. Some headers are more complicated to specify than others. For example, the MQMD header supports the specification of various fields.
    var mqmd = { "MQMD": {
              "StructId": {"$":"MD"},
               "Version": {"$":"1"},
                "Report": {"$":"0"},
               "MsgType": {"$":"8"},
                "Expiry": {"$":"-1"},
              "Feedback": {"$":"0"},
              "Encoding": {"$":"546"},
        "CodedCharSetId": {"$":"819"},
                "Format": {"$":"MQSTR"},
                 "MsgId": {"$":"414d5120514d5f4a494d5f3130303530011cdf47020a0020"},
              "CorrelId": {"$":"000000000000000000000000000000000000000000000000"},
          "BackoutCount": {"$":"0"},
              "ReplyToQ": {"$":""},
           "ReplyToQMgr": {"$":"QM1"},
        "UserIdentifier": {"$":"mqm"},
       "AccountingToken": {"$":"0431303031000000000000000000000000000000000000000000000000000006"},
      "ApplIdentityData": {"$":""},
           "PutApplType": {"$":"6"},
           "PutApplName": {"$":"putfile"},
        "ApplOriginData": {"$":""} }
    };
    
    var mqHeader = { "MQMD" : mqmd };

    More complicated headers (such as the MQRFH and MQRFH2 headers) require more structure. For example, the MQRFH header requires that the NameValueString to be a JSON object that contains a name value list.

    var mqrfh = {"MQRFH": {
            "Format":{"$":"MQSTR"},
            "NameValueString": { 
                "NameValue": [ // The NameValue uses brackets to represent an array
                    { 
                      "Name":{"$":"name1"},
                      "Value":{"$":"value1"}
                    },
                    {
                      "Name":{"$":"name2"},
                      "Value":{"$":"value2"}
                    }
                ]
            }
        }
    };
    
    var mqHeader = {
      "MQRFH":mqrfh
    };

Examples

  • Sample call to MQ in the options JSON object format. The headers label information in the options object is in a different format from the information for the other labels.
    var urlopen = require ('urlopen');
    var putData = '<MQRequest>Hello World</MQRequest>'; 
    
    var options =
    {
        target: 'mq://192.0.2.0:1414?QueueManager=QM1;UserName=mqm;Channel=QM1.SVRCONN;ChannelTimeout=10;'
                  + 'channelLimit=100;Size=1024000;RequestQueue=queue1;ReplyQueue=queue2',
      
         data : putData,
      headers : { MQMD   : { // JSON object for specified header_name
                                MQMD: { // JSON object for the MQMD header
                                       StructId : { $ : 'MD' } ,
                                        Version : { $ : '1'} ,
                                      }
                            } 
                  }
    };
    
    urlopen.open (options, function (error, response) {} );
  • An example shows how more complicated IBM MQ headers are set and used.
    var urlopen = require('urlopen');
    var putData = '<MQRequest>Hello World</MQRequest>'; 
    
    var urlopenHeaders = {
            // supply an MQMD header
            MQMD : {     // This MQMD is the header name.
                    MQMD: {  // JSON object for the MQMD header
                  StructId : { $ : 'MD' },
                   Version : { $ : '1' },
                    Format : { $ : 'MQHRF2' },
                   MsgType : { $ : '1' },
               ReplyToQMgr : { $ : session.parameters.qm },
                  ReplyToQ : { $ : session.parameters.replyQ },
                    Expiry : { $ : '10000' },
               Persistence : { $ : '1' },
                  Priority : { $ : '10' },
               PutApplType : { $ : '6' },
               PutApplName : { $ : 'My Datapower IBM MQClient' }, 
            ApplOriginData : { $ : 'testUrlOpenMPGW' },
          ApplIdentityData : { $ : 'mqUrlOpenDemo.js' } }
                   },
             // supply an MQRFH2 header
             MQRFH2 : { 
               MQRFH2: {
                     Format: { $ : 'MQSTR' },
              NameValueData: {
                       NameValue: [
                                    { mcd : { property1 : { $ : '1111' } } },
                                    { jms : { property2 : { '@dt': 'string', $ : 'value2'} } },
                                    { usr : { group : {
                                                 property3 : { $ : 'value3' },
                                                 property4 : { $ : 'value4'} } } }
                                  ] }
                   }
             }
     };
    
      var options = {
                         target : 'idgmq://' + session.parameters.qm + '/?RequestQueue='
                             + session.parameters.requestQ,
                       headers : urlopenHeaders,
                        data : putData,
               replyQueue : session.parameters.replyQ,
                      pmo : 2052  // MQPMO_NO_SYNCPOINT (4) + MQPMO_SET_ALL_CONTEXT (2048) };
    
     try {
           urlopen.open(options, function(connectError, response) {
                 if (connectError) {    
                       var errorMessage = connectError + 'errorCode='
                                            + connectError.errorCode.toString(16);
                       console.error(errorMessage);
                       session.output.write(errorMessage);
    
                  } else {
                       var responseCode = response.statusCode; 
                       if (responseCode == 0) {
                             console.info('Received MQ ' + response.statusCode
                                           + ' for target ' + options.target); 
                             response.readAsXML(function(readAsXMLError, xmlDom) {
                                  if (readAsXMLError) {
                                      var errorMessage = 'Error on readAsXML: ' + readAsXMLError;
                                      console.error(errorMessage);
                                      response.readAsBuffer(function(readAsBufferError, buffer) {
                                           if (readAsBufferError) { 
                                                 var errorMessage = 'Error on readAsBuffer: '
                                                                     + readAsBufferError;
                                                 console.error(errorMessage);
                                                 session.output.write(errorMessage);
                                           } else {
                                                 console.info('MQ Response headers: ' + response.headers);
                                                 session.output.write(buffer);
                                           }
                                });
                        } else { 
                            console.info('MQ Response headers: ' + response.headers);
                            session.output.write(xmlDom);
                        }
                   });
               } else {
                  var errorMessage = 'Received MQ ' + response.statusCode + ' for target ' + options.target;
                  session.reject(errorMessage);
               }
            }
        }); 
    } catch (err) {
         var errorMessage = 'Thrown error on urlopen.open for target ' + options.target + ': '
                             + err.message + ', error object errorCode=' + err.errorCode.toString(16);
         session.reject(errorMessage);}
  • An example of how options JSON object can be declared for an MQMP header.
    var urlopenMQMPHeaders = {
    // supply an MQMD header
    MQMD: {         // The property name 'MQMD' is the header name.
      MQMD: {       // This 'MQMD' represents the root property.
                StructId: {$:'MD'},
                 Version: {$:'2'},
                  Format: {$:'MQSTR'},
                 MsgType: {$:'1'},
             ReplyToQMgr: {$:session.parameters.qm},
                ReplyToQ: {$:session.parameters.replyQ},
                  Expiry: {$:'10000'},
             Persistence: {$:'1'},
                Priority: {$:'10'},
             PutApplType: {$:'6'},
             PutApplName: {$:'My Datapower IBM MQClient'},
          ApplOriginData: {$:'testUrlOpenMPGW'},
        ApplIdentityData: {$:'testUrlOpen.js'}
      }
    },
    // supply an MQMP header
    MQMP : {         // The property name 'MQMP' is the header name.
      MQMP: {        // This 'MQMP' represents the root property.
        Property : [ // an array of property
          {'@name':'car.brand','@type':'string',$:'DataPower'},
          {'@name':'car.color','@type':'string',$:'GREEN'},
          {'@name':'car.year','@type':'int32',$:'2005'}
        ]
        }
      }
    };
    options = {
        target: 'idgmq://' + session.parameters.qm + '/?RequestQueue=GATEWAYSCRIPT.PROPERTIES.REQUEST' 
                          + ';ReplyQueue=' + session.parameters.replyQ,
       headers: urlopenMQMPHeaders,
          data: putData,
           pmo: 2052  // MQPMO_NO_SYNCPOINT (4) + MQPMO_SET_ALL_CONTEXT (2048)};
    };