What you will learn

  1. Basic MQ messaging REST API usage
  2. Swagger UI for MQ REST APIs
  3. Go and Node.js examples for using the the messaging REST API

What you will need

  1. IBM MQ queue manager, queue and client app credentials
  2. Curl
  3. Go example
  4. Node.js example 1 and example 2

What can you do with the MQ messaging REST API

IBM MQ allows you to interact with its server objects through different interfaces or APIs. You might need to set things up as an architect, configure and maintain as an administrator or use queues, topics and subscriptions in your applications that connect to the MQ server, as an application developer.

This tutorial shows you how to use the messaging REST API in your applications so they can interact with the queue manager and its objects.

MQ has a number of APIs that applications written in different languages can use. Click through the Languages, Wire Formats and APIs slides for info on how they are connected. The Message Queue Interface or MQI is the interface that allows the most comprehensive access to MQ objects for applications.

The messaging REST API currently offers a more basic interface for interacting with queues and so can be quick and easy to get started with.

MQ APIs, languages, wire formats slide 1

MQ APIs, languages, wire formats slide 2 - C

MQ APIs, languages, wire formats slide 3 - C++

MQ APIs, languages, wire formats slide 4 - Java

MQ APIs, languages, wire formats slide 5 - Java

MQ APIs, languages, wire formats slide 6 - Python

MQ APIs, languages, wire formats slide 7 - Go

MQ APIs, languages, wire formats slide 8 - Node.js

MQ APIs, languages, wire formats slide 9 - Ruby, Java, Node.js

If you already have credentials to access a configured MQ messaging REST API and authority to connect to a queue manager and use a queue, you can skip to section 4.

Set up your queue manager

Go to Ready, Set, Connect to set up your queue manager, then come back here to continue with section 3.

Configure the mqweb server

Go to Getting started with the messaging REST API topic in the IBM MQ Knowledge Center to set up the MQ REST API, then come back here to continue with the next section. If you also need to set up the IBM MQ Console, check out the Getting started with the IBM MQ Console topic too.

cURL – put a message

You can try out the MQ messaging REST API by using cURL. cURL is a command line tool and library for transferring data with URLs. You can install it on any platform.

Make sure that you have curl installed:

curl -V

The MQ messaging REST API expects the following basic details in the POST request that will put a message on a queue:

https://host:port/ibmmq/rest/v1/messaging/qmgr/your_qm_name/queue/your_queue_name/message
for example,

https://localhost:9443/ibmmq/rest/v1/messaging/qmgr/QM1/queue/DEV.QUEUE.1/message

Issue the cURL POST command that will put a message to a queue

curl -i -k https://localhost:9443/ibmmq/rest/v1/messaging/qmgr/QM1/queue/DEV.QUEUE.1/message -X POST -u user:password -H "ibm-mq-rest-csrf-token: blank" -H "Content-Type: text/plain;charset=utf-8" -d "Hello World!"

You'll see:

HTTP/1.1 201 Created
X-Powered-By: Servlet/3.1
X-XSS-Protection: 1;mode=block
X-Content-Type-Options: nosniff
Content-Security-Policy: default-src 'none'; script-src 'self' 'unsafe-inline' 'unsafe-eval'; connect-src 'self'; img-src 'self'; style-src 'self' 'unsafe-inline'; font-src 'self'
Cache-Control: no-cache, no-store, must-revalidate
Content-Language: en-US
Content-Length: 0
Content-Type: text/plain; charset=utf-8
ibm-mq-md-messageId: 414d5120514d312020202020202020204aa5585b026bb624
Date: Thu, 26 Jul 2018 07:36:33 GMT

Well done! If your output message looks like the one here, you've successfully used cURL to put a message to the queue. See if you can get the message off the queue by using a similar command.


cURL - get a message

The MQ messaging REST API expects the following basic details in the DELETE request that will destructively GET a message from a queue:

curl -i -k https://localhost:9443/ibmmq/rest/v1/messaging/qmgr/QM1/queue/DEV.QUEUE.1/message -X DELETE -u user:password -H "ibm-mq-rest-csrf-token: blank"

You'll see:

