Proud to be named as an IBM Champion for my contributions to IBM MQ community for the 2nd year in a row!
https://www.ibm.com/developerworks/champion/
Regards,
Roger Lacroix
Capitalware Inc.
Proud to be named as an IBM Champion for my contributions to IBM MQ community for the 2nd year in a row!
https://www.ibm.com/developerworks/champion/
Regards,
Roger Lacroix
Capitalware Inc.
All,
Capitalware is ready for beta testers for a new solution called: MQ Channel Connection Inspector.
Have you ever had client applications or remote queue managers attempt to connect to your queue manager but failed and the user claimed they used the “correct values”.
I’ve created a new solution to quickly diagnose this problem and need some beta testers to give me some feedback. MQ Channel Connection Inspector (MQCCI) is an MQ Channel Security Exit. For those who don’t know, a channel security exit is ONLY invoked/called by the MCA for MQCONN/X and MQDISC API calls (so it is very light-weight). The MCA passes the MQCD and MQCXP structures to the channel security exit. Those structures contain SSL/TLS fields, MCAUserId, batch size, retry information, etc. The MQCD structure has 82 fields and the MQCXP structure 26 fields (see MQ’s cmqxc.h file for more details).
I have designed MQCCI to output any or all of the fields from the MQCD and MQCXP structures (user selectable). The information is written to a CSV (Comma-Separated-Values) file. Right now, the output is in the format of “field=value,field=value,field=value,etc.”. The “value” data has been converted to human-readable format. The first question for beta testers is this an acceptable format or would you prefer a true CSV/spreadsheet format. i.e. where the field/column names are in row 1 and only the values are in rows 2 through to the last row.
Current format:
2018/01/10 17:25:07.712373, CONN, QMgrName=MQWT1, ChlName=TEST.EXIT, CD_MaxMsgLength=4194304, CD_PutAuthority=MQPA_DEFAULT, CD_MCAUserIdentifier=barney, CD_ConnectionName=10.10.10.10, CD_RemoteUserIdentifier=barney, CXP_RemoteProduct=MQCC, CXP_RemoteVersion=0800,
Or a true CSV/spreadsheet format would be (row # 1 would only be in the CSV file once):
"Date/Time", "API Call", Queue Manager Name", "Channel Name", "CD_MaxMsgLength", "CD_PutAuthority", "CD_MCAUserIdentifier", "CD_ConnectionName", "CD_RemoteUserIdentifier", "CXP_RemoteProduct", "CXP_RemoteVersion", "2018/01/10 17:25:07.712373", "CONN", "MQWT1", "TEST.EXIT", 4194304, "MQPA_DEFAULT", "barney", "10.10.10.10", "barney", "MQCC", "0800", "2018/01/10 17:25:09.446511", "CONN", "MQWT1", "TEST.EXIT", 4194304, "MQPA_DEFAULT", "wilma", "10.10.10.20", "wilma", "MQCC", "0800",
I plan on building MQ Channel Connection Inspector for AIX, HP-UX (RISC & IA64), Solaris (SPARC & x86_64), Linux (x86, x86_64, POWER & zSeries), Windows and IBM i (OS/400) and z/OS. MQ Channel Connection Inspector will support WMQ v6.0, v7.0, v7.1, v7.5, v8.0 & v9.0.
Beta testing MQ Channel Connection Inspector is absolutely free including support (no strings attached).
If you interesting in trying it out, please send an email to support@capitalware.com to request a trial of MQ Channel Connection Inspector,
Regards,
Roger Lacroix
Capitalware Inc.
IBM has made available the MQ Redistributable Client (Java/JMS portion) on Maven. Mark Taylor of IBM has a blog posting on it and how to configure your files to use it:
https://developer.ibm.com/messaging/2018/01/09/developing-mq-java-applications-maven/
Regards,
Roger Lacroix
Capitalware Inc.
Its January 9th, 2018 and I’m already sick of winter. Polar vortex, snow and more snow. I know it is early January and I’m Canadian but I’m sick of it. Snow banks are over 6 feet (2 meters) tall. I want Spring and not in 2 and half months but now. 🙁
Here’s a picture looking up my street (click to see a larger image):

Here’s another picture looking down my street (click to see a larger image):

Snow and cold is great for Christmas holidays but when the holidays are over, the snow needs to go too (just like the Christmas tree). I really need to move somewhere where it is warm this time of year. 🙂
Regards,
Roger Lacroix
Capitalware Inc.
Capitalware Inc. would like to announce the official release of MQ Batch Toolkit v3.0.0. MQ Batch Toolkit allows users to manipulate, monitor and manage messages in a queue of an IBM MQ (formally WebSphere MQ & MQSeries) queue manager from a command-line or shell scripting environment.
Starting with MQ Batch Toolkit v3.0.0, the licensing model has changed to be subscription based model meaning there will be no upfront software cost, only a yearly subscription fee.
New lower price: The cost for MQ Batch Toolkit is now $49.00 USD per user for a 1-year subscription.
For more information about MQ Batch Toolkit go to:
https://www.capitalware.com/mqbt_overview.html
Regards,
Roger Lacroix
Capitalware Inc.
I would like to wish everyone a Merry Christmas, Happy Hanukkah, Happy Kwanzaa, etc… and a Happy New Year. 🙂
Regards,
Roger Lacroix
Capitalware Inc.
Here is blog posting # 2 on subscribing to a topic in IBM MQ. More code examples – here is a Java IBM MQ (non-JMS) sample program to subscribe to a topic within a queue manager of IBM MQ. It will receives messages until ‘no messages available’ exception which is set for 30 seconds.
You can download the source code from here.
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Hashtable;
import com.ibm.mq.MQException;
import com.ibm.mq.MQGetMessageOptions;
import com.ibm.mq.MQMessage;
import com.ibm.mq.MQQueueManager;
import com.ibm.mq.MQTopic;
import com.ibm.mq.constants.CMQC;
/**
* Program Name
* MQSub01
*
* Description
* This java class will connect to a queue manager, subscribe to a topic and receive messages.
*
* Sample Command Line Parameters
* -h 127.0.0.1 -p 1414 -c TEST.CHL -m MQA1 -t topicString -o topicObject -u userId -x password
*
* @author Roger Lacroix, Capitalware Inc.
*/
public class MQSub01
{
private static final SimpleDateFormat lOGGER_TIMESTAMP = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss.SSS");
private Hashtable<String, String> params = null;
private Hashtable<String, Object> mqht = null;
private String qMgrName;
private String topicString = null;
private String topicObject = null;
/**
* The constructor
*/
public MQSub01()
{
super();
MQSub01.logger("Is now starting.");
}
/**
* Make sure the required parameters are present.
* @return true/false
*/
private boolean allParamsPresent()
{
boolean b = params.containsKey("-h") && params.containsKey("-p") &&
params.containsKey("-c") && params.containsKey("-m") &&
params.containsKey("-u") && params.containsKey("-x");
// Need at least one
if ( (!params.containsKey("-t")) && (!params.containsKey("-o")) )
b = false;
if (b)
{
try
{
Integer.parseInt((String) params.get("-p"));
}
catch (NumberFormatException e)
{
b = false;
}
}
return b;
}
/**
* Extract the command-line parameters and initialize the MQ variables.
* @param args
* @throws IllegalArgumentException
*/
private void init(String[] args) throws IllegalArgumentException
{
params = new Hashtable<String, String>();
if (args.length > 0 && (args.length % 2) == 0)
{
for (int i = 0; i < args.length; i += 2)
{
params.put(args[i], args[i + 1]);
}
}
else
{
throw new IllegalArgumentException();
}
if (allParamsPresent())
{
qMgrName = (String) params.get("-m");
topicString = (String) params.get("-t");
topicObject = (String) params.get("-o");
mqht = new Hashtable<String, Object>();
mqht.put(CMQC.CHANNEL_PROPERTY, params.get("-c"));
mqht.put(CMQC.HOST_NAME_PROPERTY, params.get("-h"));
try
{
mqht.put(CMQC.PORT_PROPERTY, new Integer(params.get("-p")));
}
catch (NumberFormatException e)
{
mqht.put(CMQC.PORT_PROPERTY, new Integer(1414));
}
mqht.put(CMQC.USER_ID_PROPERTY, params.get("-u"));
mqht.put(CMQC.PASSWORD_PROPERTY, params.get("-x"));
// I don't want to see MQ exceptions at the console.
MQException.log = null;
}
else
{
throw new IllegalArgumentException();
}
}
/**
* Connect, open topic, receive messages, close topic and disconnect.
*
*/
private void testSub()
{
int openOptionsForGet = CMQC.MQSO_CREATE | CMQC.MQSO_FAIL_IF_QUIESCING | CMQC.MQSO_MANAGED | CMQC.MQSO_NON_DURABLE;
MQQueueManager _qMgr = null;
MQTopic subscriber = null;
MQGetMessageOptions gmo = new MQGetMessageOptions();
gmo.options = CMQC.MQGMO_WAIT + CMQC.MQGMO_FAIL_IF_QUIESCING;
gmo.waitInterval = 30000; // wait up to 30 seconds
MQMessage mqMsg = null;
String msgText = null;
boolean more = true;
try
{
_qMgr = new MQQueueManager(qMgrName, mqht);
MQSub01.logger("connected to queue manager: " + qMgrName);
subscriber = _qMgr.accessTopic( topicString,
topicObject,
CMQC.MQTOPIC_OPEN_AS_SUBSCRIPTION,
openOptionsForGet);
logger("subscribed to topic: " + subscriber.getName());
while (more)
{
try
{
mqMsg = new MQMessage();
mqMsg.messageId = CMQC.MQMI_NONE;
mqMsg.correlationId = CMQC.MQCI_NONE;
subscriber.get(mqMsg, gmo);
msgText = mqMsg.readStringOfByteLength(mqMsg.getMessageLength());
MQSub01.logger("received message: " + msgText);
}
catch (MQException e)
{
more = false;
MQSub01.logger("MQException CC=" +e.completionCode + " : RC=" + e.reasonCode);
}
catch (IOException e)
{
more = false;
MQSub01.logger("IOException " + e.getLocalizedMessage());
}
}
}
catch (MQException e)
{
MQSub01.logger("MQException CC=" +e.completionCode + " : RC=" + e.reasonCode);
}
finally
{
try
{
if (subscriber != null)
subscriber.close();
}
catch (MQException e)
{
MQSub01.logger("MQException CC=" +e.completionCode + " : RC=" + e.reasonCode);
}
try
{
if (_qMgr != null)
_qMgr.disconnect();
}
catch (MQException e)
{
MQSub01.logger("MQException CC=" +e.completionCode + " : RC=" + e.reasonCode);
}
}
MQSub01.logger("Is now ending.");
}
/**
* A simple logger method
* @param data
*/
public static void logger(String data)
{
String className = Thread.currentThread().getStackTrace()[2].getClassName();
// Remove the package info.
if ( (className != null) && (className.lastIndexOf('.') != -1) )
className = className.substring(className.lastIndexOf('.')+1);
System.out.println(lOGGER_TIMESTAMP.format(new Date())+" "+className+": "+Thread.currentThread().getStackTrace()[2].getMethodName()+": "+data);
}
/**
* main line
* @param args
*/
public static void main(String[] args)
{
MQSub01 mqs = new MQSub01();
try
{
mqs.init(args);
mqs.testSub();
}
catch (IllegalArgumentException e)
{
System.out.println("Usage: java MQSub01 -h host -p port -c channel -m QueueManagerName -t topicString -o topicObject -u userId -x password");
System.exit(1);
}
System.exit(0);
}
}
Things to note:
Regards,
Roger Lacroix
Capitalware Inc.
Programmers always have questions about coding Pub/Sub in IBM MQ. I’ll do 2 blog posting: one on publishing to a topic and the next one on subscribing to a topic in IBM MQ. Since everyone likes code examples, here is a Java IBM MQ (non-JMS) sample program to publish a message to a topic within a queue manager of IBM MQ.
You can download the source code from here.
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Hashtable;
import com.ibm.mq.MQException;
import com.ibm.mq.MQMessage;
import com.ibm.mq.MQPutMessageOptions;
import com.ibm.mq.MQQueueManager;
import com.ibm.mq.MQTopic;
import com.ibm.mq.constants.CMQC;
/**
* Program Name
* MQPub01
*
* Description
* This java class will connect to a queue manager and publish a message to a topic.
*
* Sample Command Line Parameters
* -h 127.0.0.1 -p 1414 -c TEST.CHL -m MQA1 -t topicString -o topicObject -u userId -x password
*
* @author Roger Lacroix, Capitalware Inc.
*/
public class MQPub01
{
private static final SimpleDateFormat lOGGER_TIMESTAMP = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss.SSS");
private Hashtable<String, String> params = null;
private Hashtable<String, Object> mqht = null;
private String qMgrName;
private String topicString = null;
private String topicObject = null;
/**
* The constructor
*/
public MQPub01()
{
super();
MQPub01.logger("Is now starting.");
}
/**
* Make sure the required parameters are present.
* @return true/false
*/
private boolean allParamsPresent()
{
boolean b = params.containsKey("-h") && params.containsKey("-p") &&
params.containsKey("-c") && params.containsKey("-m") &&
params.containsKey("-u") && params.containsKey("-x");
// Need at least one
if ( (!params.containsKey("-t")) && (!params.containsKey("-o")) )
b = false;
if (b)
{
try
{
Integer.parseInt((String) params.get("-p"));
}
catch (NumberFormatException e)
{
b = false;
}
}
return b;
}
/**
* Extract the command-line parameters and initialize the MQ variables.
* @param args
* @throws IllegalArgumentException
*/
private void init(String[] args) throws IllegalArgumentException
{
params = new Hashtable<String, String>();
if (args.length > 0 && (args.length % 2) == 0)
{
for (int i = 0; i < args.length; i += 2)
{
params.put(args[i], args[i + 1]);
}
}
else
{
throw new IllegalArgumentException();
}
if (allParamsPresent())
{
qMgrName = (String) params.get("-m");
topicString = (String) params.get("-t");
topicObject = (String) params.get("-o");
mqht = new Hashtable<String, Object>();
mqht.put(CMQC.CHANNEL_PROPERTY, params.get("-c"));
mqht.put(CMQC.HOST_NAME_PROPERTY, params.get("-h"));
try
{
mqht.put(CMQC.PORT_PROPERTY, new Integer(params.get("-p")));
}
catch (NumberFormatException e)
{
mqht.put(CMQC.PORT_PROPERTY, new Integer(1414));
}
mqht.put(CMQC.USER_ID_PROPERTY, params.get("-u"));
mqht.put(CMQC.PASSWORD_PROPERTY, params.get("-x"));
// I don't want to see MQ exceptions at the console.
MQException.log = null;
}
else
{
throw new IllegalArgumentException();
}
}
/**
* Connect, open topic, write a message, close topic and disconnect.
*
*/
private void testPub()
{
int openOutputOptions = CMQC.MQOO_OUTPUT + CMQC.MQOO_FAIL_IF_QUIESCING;
MQPutMessageOptions pmo = new MQPutMessageOptions();
MQQueueManager _qMgr = null;
MQTopic publisher = null;
MQMessage mqMsg = null;
String line = "This is a test message from MQPub01.";
try
{
_qMgr = new MQQueueManager(qMgrName, mqht);
MQPub01.logger("connected to queue manager: " + qMgrName);
publisher = _qMgr.accessTopic( topicString,
topicObject,
CMQC.MQTOPIC_OPEN_AS_PUBLICATION,
openOutputOptions);
MQPub01.logger("opened topic: " + publisher.getName());
mqMsg = new MQMessage();
mqMsg.messageId = CMQC.MQMI_NONE;
mqMsg.correlationId = CMQC.MQCI_NONE;
mqMsg.writeString(line);
publisher.put(mqMsg, pmo);
MQPub01.logger("message published: " + line);
}
catch (MQException e)
{
MQPub01.logger("MQException CC=" +e.completionCode + " : RC=" + e.reasonCode);
}
catch (IOException e)
{
MQPub01.logger("IOException " + e.getLocalizedMessage());
}
finally
{
try
{
if (publisher != null)
publisher.close();
}
catch (MQException e)
{
MQPub01.logger("MQException CC=" +e.completionCode + " : RC=" + e.reasonCode);
}
try
{
if (_qMgr != null)
_qMgr.disconnect();
}
catch (MQException e)
{
MQPub01.logger("MQException CC=" +e.completionCode + " : RC=" + e.reasonCode);
}
}
MQPub01.logger("Is now ending.");
}
/**
* A simple logger method
* @param data
*/
public static void logger(String data)
{
String className = Thread.currentThread().getStackTrace()[2].getClassName();
// Remove the package info.
if ( (className != null) && (className.lastIndexOf('.') != -1) )
className = className.substring(className.lastIndexOf('.')+1);
System.out.println(lOGGER_TIMESTAMP.format(new Date())+" "+className+": "+Thread.currentThread().getStackTrace()[2].getMethodName()+": "+data);
}
/**
* main line
* @param args
*/
public static void main(String[] args)
{
MQPub01 mqp = new MQPub01();
try
{
mqp.init(args);
mqp.testPub();
}
catch (IllegalArgumentException e)
{
System.out.println("Usage: java MQPub01 -h host -p port -c channel -m QueueManagerName -t topicString -o topicObject -u userId -x password");
System.exit(1);
}
System.exit(0);
}
}
Things to note:
Regards,
Roger Lacroix
Capitalware Inc.