Capitalware would like to announce that TxMQ is a Gold Sponsor of MQ Technical Conference v2.0.1.6 (MQTC).
For more information, please go to: http://www.mqtechconference.com
Regards,
Roger Lacroix
Capitalware Inc.
Capitalware would like to announce that TxMQ is a Gold Sponsor of MQ Technical Conference v2.0.1.6 (MQTC).
For more information, please go to: http://www.mqtechconference.com
Regards,
Roger Lacroix
Capitalware Inc.
Chris Frank of IBM will be speaking at MQ Technical Conference v2.0.1.6 (MQTC). Chris Frank will be presenting the following sessions at MQTC:
For more information about MQTC, please go to:
http://www.mqtechconference.com
Regards,
Roger Lacroix
Capitalware Inc.
Mark Taylor of the IBM UK MQ Labs has published a blog entry on how to use IBM MQ from a Go application. You can read about it at:
https://www.ibm.com/developerworks/community/blogs/messaging/entry/Calling_IBM_MQ_from_Go_applications
I’m kinda surprising that IBM hasn’t created an interface between IBM MQ and Swift, since I get monthly emails from IBM telling me that I can try out Swift programming on a Linux VM.
Regards,
Roger Lacroix
Capitalware Inc.
On June 22nd, 2016, Eclipse Foundation has released the annual Eclipse release train:
https://www.eclipse.org/org/press-release/20160622_neon.php
Eclipse is an open source community, whose projects are focused on building an open development platform comprised of extensible frameworks, tools and runtimes for building, deploying and managing software across the lifecycle. The Eclipse Foundation is a not-for-profit, member supported corporation that hosts the Eclipse projects and helps cultivate both an open source community and an ecosystem of complementary products and services.
Regards,
Roger Lacroix
Capitalware Inc.
Someone over at Stack Overflow posted a question about logging MQ error messages to a file. After the user updated the posting, I recognized the code as mine (MQWrite.java) that I wrote back in 2000 (Yup, 16 years ago!!).
So, I decided to bring MQWrite.java into this decade and created MQWrite2.java. Here is MQWrite2.java that sets the connection information in a HashTable and uses Log4J as the logger. (You can download it from here.)
import java.io.IOException;
import java.util.Hashtable;
import org.apache.log4j.Logger;
import com.ibm.mq.MQException;
import com.ibm.mq.MQMessage;
import com.ibm.mq.MQPutMessageOptions;
import com.ibm.mq.MQQueue;
import com.ibm.mq.MQQueueManager;
import com.ibm.mq.constants.CMQC;
/**
* Program Name
* MQWrite2
*
* Description
* This java class will connect to a queue manager and
* and write a message to a queue.
*
* Sample Command Line Parameters
* -h 127.0.0.1 -p 1414 -c TEST.CHL -m MQA1 -q TEST.Q1
*
* @author Roger Lacroix, Capitalware Inc.
*/
public class MQWrite2
{
private Logger logger = Logger.getLogger(MQWrite2.class.getName());
private Hashtable<String, String> params = null;
private Hashtable<String, Object> mqht = null;
private String qMgrName;
private String outputQName;
/**
* The constructor
*/
public MQWrite2()
{
super();
logger.info("MQWrite2 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("-q");
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");
outputQName = (String) params.get("-q");
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));
}
// I don't want to see MQ exceptions at the console.
MQException.log = null;
}
else
{
throw new IllegalArgumentException();
}
}
/**
* Connect, open queue, write a message, close queue and disconnect.
*
*/
private void testReceive()
{
int openOptions = CMQC.MQOO_OUTPUT + CMQC.MQOO_FAIL_IF_QUIESCING;
MQPutMessageOptions pmo = new MQPutMessageOptions();
MQQueueManager _qMgr = null;
MQQueue queue = null;
MQMessage sendMsg = null;
String line = "This is a test message.";
try
{
_qMgr = new MQQueueManager(qMgrName, mqht);
queue = _qMgr.accessQueue(outputQName, openOptions);
sendMsg = new MQMessage();
sendMsg.messageId = CMQC.MQMI_NONE;
sendMsg.correlationId = CMQC.MQCI_NONE;
sendMsg.writeString(line);
// put the message on the queue
queue.put(sendMsg, pmo);
logger.info("MQWrite2 Message inserted: " + line);
}
catch (MQException mqex)
{
logger.error("MQWrite2 MQException CC=" +mqex.completionCode + " : RC=" + mqex.reasonCode);
}
catch (IOException e)
{
logger.error("MQWrite2 IOException " + e.getLocalizedMessage());
}
finally
{
try
{
if (queue != null)
queue.close();
}
catch (MQException mqex2)
{
logger.error("MQWrite2 MQException CC=" +mqex2.completionCode + " : RC=" + mqex2.reasonCode);
}
finally
{
try
{
if (_qMgr != null)
_qMgr.disconnect();
}
catch (MQException mqex3)
{
logger.error("MQWrite2 MQException CC=" +mqex3.completionCode + " : RC=" + mqex3.reasonCode);
}
}
}
logger.info("MQWrite2 is now ending.");
}
/**
* main line
* @param args
*/
public static void main(String[] args)
{
MQWrite2 write = new MQWrite2();
try
{
write.init(args);
write.testReceive();
}
catch (IllegalArgumentException e)
{
System.out.println("Usage: java MQWrite2 -h host -p port -c channel -m QueueManagerName -q QueueName");
System.exit(1);
}
System.exit(0);
}
}
And here is the ‘log4j.properties’ file that goes with the code (it is included in the download):
#
# stdout
#
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%m%n
#
# MQWrite
#
log4j.category.MQWrite2=DEBUG, mqwrite, stdout
#log4j.category.MQWrite2=INFO, mqwrite, stdout
# "mqwrite" appender writes to a file
log4j.appender.mqwrite=org.apache.log4j.RollingFileAppender
log4j.appender.mqwrite.File=log/MQWrite.log
log4j.appender.mqwrite.MaxFileSize=1000KB
log4j.appender.mqwrite.MaxBackupIndex=9
log4j.appender.mqwrite.layout=org.apache.log4j.PatternLayout
log4j.appender.mqwrite.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %p - %m%n
#log4j.appender.mqwrite.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss.SSS} [%t] %p (%F:%M:%L) - %m%n
Make sure you create a ‘log’ directory under the directory where you run the code from or else it will throw an error like:
log4j:ERROR setFile(null,true) call failed. java.io.FileNotFoundException: log\MQWrite.log (The system cannot find the path specified)
Regards,
Roger Lacroix
Capitalware Inc.
Here’s an interesting head-scratcher. I was writing some Java code to handle an MQ message and in this particular case, it was an MQRFH2 message. The code below was working fine until I decided to dump (output) the message in hexadecimal.
int openOptions = CMQC.MQOO_INQUIRE + CMQC.MQOO_FAIL_IF_QUIESCING;
MQGetMessageOptions gmo = new MQGetMessageOptions();
gmo.options = CMQC.MQGMO_NO_WAIT + CMQC.MQGMO_FAIL_IF_QUIESCING;
MQQueueManager _qMgr = null;
MQQueue queue = null;
MQMessage receiveMsg = null;
MQRFH2 rfh2;
byte[] b;
boolean getMore = true;
try
{
_qMgr = new MQQueueManager(qManager);
queue = _qMgr.accessQueue(inputQName, openOptions);
while(getMore)
{
receiveMsg = new MQMessage();
try
{
queue.get(receiveMsg, gmo);
printMsgHex(receiveMsg);
if (CMQC.MQFMT_RF_HEADER_2.equals(receiveMsg.format))
{
rfh2 = new MQRFH2(receiveMsg);
}
b = new byte[receiveMsg.getDataLength()];
receiveMsg.readFully(b);
System.out.println("Message data-> " + new String(b));
}
catch (com.ibm.mq.MQException e)
{
System.err.println("CC=" +e.completionCode + " : RC=" + e.reasonCode);
getMore = false;
}
catch (java.io.IOException ioex)
{
System.err.println("ioex=" +ioex);
getMore = false;
}
catch (MQDataException e)
{
System.err.println("CC=" +e.completionCode + " : RC=" + e.reasonCode);
getMore = false;
}
}
}
catch (com.ibm.mq.MQException mqex)
{
System.err.println("CC=" +mqex.completionCode + " : RC=" + mqex.reasonCode);
}
finally
{
try
{
if (queue != null)
queue.close();
}
catch (com.ibm.mq.MQException mqex2)
{
System.err.println("CC=" +mqex2.completionCode + " : RC=" + mqex2.reasonCode);
}
finally
{
try
{
if (_qMgr != null)
_qMgr.disconnect();
}
catch (com.ibm.mq.MQException mqex3)
{
System.err.println("CC=" +mqex3.completionCode + " : RC=" + mqex3.reasonCode);
}
}
}
The printMsgHex() method is a simple method to retrieve the message and output.
byte[] b = new byte[msg.getMessageLength()]; msg.readFully(b); etc...
When I would run the code, I would get the following error:
CC=2 : RC=6114
The MQ Knowledge Center says the following:
6114 (X'17E2') MQRC_INSUFFICIENT_DATA Explanation: There is insufficient data after the data pointer to accommodate the request. This reason code occur s in the WebSphere MQ C++ environment. Completion Code: MQCC_FAILED
I scratched my head and said WTF. I’m coding in Java but it is giving me a C++ error message. I commented out the printMsgHex() method and the code would work. I have used the printMsgHex() method for years. I looked at the code and nothing stood out. The only thing different about this code and the other code was the use of the MQRFH2 class.
I sat and stared at the code (we all know that works) and I could not see anything wrong with the code. As I sat scratching my head, I started thinking about the MQMessage class and it occurred to me that IBM implemented it like RandomAccessFile class. Then the light went on. I wondered if the MQRFH2 class reset the cursor position. So I added the following line before the call to the MQRFH2 class and bingo, everything started to work as expected.
receiveMsg.seek(0);
So, the bottom-line is if your code is going to mess around with the message then before using an internal message header class like MQRFH, MQRFH2, MQCIH, MQDEAD, MQIIH or MQXMIT, make sure you update the message’s cursor position to the correct location before passing the message to the class.
if (CMQC.MQFMT_RF_HEADER_2.equals(receiveMsg.format))
{
receiveMsg.seek(0);
rfh2 = new MQRFH2(receiveMsg);
}
Regards,
Roger Lacroix
Capitalware Inc.
Angel Rivera and Mike Cregger of IBM have published a support document titled:
Using SSL TLS to connect two MQ queue managers in MQ 7.5 and MQ 8.0 / MQ 9.0 using self-signed certificates
The document provides step-by-step details for connecting a WebSphere MQ V7.5 queue manager in one platform (Windows) to a V8.0 queue manager running on another platform (Linux), using SSL TLS self-signed certificates.
Note: I have not tested the information in the document.
I have put a local link to the PDF here, in case IBM reshuffles their web site in the page disappears.
Regards,
Roger Lacroix
Capitalware Inc.
Jeff Lowrey of IBM will be speaking at MQ Technical Conference v2.0.1.6 (MQTC).
For more information about MQTC, please go to:
http://www.mqtechconference.com
Regards,
Roger Lacroix
Capitalware Inc.
Lyn Elkins of IBM and her team are generously hosting MQ Labs at MQTC v2.0.1.6. The lab will have 10-12 PCs/laptops with IBM MQ running on them. The labs will be free-format. Attendees will be able to use the lab when they have free time.
For more information about MQTC, please go to:
http://www.mqtechconference.com
Regards,
Roger Lacroix
Capitalware Inc.