HTTP/1.1 200 OK
X-Powered-By: Servlet/3.1
X-XSS-Protection: 1;mode=block
X-Content-Type-Options: nosniff
Content-Security-Policy: default-src 'none'; script-src 'self' 'unsafe-inline' 'unsafe-eval'; connect-src 'self'; img-src 'self'; style-src 'self' 'unsafe-inline'; font-src 'self'
Cache-Control: no-cache, no-store, must-revalidate
Content-Type: text/plain; charset=utf-8
Content-Language: en-US
ibm-mq-md-expiry: unlimited
ibm-mq-md-messageId: 414d5120514d312020202020202020204aa5585b026bb624
ibm-mq-md-persistence: nonPersistent
Content-Length: 12
Date: Thu, 26 Jul 2018 07:46:46 GMT

Hello World!

Well done! If your output message looks like the one here, you've successfully used cURL to get your message from the queue.
Next up, check out examples of how you can use the MQ messaging REST API in a Go or Node.js application.


MQ REST API discovery with Swagger UI

The mqweb server provides an option for switching on the API Discovery feature.

MQ REST API Swagger

When the mqweb server is set up and running, and the .xml file that you configured in section 3 contains the line inside the 'featureManager' tags:

<featureManager>
<feature>apiDiscovery-1.0</feature>
</featureManager>

you can then use the Swagger documentation by:

  • pointing your browser to
    https://host:port/ibm/api/explorer
    and using the Swagger UI to interact with the REST APIs – you can put and get messages from the 'messaging REST API' sections and see the queue depth change in the MQ Console for the queue DEV.QUEUE.1.
  • Retrieving a Swagger 2 document that describes the whole REST API from
    https://host:port/ibm/api/docs

MQ messaging REST API examples

In this example, the put and get calls are wrapped in Go functions.

The queue manager that the application looks to communicate with is running in IBM Cloud. The default port for queue managers running in IBM Cloud is 443. A user can specify a different port but if no port is available, the default will be used.

The request URL for the queue manager, qmURL, is constructed to include the host, port, the default path for the messaging REST API, queue manager name, and queue name.

The request is then created, the message type is set and additional parameters that we used in our cURL calls earlier are added; the CSRF token, the content type and user and password for authentication.

The sender and receiver samples that are a part of this application pass on the correct MQ parameters to this method and the REST call is constructed and sent.

