vx_MQClient

vx_MQClient – Websphere MQ-client for PHP

Background

We’ve been trying to incorporate a client for IBM Websphere MQ to our Vortex framework using the PECL plugin mqseries (http://php.net/manual/en/book.mqseries.php). This is working fine, however when using MQRFH2 headers, which we currently are, the mqseries plugin is no good as it currently removes the headers from the message payload and discards them.

To solve this problem we’ve made a minor adjustment to the plugin as described below, and written a vx_MQMessage class used to parse messages. We’ve also made a vx_MQClient class simplifying connection, browsing, getting and putting messages to and from the MQ QueueManager.

This project is work in progress as it currently only supports parsing MQRFH2 header information, although for other types of headers it removes the header data from the message payload, and will re-attach it to the outgoing message, enabling moving complete messages between MQ Queues, which the mqseries plugin could not do earlier.

Prerequisites

  • First you need to install the Websphere MQ Client for your platform. This is downloaded from IBM (download here).
  • After downloading and unpacking the .tgz you will have a bunch of packages to install. For the PHP client to work, MQSeriesSDK needs to be installed.
  • Download the PECL package from here
  • Apply the patch as described below to the mqseries.c sourcefile
  • phpize, make and install the plugin, checking phpinfo() for availability

Patching mqseries.c

Find the function mqseries_get, this is the one we need to modify.

PHP_FUNCTION(mqseries_get)

After the declaration of all zval add a new zval declaration

zval *z_hdr;

Change the zend_parse_parameters line to read

if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rraalzzzzz", &z_mqdesc, &z_mqobj, &z_msg_desc, &z_get_msg_opts, &buf_len, &z_buffer, &z_data_length, &z_comp_code, &z_reason, &z_hdr) == FAILURE) {
  return;
}

Finally change the section of the code that removes the header information from the message from

if (!strncmp(msg_desc.Format, MQFMT_RF_HEADER, sizeof(msg_desc.Format))) {
  MQRFH rfh = {MQRFH_DEFAULT};
  memcpy(&rfh, buf, MQRFH_STRUC_LENGTH_FIXED);
  data = buf + rfh.StrucLength;
  buf_len -= rfh.StrucLength;
} else if (!strncmp(msg_desc.Format, MQFMT_RF_HEADER_2, sizeof(msg_desc.Format))) {
  MQRFH2 rfh2 = {MQRFH2_DEFAULT};
  memcpy(&rfh2, buf, MQRFH_STRUC_LENGTH_FIXED_2);
  data = buf + rfh2.StrucLength;
  buf_len -= rfh2.StrucLength;
} else if (!strncmp(msg_desc.Format, MQFMT_MD_EXTENSION, sizeof(msg_desc.Format))) {
  MQMDE rfhe = { MQMDE_DEFAULT };
  memcpy(&rfhe, buf, MQMDE_LENGTH_2);
  data = buf + rfhe.StrucLength;
  buf_len -= rfhe.StrucLength;
}

to

if (!strncmp(msg_desc.Format, MQFMT_RF_HEADER, sizeof(msg_desc.Format))) {
  MQRFH rfh = {MQRFH_DEFAULT};
  memcpy(&rfh, buf, MQRFH_STRUC_LENGTH_FIXED);
  zval_dtor( z_hdr );
  ZVAL_STRINGL( z_hdr, (char *)buf, rfh.StrucLength, 1);
  data = buf + rfh.StrucLength;
  buf_len -= rfh.StrucLength;
} else if (!strncmp(msg_desc.Format, MQFMT_RF_HEADER_2, sizeof(msg_desc.Format))) {
  MQRFH2 rfh2 = {MQRFH2_DEFAULT};
  memcpy(&rfh2, buf, MQRFH_STRUC_LENGTH_FIXED_2);
  zval_dtor( z_hdr );
  ZVAL_STRINGL( z_hdr, (char *)buf, rfh2.StrucLength,1);

  data = buf + rfh2.StrucLength;
  buf_len -= rfh2.StrucLength;
} else if (!strncmp(msg_desc.Format, MQFMT_MD_EXTENSION, sizeof(msg_desc.Format))) {
  MQMDE rfhe = { MQMDE_DEFAULT };
  memcpy(&rfhe, buf, MQMDE_LENGTH_2);
  zval_dtor( z_hdr );
  ZVAL_STRINGL( z_hdr, (char *)buf, rfhe.StrucLength, 1);
  data = buf + rfhe.StrucLength;
  buf_len -= rfhe.StrucLength;
}

This stores the header information to the *z_hdr parameter, changing the syntax of the mqseries_get function adding a $hdr parameter to the end of the parameter list.
Or simply apply this patch to the mqseries 0.14.2 version.

PHP Classes

Download the archive, unpack it and include the mqclient.php in your .php file. API Documentation is found here.

Version history

v1.0 – Initial release (2016-02-05)
v1.01 – Logger is only run if the Logger class is defined, for use without the vortex (2016-02-08)
v1.02 – Removed some debug information, added $msgid to get and browse methods to fetch a specific message (2016-02-09)