IBM has just released Fix Pack 9.0.0.9 for IBM MQ V9.0 LTS
https://www.ibm.com/support/pages/node/3255381?myns=swgws&mynp=OCSSYHRD
Regards,
Roger Lacroix
Capitalware Inc.
IBM has just released Fix Pack 9.0.0.9 for IBM MQ V9.0 LTS
https://www.ibm.com/support/pages/node/3255381?myns=swgws&mynp=OCSSYHRD
Regards,
Roger Lacroix
Capitalware Inc.
After I received David La Rose of IBM’s email, I replied asking about the IBM Integration Technical Conference 2020 and I copied Ray Daniel of IBM on the email.
Ray Daniel replied with an official statement of:
Thank you for your interest in the Integration Technical Conference 2020 on March 16-19. Due to participant travel concerns related to COVID-19, IBM is postponing the conference. We will share the new dates once the conference reschedule is finalized. Thank you for your understanding and being a part of our community.
and he include the following comment:
The important take away is that we are postponing until August, but it will still be face to face and in Dallas!
Regards,
Roger Lacroix
Capitalware Inc.
I just received the following email from David La Rose of IBM saying that IBM Think 2020 has been cancelled and turn into a virtual event.
Here is what email said:
The health of IBM’s clients, employees and business partners is our primary concern. In light of global precautions for the COVID-19 Coronavirus, and building upon recommendations from the World Health Organization, IBM is taking a new approach to its signature events.
“IBM Think 2020,” the company’s premier client and developer conference, and PartnerWorld, IBM’s flagship event for business partners, will be recreated as global, digital-first events, to still be held May 5-7.
Think 2020 and PartnerWorld will be an exciting combination of live streamed content, interactive sessions and certifications, and locally hosted events, which will highlight IBM’s technology and industry expertise for business partners, developers and clients without the risk of travel. We will share updates here.
Attendees who were registered for Think will be issued a full refund and automatically be registered for Think Virtual Experience at no charge. We hope you will join us for our digital Think and PartnerWorld programs.
Regards,
Roger Lacroix
Capitalware Inc.
After 25 years, it is still surprising that Java doesn’t have a proper byte array class. There can be many reasons that the data a Java program needs to work with is in a byte array. It could be the contents of a file or MQTT message or IBM MQ message, etc. Since there is no byte array class for working with a byte array that means that every Java programmer must either write their own class or search the internet for what they need. Talk about millions of people re-inventing the wheel over and over again (probably every day for the last 25 years).
FYI: A byte array is simply an array of bytes (i.e. byte[] ). “byte” is a primitive object in Java. A Java primitive does not have any methods declared for it other than what is inherited from “java.lang.Object”. As the name implies, it is the most basic of objects.
A lot of programmers will simply convert the byte array to a String and use the methods of the String class. The first problem is that you have doubled the amount of memory being used. The second problem (but more importantly) with converting from byte array to String class is that the data may actually change. The JVM will make a best guess as to what type of data is in the byte array and potentially do a conversion based on code page, coded character set identifier and/or encoding. Hence, as your Java programming teacher said, “garbage in, garbage out”.
So, I have decided to cleanup and publish my byte array class for anyone to use. The class is called ByteArray. I really do think outside the box when I name things!!! 🙂
My ByteArray class has 40 methods that can do pretty much anything to a byte array. It can be used with any type of Java application. i.e. stand-alone, JMS, etc.
There are a couple of duplicate methods because of different naming standards in the real world. i.e. getBytes() and toByteArray() methods return the same thing and getLength() and length() methods return the same thing.
Here is a simple tester Java program that shows how to use the various methods:
/**
* Simple program to test the various methods of the ByteArray class.
*
* @author Roger Lacroix, Capitalware Inc.
* @version 1.0.0
* @license Apache 2 License
*/
public class Test_ByteArray
{
public Test_ByteArray()
{
super();
// "Mary had a little lamb, little lamb."
byte[] bData = { 'M', 'a', 'r', 'y', ' ', 'h', 'a', 'd', ' ', 'a', ' ', 'l', 'i', 't', 't', 'l', 'e', ' ', 'l', 'a', 'm', 'b', ',', ' ', 'l', 'i', 't', 't', 'l', 'e', ' ', 'l', 'a', 'm', 'b', '.' };
byte[] bSearch = { 0x68, 0x61, 0x64 }; // had
byte[] bLamb = { 0x6C, 0x61, 0x6D, 0x62 }; // lamb
byte[] bMary = { 'M', 'a', 'r', 'y' };
byte[] bLittle = { 'l', 'i', 't', 't', 'l', 'e' };
byte[] bPetite = { 'p', 'e', 't', 'i', 't', 'e' };
ByteArray ba = new ByteArray(bData);
System.out.println("ba.charAt(20)=" + ba.charAt(20));
System.out.println("ba.byteAt(20)=" + String.format("0x%X", ba.byteAt(20)) + "\n");
System.out.println("new String(ba.concat(bLamb))=" + new String(ba.concat(bLamb)) + "\n");
System.out.println("ba.endsWith(bLamb)=" + ba.endsWith(bLamb) + "\n");
System.out.println("ba.equals(new ByteArray(bLamb))=" + ba.equals(new ByteArray(bLamb)));
System.out.println("ba.equals(new ByteArray(bData))=" + ba.equals(new ByteArray(bData)) + "\n");
System.out.println("new String(ba.getBytes(11))=" + new String(ba.getBytes(11)));
System.out.println("new ByteArray(ba.getBytes(11)).toHex())=" + new ByteArray(ba.getBytes(11)).toHexArray());
System.out.println("ba.getBytes(11,16)=" + new String(ba.getBytes(11, 16)) + "\n");
System.out.println("ba.getLength()=" + ba.getLength());
System.out.println("ba.length()=" + ba.length() + "\n");
System.out.println("ba.indexOf(bSearch)=" + ba.indexOf(bSearch));
System.out.println("ba.indexOf(0x64) [d]=" + ba.indexOf((byte) 0x64));
System.out.println("ba.indexOf(\"lamb\")=" + ba.indexOf("lamb"));
System.out.println("ba.indexOf('l')=" + ba.indexOf('l'));
System.out.println("ba.indexOf('l', 20))=" + ba.indexOf('l', 20) + "\n");
System.out.println("ba.lastIndexOf(bSearch)=" + ba.lastIndexOf(bSearch));
System.out.println("ba.lastIndexOf(0x64) [d]=" + ba.lastIndexOf((byte) 0x64));
System.out.println("ba.lastIndexOf(\"lamb\")=" + ba.lastIndexOf("lamb"));
System.out.println("ba.lastIndexOf('l')=" + ba.lastIndexOf('l'));
System.out.println("ba.lastIndexOf('l', 20))=" + ba.lastIndexOf('l', 20) + "\n");
System.out.println("ba.isEmpty()=" + ba.isEmpty() + "\n");
System.out.println("ba.replace('l','z')=" + new String(ba.replace('l', 'z')));
System.out.println("ba.replace((byte)0x6C,(byte)0x7A)=" + new String(ba.replace((byte) 0x6C, (byte) 0x7A)) + "\n");
System.out.println("ba.replace(bLittle, bPetite)=" + new String(ba.replace(bLittle, bPetite)) + "\n");
byte[] newArray = ba.resize(111);
System.out.println("byte[] newArray = ba.resize(111)");
System.out.println("newArray.length=" + newArray.length + " : new String(newArray)=" + new String(newArray) + "\n");
byte[][] newArray2 = ba.split(' ');
for (int i = 0; i < newArray2.length; i++)
System.out.println("new String(newArray2[" + i + "])=" + new String(newArray2[i]));
System.out.println();
System.out.println("ba.startsWith(bMary)=" + ba.startsWith(bMary));
System.out.println("ba.startsWith(bLamb)=" + ba.startsWith(bLamb));
System.out.println("ba.startsWith(bLamb,18)=" + ba.startsWith(bLamb, 18));
}
public static void main(String[] args)
{
new Test_ByteArray();
}
}
I have generated the JavaDocs for the ByteArray class. I zipped up the JavaDocs, Test_ByteArray.java program and the ByteArray class. You can download the source code from here.
Simply copy the ByteArray class to your utility (or handler) package of your application and then start using it.
Regards,
Roger Lacroix
Capitalware Inc.
The person on StackOverflow made a comment that I was using a static string as my reply message. Humm. Some times people cannot see the forest for the trees.
So, I have updated my sample Java/MQ (i.e. MQTest77.java) in this posting to do the following:
There you go, nothing static about the reply text in the reply message.
Although, this did feel like doing a lab assignment for a Java programming course. 🙂
And of course, if anyone wins the Powerball lottery or any other lottery with my code, I DO expect a 10% cut of the winnings!! 🙂
Regards,
Roger Lacroix
Capitalware Inc.
On StackOverflow, someone asked a question about inhibiting get actions against a queue.
Here is a simple Java/MQ program that will set inhibit or allow for the GET and PUT attributes of a queue.
You can download the source code from here.
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Hashtable;
import com.ibm.mq.MQException;
import com.ibm.mq.MQQueue;
import com.ibm.mq.MQQueueManager;
import com.ibm.mq.constants.CMQC;
/**
* Program Name
* MQTest15
*
* Description
* This java class will connect to a remote queue manager with the
* MQ setting stored in a HashTable and set the queue's get & put attributes to
* either inhibit or allow.
*
* Sample Command Line Parameters
* -m MQA1 -h 127.0.0.1 -p 1414 -c TEST.CHL -q TEST.Q1 -i 0/1 -o 0/1 -u UserID -x Password
*
* @author Roger Lacroix
*/
public class MQTest15
{
private static final SimpleDateFormat LOGGER_TIMESTAMP = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss.SSS");
private Hashtable<String,String> params;
private Hashtable<String,Object> mqht;
private String qMgrName;
private String outputQName;
private boolean getInhibit = false;
private boolean putInhibit = false;
/**
* The constructor
*/
public MQTest15()
{
super();
params = new Hashtable<String,String>();
mqht = new Hashtable<String,Object>();
}
/**
* 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") &&
params.containsKey("-i") && params.containsKey("-o") &&
params.containsKey("-u") && params.containsKey("-x");
if (b)
{
try
{
Integer.parseInt((String) params.get("-p"));
Integer.parseInt((String) params.get("-i"));
Integer.parseInt((String) params.get("-o"));
}
catch (NumberFormatException e)
{
b = false;
}
}
return b;
}
/**
* Extract the command-line parameters and initialize the MQ HashTable.
* @param args
* @throws IllegalArgumentException
*/
private void init(String[] args) throws IllegalArgumentException
{
int port = 1414;
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");
try
{
port = Integer.parseInt((String) params.get("-p"));
}
catch (NumberFormatException e)
{
port = 1414;
}
try
{
int temp = Integer.parseInt((String) params.get("-i"));
if (temp == 1)
getInhibit = true;
}
catch (NumberFormatException e)
{
getInhibit = false;
}
try
{
int temp = Integer.parseInt((String) params.get("-o"));
if (temp == 1)
putInhibit = true;
}
catch (NumberFormatException e)
{
putInhibit = false;
}
mqht.put(CMQC.CHANNEL_PROPERTY, params.get("-c"));
mqht.put(CMQC.HOST_NAME_PROPERTY, params.get("-h"));
mqht.put(CMQC.PORT_PROPERTY, new Integer(port));
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 queue, set the queue's get & put attributes with
* either inhibit or allow, close queue and disconnect.
*
*/
private void doIt()
{
MQQueueManager qMgr = null;
MQQueue queue = null;
int openOptions = CMQC.MQOO_SET + CMQC.MQOO_FAIL_IF_QUIESCING;
try
{
qMgr = new MQQueueManager(qMgrName, mqht);
MQTest15.logger("successfully connected to "+ qMgrName);
queue = qMgr.accessQueue(outputQName, openOptions);
MQTest15.logger("successfully opened "+ outputQName);
if (getInhibit)
{
queue.setInhibitGet(CMQC.MQQA_GET_INHIBITED);
MQTest15.logger("Set inhibited get on queue: " +outputQName);
}
else
{
queue.setInhibitGet(CMQC.MQQA_GET_ALLOWED);
MQTest15.logger("Set allowed get on queue: " +outputQName);
}
if (putInhibit)
{
queue.setInhibitPut(CMQC.MQQA_PUT_INHIBITED);
MQTest15.logger("Set inhibited put on queue: " +outputQName);
}
else
{
queue.setInhibitPut(CMQC.MQQA_PUT_ALLOWED);
MQTest15.logger("Set allowed put on queue: " +outputQName);
}
}
catch (MQException e)
{
MQTest15.logger("CC=" +e.completionCode + " : RC=" + e.reasonCode);
}
finally
{
try
{
if (queue != null)
{
queue.close();
MQTest15.logger("closed: "+ outputQName);
}
}
catch (MQException e)
{
MQTest15.logger("CC=" +e.completionCode + " : RC=" + e.reasonCode);
}
try
{
if (qMgr != null)
{
qMgr.disconnect();
MQTest15.logger("disconnected from "+ qMgrName);
}
}
catch (MQException e)
{
MQTest15.logger("CC=" +e.completionCode + " : RC=" + e.reasonCode);
}
}
}
/**
* 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)
{
MQTest15 write = new MQTest15();
try
{
write.init(args);
write.doIt();
}
catch (IllegalArgumentException e)
{
MQTest15.logger("Usage: java MQTest15 -m QueueManagerName -h host -p port -c channel -q QueueName -i 0/1 -o 0/1 -u UserID -x Password");
System.exit(1);
}
System.exit(0);
}
}
Regards,
Roger Lacroix
Capitalware Inc.
Sometimes people over think a problem and write a complicated solution when really the solution is no different than any other Request/Reply scenario (use case).
On StackOverflow, someone asked a question about sending a reply JMS/MQRFH2 message using the RFH2 header and folder values from the original request message.
The code will copy the RFH2 header and folders from the request message to the reply message.
I did 3 extra things:
(1) Updated the destination queue name in the “jms” folder.
(2) Set the reply message’s Correlation Id to contain the request message’s Message Id.
(3) Used the checksum of the request message’s payload as a seed value for the random number generator that generated Powerball numbers for the reply message’s payload.
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 java.util.Random;
import java.util.zip.CRC32;
import java.util.zip.Checksum;
import com.ibm.mq.MQException;
import com.ibm.mq.MQMessage;
import com.ibm.mq.MQPutMessageOptions;
import com.ibm.mq.MQGetMessageOptions;
import com.ibm.mq.MQQueue;
import com.ibm.mq.MQQueueManager;
import com.ibm.mq.constants.CMQC;
import com.ibm.mq.headers.MQDataException;
import com.ibm.mq.headers.MQRFH2;
/**
* Program Name
* MQTest77
*
* Description
* This java class will connect to a remote queue manager with the MQ setting stored in a HashTable.
* It will get a request MQRFH2 message from an input queue and then send a reply MQRFH2 message.
*
* Sample Command Line Parameters
* -m MQA1 -h 127.0.0.1 -p 1414 -c TEST.CHL -q INPUT.Q1 -o OUTPUT.Q1 -u UserID -x Password
*
* @author Roger Lacroix
*/
public class MQTest77
{
private static final SimpleDateFormat LOGGER_TIMESTAMP = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss.SSS");
private Hashtable<String,String> params;
private Hashtable<String,Object> mqht;
private String qMgrName;
private String inputQName;
private String outputQName;
/**
* The constructor
*/
public MQTest77()
{
super();
params = new Hashtable<String,String>();
mqht = new Hashtable<String,Object>();
}
/**
* 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") && params.containsKey("-o") &&
params.containsKey("-u") && params.containsKey("-x");
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 HashTable.
* @param args
* @throws IllegalArgumentException
*/
private void init(String[] args) throws IllegalArgumentException
{
int port = 1414;
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");
inputQName = (String) params.get("-q");
outputQName = (String) params.get("-o");
try
{
port = Integer.parseInt((String) params.get("-p"));
}
catch (NumberFormatException e)
{
port = 1414;
}
mqht.put(CMQC.CHANNEL_PROPERTY, params.get("-c"));
mqht.put(CMQC.HOST_NAME_PROPERTY, params.get("-h"));
mqht.put(CMQC.PORT_PROPERTY, new Integer(port));
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();
}
}
/**
* This method will do the following:
* 1. Connect
* 2. Open input queue, get a request message, close queue
* 3. Open output queue, send a reply message, close queue
* 4. Disconnect.
*/
private void doIt()
{
MQQueueManager qMgr = null;
try
{
qMgr = new MQQueueManager(qMgrName, mqht);
MQTest77.logger("successfully connected to "+ qMgrName);
MQMessage requestMsg = getRequestMsg(qMgr);
if (requestMsg != null)
{
ResponseStuff rs = doSomeLogic(requestMsg);
if (rs != null)
sendReplyMsg(qMgr, rs);
}
}
catch (MQException e)
{
MQTest77.logger("CC=" +e.completionCode + " : RC=" + e.reasonCode);
}
finally
{
try
{
if (qMgr != null)
{
qMgr.disconnect();
MQTest77.logger("disconnected from "+ qMgrName);
}
}
catch (MQException e)
{
MQTest77.logger("CC=" +e.completionCode + " : RC=" + e.reasonCode);
}
}
}
/**
* Open the input queue, get a message, close queue.
* @param qMgr
* @return requestMsg
*/
private MQMessage getRequestMsg(MQQueueManager qMgr)
{
MQQueue queue = null;
int openOptions = CMQC.MQOO_INPUT_AS_Q_DEF + CMQC.MQOO_INQUIRE + CMQC.MQOO_FAIL_IF_QUIESCING;
MQGetMessageOptions gmo = new MQGetMessageOptions();
gmo.options = CMQC.MQGMO_PROPERTIES_FORCE_MQRFH2 + CMQC.MQGMO_FAIL_IF_QUIESCING + CMQC.MQGMO_NO_WAIT;
MQMessage requestMsg = null;
try
{
queue = qMgr.accessQueue(inputQName, openOptions);
MQTest77.logger("successfully opened "+ inputQName);
requestMsg = new MQMessage();
requestMsg.messageId = CMQC.MQMI_NONE;
requestMsg.correlationId = CMQC.MQCI_NONE;
// get the message on the queue
queue.get(requestMsg, gmo);
}
catch (MQException e)
{
MQTest77.logger("CC=" +e.completionCode + " : RC=" + e.reasonCode);
if ( (e.completionCode == CMQC.MQCC_FAILED) && (e.reasonCode == CMQC.MQRC_NO_MSG_AVAILABLE) )
{
MQTest77.logger("No messages on the queue: " + inputQName);
requestMsg = null; // no message on queue
}
}
finally
{
try
{
if (queue != null)
{
queue.close();
MQTest77.logger("closed input: "+ inputQName);
}
}
catch (MQException e)
{
MQTest77.logger("CC=" +e.completionCode + " : RC=" + e.reasonCode);
}
}
return requestMsg;
}
/**
* This is the method where you would normally do business logic stuff.
* This code will we will take the checksum of the request
* message and use the value as a seed to the random number generator
* to that will generate numbers for the next PowerBall lottery!!
*
* @param requestMsg
*/
private ResponseStuff doSomeLogic(MQMessage requestMsg)
{
SimpleDateFormat date = new SimpleDateFormat("yyyy/MM/dd");
ResponseStuff rs = new ResponseStuff();
byte[] msgInBytes;
try
{
rs.setRequestMsgId(requestMsg.messageId);
requestMsg.seek(0); // Important: put the cursor at the beginning of the message.
MQRFH2 requestRFH2 = new MQRFH2(requestMsg);
// Save the RFH2 Values
rs.setRfh2(extractRFH2Values(requestRFH2));
if (CMQC.MQFMT_STRING.equals(requestRFH2.getFormat()))
{
String msgStr = requestMsg.readStringOfByteLength(requestMsg.getDataLength());
msgInBytes = msgStr.getBytes();
}
else
{
msgInBytes = new byte[requestMsg.getDataLength()];
requestMsg.readFully(msgInBytes);
}
/**
* Now do something with the request message payload.
* i.e. process msgStr
*
* But we are going to generate PowerBall lottery numbers.
*
*/
/* Apply checksum to the message payload */
Checksum checksum = new CRC32();
checksum.update(msgInBytes, 0, msgInBytes.length);
// get the current checksum value & use it as a seed value.
Random random = new Random(checksum.getValue());
StringBuffer sb = new StringBuffer();
sb.append("For today, ");
sb.append(date.format(new Date()));
sb.append(" your Powerball numbers are: ");
for (int i=0; i < 4; i++)
sb.append(random.nextInt(69)+", ");
sb.append(random.nextInt(69)+" ");
sb.append("and your power ball is ");
sb.append(random.nextInt(26));
rs.setResponseText(sb.toString());
}
catch (IOException e)
{
MQTest77.logger("IOException:" +e.getLocalizedMessage());
}
catch (MQDataException e)
{
MQTest77.logger("CC=" +e.completionCode + " : RC=" + e.reasonCode);
}
return rs;
}
/**
* Extract the MQRFH2 values we will need.
* @param requestRFH2
* @return rfh2
*/
private MQRFH2 extractRFH2Values(MQRFH2 requestRFH2)
{
MQRFH2 replyRFH2 = null;
try
{
// Set the RFH2 Values
replyRFH2 = new MQRFH2();
replyRFH2.setEncoding(requestRFH2.getEncoding());
replyRFH2.setCodedCharSetId(requestRFH2.getCodedCharSetId());
replyRFH2.setFormat(requestRFH2.getFormat());
replyRFH2.setFlags(requestRFH2.getFlags());
replyRFH2.setNameValueCCSID(requestRFH2.getNameValueCCSID());
String[] folders = requestRFH2.getFolderStrings();
for (int i=0; i < folders.length; i++)
{
if ( (folders[i].startsWith("<jms>")) && (folders[i].contains("<Dst>")) && (folders[i].contains("</Dst>")) )
{
int prefix = folders[i].indexOf("<Dst>");
int suffix = folders[i].indexOf("</Dst>");
// Set the destination to the output queue name.
folders[i] = folders[i].substring(0, prefix) + "<Dst>queue:///"+outputQName+"</Dst>" + folders[i].substring(suffix+6);
break;
}
}
replyRFH2.setFolderStrings(folders);
}
catch (IOException e)
{
MQTest77.logger("IOException:" +e.getLocalizedMessage());
}
return replyRFH2;
}
/**
* Open output queue, write a message, close queue.
* @param qMgr
* @param requestMsg
*/
private void sendReplyMsg(MQQueueManager qMgr, ResponseStuff rs)
{
MQQueue queue = null;
int openOptions = CMQC.MQOO_OUTPUT + CMQC.MQOO_FAIL_IF_QUIESCING;
MQPutMessageOptions pmo = new MQPutMessageOptions();
try
{
queue = qMgr.accessQueue(outputQName, openOptions);
MQTest77.logger("successfully opened "+ outputQName);
MQMessage replymsg = new MQMessage();
// Set the RFH2 Values
MQRFH2 replyRFH2 = new MQRFH2();
replyRFH2.setEncoding(rs.getRfh2().getEncoding());
replyRFH2.setCodedCharSetId(rs.getRfh2().getCodedCharSetId());
replyRFH2.setFormat(rs.getRfh2().getFormat());
replyRFH2.setFlags(rs.getRfh2().getFlags());
replyRFH2.setNameValueCCSID(rs.getRfh2().getNameValueCCSID());
replyRFH2.setFolderStrings(rs.getRfh2().getFolderStrings());
// Set the MQRFH2 structure to the message
replyRFH2.write(replymsg);
// Write message data
replymsg.writeString(rs.getResponseText());
// Set MQMD values
replymsg.messageId = CMQC.MQMI_NONE;
/* set the reply's Correl Id to be the request message's Msg id */
replymsg.correlationId = rs.getRequestMsgId();
replymsg.messageType = CMQC.MQMT_DATAGRAM;
// IMPORTANT: Set the format to MQRFH2 aka JMS Message.
replymsg.format = CMQC.MQFMT_RF_HEADER_2;
// put the message on the queue
queue.put(replymsg, pmo);
MQTest77.logger("Message Data>>>" + rs.getResponseText());
}
catch (MQException e)
{
MQTest77.logger("CC=" +e.completionCode + " : RC=" + e.reasonCode);
}
catch (IOException e)
{
MQTest77.logger("IOException:" +e.getLocalizedMessage());
}
finally
{
try
{
if (queue != null)
{
queue.close();
MQTest77.logger("closed output: "+ outputQName);
}
}
catch (MQException e)
{
MQTest77.logger("CC=" +e.completionCode + " : RC=" + e.reasonCode);
}
}
}
/**
* 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)
{
MQTest77 write = new MQTest77();
try
{
write.init(args);
write.doIt();
}
catch (IllegalArgumentException e)
{
MQTest77.logger("Usage: java MQTest77 -m QueueManagerName -h host -p port -c channel -q InputQueueName -o OutputQueueName-u UserID -x Password");
System.exit(1);
}
System.exit(0);
}
/**
* This class will hold the information to be used in the reply message.
*/
class ResponseStuff
{
private MQRFH2 rfh2;
private String responseText;
private byte[] requestMsgId;
/**
* The constructor
*/
public ResponseStuff()
{
super();
rfh2 = new MQRFH2();
}
public MQRFH2 getRfh2()
{
return rfh2;
}
public void setRfh2(MQRFH2 rfh2)
{
this.rfh2 = rfh2;
}
public String getResponseText()
{
return responseText;
}
public void setResponseText(String responseText)
{
this.responseText = responseText;
}
public byte[] getRequestMsgId()
{
return requestMsgId;
}
public void setRequestMsgId(byte[] requestMsgId)
{
this.requestMsgId = requestMsgId;
}
}
}
Regards,
Roger Lacroix
Capitalware Inc.
IBM has just released Fix Pack 5.3.1.16 for WebSphere MQ for HPE NonStop:
https://www.ibm.com/support/docview.wss?uid=swg1IT29752
Regards,
Roger Lacroix
Capitalware Inc.
A bug was discovered in Capitalware’s framework subroutine for removing trailing blanks (spaces) from a variable. If the contents of the variable contained only blanks then the code miscalculated the length by 1. This bug affects all commercial and “Licensed as Free” products.
To receive updates to the commercial products, please send an email to support@capitalware.com
The updates for the “Licensed as Free” products have been posted to Capitalware’s web site, so you can download them immediately.
Regards,
Roger Lacroix
Capitalware Inc.
IBM has just released Fix Pack 8.0.0.14 for IBM MQ
https://www.ibm.com/support/pages/node/1282120
Regards,
Roger Lacroix
Capitalware Inc.