func mqRestCall(qm QueueManager, q Queue, verb string, msg Message, queryParams string) (statusCode int, body []byte, err error) {

if qm.Port == "" {
	qm.Port = "443"
}

qmURL := "https://" + qm.Host + ":" + qm.Port + "/ibmmq/rest/v1/messaging/qmgr/" + qm.Name + "/queue/" + q.Name + "/message"
if queryParams != "" {
	qmURL = qmURL + queryParams
}

// allow self-signed certs. Only required in dev.
tr := &http.Transport{
	TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
}
client := &http.Client{Transport: tr}

//	client := &http.Client{}
msgByteSlice := []byte(msg.Message)
req, err := http.NewRequest(verb, qmURL, bytes.NewBuffer(msgByteSlice))
if err != nil {
	fmt.Printf("Error preparing rest call. Error: %v", err)
	return statusCode, body, err
}

if msg.MsgType == "" {
	msg.MsgType = "application/json"
}
req.Header.Add("ibm-mq-rest-csrf-token", "anyvalue")
req.Header.Add("Content-Type", msg.MsgType)
req.SetBasicAuth(qm.Username, qm.Password)

resp, err := client.Do(req)

In this Node.js example, available in our github repository, we put and get a message with the help of a basic HTTPS module.

Set up variables to include the HTTPS module, the base URI for the rest call, user and password for the Liberty server and MQ, queue manager and queue name:

// Use the inbuilt HTTPS module. Though there are simplified alternatives
var https=require('https')

// All the admin REST calls start from this point
var apiBase="/ibmmq/rest/v1/"

// Who am I
var username="app"
var password="_APP_PASSWORD_"

var queue="DEV.QUEUE.1"
var qMgr ="QM1"

Set up the GET call with basic details that the MQ messaging REST API needs to authenticate the request:

// Use basic authentication - pass userid/password on every request
// Could use alternatives with the LTPA token after a call to the /login API
var options = {
  hostname:"localhost",
  port:9443,
  method:'GET',
  headers: {
    'Authorization': 'Basic ' + new Buffer(username + ':' + password).toString('base64'),
    'Content-Type' : 'text/plain',
// Need this header for POST operations even if it has no content
    'ibm-mq-rest-csrf-token' : ''
   }
}

Construct the request path from the declared variables:

// Construct the full API path from the base for a particular request
                options.path = apiBase + "messaging/qmgr/" + qMgr + "/queue/" + queue + "/message"

Put the message:

putMessage()

///////////////////////////////////////////////////////
function putMessage() {
  // And call the operation
  options.method = 'POST'
  var request = https.request(options,(response) => {
    console.log('POST   statusCode : ', response.statusCode);
    response.setEncoding('utf8');

    response.on('data',function(cbresponse) {
       console.log('POST response: ',cbresponse);
    });

    // Once the message has been successfully put, try to get it again
    response.on('end', function() {
        getMessage();
    });
  });

  request.on('error', function (e) {
    console.log('problem with request: ' + e);
  });

  var msg = "Hello world at " + new Date()

  request.write(msg)
  request.end();
}

Get the message:

function getMessage() {
// Call the operation
options.method = 'DELETE'
var request = https.request(options,(response) => {
  console.log('DELETE statusCode : ', response.statusCode);
  response.setEncoding('utf8');
  response.on('data',function(cbresponse) {
     console.log('Message is <%s>',cbresponse);
  });
});

Make sure you have Node installed. From the directory with your mq-rest-node-https.js sample, run;

node mq-rest-node-https.js

You'll see:

POST   statusCode :  201
DELETE statusCode :  200
Message is <Hello world at Thu Aug 23 2018 12:02:09 GMT+0100 (BST)>

This Node.js example, available in our github repository, shows you how to use JavaScript promises so the put and get can be used in the right sequence.

// Define the function to be used when putting a message. The
// function returns a Promise so it can be used in sequence
// before the retrieval.
const putMessage = function(msg) {
  return new Promise((resolve,reject) =>  {
    options.method = 'POST';

    // Create the request and aggregate any returned data
    var request = https.request(options,(response) => {
      if (response.statusCode < 200 || response.statusCode > 299) {
        var errMsg = util.format("POST failed.\nStatusCode: %d\nStatusMessage: \n",response.statusCode, response.statusMessage);
        reject(new Error(errMsg));

      } else {
        console.log('POST   statusCode: ' + response.statusCode);
      }
      var body = '';
      response.on('data',(chunk) => body +=chunk);
      response.on('end', () => resolve());
    });

    request.on('error', (error) => reject(error));
    // Send the message contents
    request.write(msg);
    request.end();
  });
};

// Define a function used to retrieve a message. Use
// a Promise to control when it's ready to print the
// contents.
const getMessage = function() {
  return new Promise((resolve,reject) => {
    options.method = 'DELETE';

    // Create the request and aggregate any returned data
    var request = https.request(options,(response) => {
      if (response.statusCode < 200 || response.statusCode > 299) {
        var errMsg = util.format("DELETE failed.\nStatusCode: %d\nStatusMessage: ",response.statusCode, response.statusMessage);
        reject(new Error(errMsg));
      } else {
        console.log('DELETE statusCode: ' + response.statusCode);
      }
      var body = ''; // The message contents
      response.on('data',(chunk) => body +=chunk);
      response.on('end', () => resolve(body));
    });
    request.on('error', (error) => reject(error));
    request.end();
  });
};

// Create message contents
var msg = "Hello world at " + new Date();

// Put the message and then try to retrieve it. Using Promises
// simplifies the flow and error handling.
putMessage(msg)
  .then(()   => getMessage())
  .then(body => console.log(body))
  .catch(err => console.error(err));

Make sure you have Node installed. From the directory with your mq-rest-node-promise.js sample, run;

node mq-rest-node-promise.js

You'll see:

POST   statusCode: 201
DELETE statusCode: 200
Hello world at Thu Aug 23 2018 12:16:29 GMT+0100 (BST)

Congratulations! You can REST easy now that you've put and got your messages.