Skip to content

Instantly share code, notes, and snippets.

@ibmmqmet
Last active October 6, 2022 06:17
Show Gist options
  • Save ibmmqmet/a20a2eb13978448ae4d65f4865b444b3 to your computer and use it in GitHub Desktop.
Save ibmmqmet/a20a2eb13978448ae4d65f4865b444b3 to your computer and use it in GitHub Desktop.
Building an MQ RFH2 structure - see https://marketaylor.synology.me/?p=1335
import java.util.Enumeration;
import javax.jms.Connection;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.Queue;
import javax.jms.QueueBrowser;
import javax.jms.Session;
import javax.jms.TextMessage;
import com.ibm.msg.client.jms.JmsConnectionFactory;
import com.ibm.msg.client.jms.JmsFactoryFactory;
import com.ibm.msg.client.wmq.WMQConstants;
/**
* A JMS queue browser application that looks at all available messages on the named queue, without
* removing them, in the order they would be received by a consumer application.
*
* Tip: A browser is not applicable for topics.
*
* Notes:
*
* API type: IBM JMS API (v1.1, unified domain)
*
* Messaging domain: Point-to-point
*
* Provider type: IBM MQ
*
* Connection mode: Client connection
*
* JNDI in use: No
*
* Usage:
*
* JmsBrowser -m queueManagerName -d queueName [-h host -p port -l channel]
*
* for example:
*
* JmsBrowser -m QM1 -d Q1
*
* JmsBrowser -m QM1 -d Q1 -h localhost -p 1414
*/
public class JmsBrowser {
private static String host = "localhost";
private static int port = 1414;
private static String channel = "SYSTEM.DEF.SVRCONN";
private static String queueManagerName = null;
private static String queueName = null;
private static boolean clientTransport = false;
// System exit status value (assume unset value to be 1)
private static int status = 1;
/**
* Main method
*
* @param args
*/
public static void main(String[] args) {
String prop,val;
// Parse the arguments
parseArgs(args);
// Variables
Connection connection = null;
Session session = null;
Queue destination = null;
QueueBrowser browser = null;
System.out.println("JmsBrowser - starts here");
System.out.println("************************");
try {
// Create a connection factory
JmsFactoryFactory ff = JmsFactoryFactory.getInstance(WMQConstants.WMQ_PROVIDER);
JmsConnectionFactory cf = ff.createConnectionFactory();
// Set the properties
cf.setStringProperty(WMQConstants.WMQ_HOST_NAME, host);
cf.setIntProperty(WMQConstants.WMQ_PORT, port);
cf.setStringProperty(WMQConstants.WMQ_CHANNEL, channel);
if (clientTransport) {
cf.setIntProperty(WMQConstants.WMQ_CONNECTION_MODE, WMQConstants.WMQ_CM_CLIENT);
}
else {
cf.setIntProperty(WMQConstants.WMQ_CONNECTION_MODE, WMQConstants.WMQ_CM_BINDINGS);
}
cf.setStringProperty(WMQConstants.WMQ_QUEUE_MANAGER, queueManagerName);
// Create JMS objects
connection = cf.createConnection();
session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
destination = session.createQueue(queueName);
browser = session.createBrowser(destination);
// Start the connection
connection.start();
// And, browse the message
Enumeration<?> messages = browser.getEnumeration();
int count = 0;
TextMessage current;
while (messages.hasMoreElements()) {
Message m = (Message)messages.nextElement();
if (m instanceof TextMessage) {
current = (TextMessage) m;
System.out.println("\nMessage " + ++count + ":\n");
@SuppressWarnings("unchecked")
Enumeration<String> props = (Enumeration<String>)current.getPropertyNames();
System.out.printf("Properties:\n");
while (props.hasMoreElements()) {
prop = props.nextElement();
val = current.getStringProperty(prop);
System.out.printf(" Prop: %-20.20s Val:%s\n",prop,val);
}
System.out.printf("Body: \n <%s>\n",current.getText());
} else {
System.out.printf("Message is not a TextMessage\n");
}
}
System.out.println("\nNo more messages\n");
recordSuccess();
}
catch (JMSException jmsex) {
recordFailure(jmsex);
}
finally {
if (browser != null) {
try {
browser.close();
}
catch (JMSException jmsex) {
System.out.println("Browser could not be closed.");
recordFailure(jmsex);
}
}
if (session != null) {
try {
session.close();
}
catch (JMSException jmsex) {
System.out.println("Session could not be closed.");
recordFailure(jmsex);
}
}
if (connection != null) {
try {
connection.close();
}
catch (JMSException jmsex) {
System.out.println("Connection could not be closed.");
recordFailure(jmsex);
}
}
}
System.exit(status);
return;
} // end main()
/**
* Process a JMSException and any associated inner exceptions.
*
* @param jmsex
*/
private static void processJMSException(JMSException jmsex) {
System.out.println(jmsex);
Throwable innerException = jmsex.getLinkedException();
if (innerException != null) {
System.out.println("Inner exception(s):");
}
while (innerException != null) {
System.out.println(innerException);
innerException = innerException.getCause();
}
return;
}
/**
* Record this run as successful.
*/
private static void recordSuccess() {
System.out.println("SUCCESS");
status = 0;
return;
}
/**
* Record this run as failure.
*
* @param ex
*/
private static void recordFailure(Exception ex) {
if (ex != null) {
if (ex instanceof JMSException) {
processJMSException((JMSException) ex);
} else {
System.out.println(ex);
}
}
System.out.println("FAILURE");
status = -1;
return;
}
/**
* Parse user supplied arguments.
*
* @param args
*/
private static void parseArgs(String[] args) {
try {
int length = args.length;
//for (int i=1;i<args.length;i++)
// System.out.printf("Arg:%d Val:%s\n",i,args[i]);
if (length == 0) {
throw new IllegalArgumentException("No arguments! Mandatory arguments must be specified.");
}
if ((length % 2) != 0) {
throw new IllegalArgumentException("Incorrect number of arguments!");
}
int i = 0;
while (i < length) {
if ((args[i]).charAt(0) != '-') {
throw new IllegalArgumentException("Expected a '-' character next: " + args[i]);
}
char opt = (args[i]).toLowerCase().charAt(1);
switch (opt) {
case 'h' :
host = args[++i];
clientTransport = true;
break;
case 'p' :
port = Integer.parseInt(args[++i]);
break;
case 'l' :
channel = args[++i];
break;
case 'm' :
queueManagerName = args[++i];
break;
case 'd' :
queueName = args[++i];
break;
default : {
throw new IllegalArgumentException("Unknown argument: " + opt);
}
}
++i;
}
if (queueManagerName == null) {
throw new IllegalArgumentException("A queueManager name must be specified.");
}
if (queueName == null) {
throw new IllegalArgumentException("A queue name must be specified.");
}
}
catch (Exception e) {
System.out.println(e.getMessage());
printUsage();
System.exit(-1);
}
return;
}
/**
* Display usage help.
*/
private static void printUsage() {
System.out.println("\nUsage:");
System.out.println("JmsBrowser -m queueManagerName -d queueName [-h host -p port -l channel]");
return;
}
} // end class
all: rfh2put JmsBrowser.class
rfh2put: rfh2put.c
cc -o $@ rfh2put.c -I/opt/mqm/inc -L/opt/mqm/lib64 -lmqm_r
JmsBrowser.class: JmsBrowser.java
javac -cp /opt/mqm/java/lib/com.ibm.mq.allclient.jar JmsBrowser.java
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <cmqc.h>
#include <cmqstrc.h>
#ifndef RoundTo4
#define RoundTo4(u) (((u)+ (( 4-((u)%4))%4)))
#endif
int main(int argc, char **argv)
{
MQOD od = {MQOD_DEFAULT};
MQMD md = {MQMD_DEFAULT};
MQPMO pmo = {MQPMO_DEFAULT};
MQRFH2 rfh2Header = {MQRFH2_DEFAULT};
MQHCONN hConn;
MQHOBJ hObj;
MQLONG openOptions;
MQLONG CC;
MQLONG RC;
MQLONG messageLen;
MQLONG folderLen; // this must be a 4-byte integer
char qMgrName[50];
char buffer[65535] = {0};
char inputLine[BUFSIZ] = {0};
int offset;
char *body;
char *folder;
int s;
if (argc < 2)
{
printf("Required parameter missing - queue name\n");
exit(1);
}
qMgrName[0] = 0;
if (argc > 2)
{
strncpy(qMgrName, argv[2], (size_t)MQ_Q_MGR_NAME_LENGTH);
}
MQCONN(qMgrName, &hConn, &CC, &RC);
if (CC == MQCC_FAILED)
{
printf("MQCONNX ended with RC code %d\n", RC);
exit((int)RC );
}
strncpy(od.ObjectName, argv[1], (size_t)MQ_Q_NAME_LENGTH);
printf("target queue is %s\n", od.ObjectName);
openOptions = MQOO_OUTPUT | MQOO_FAIL_IF_QUIESCING;
MQOPEN(hConn, &od, openOptions, &hObj, &CC, &RC);
if (RC != MQRC_NONE)
{
printf("MQOPEN ended with RC code %d\n", RC);
exit(1);
}
printf("Enter folder strings (empty string ends):\n");
offset = MQRFH_STRUC_LENGTH_FIXED_2; // 36
do
{
memset(inputLine,0,sizeof(inputLine));
folder = fgets(inputLine,sizeof(inputLine)-1,stdin);
// Remove trailing LF
if (folder[strlen(folder)-1] == '\n')
{
folder[strlen(folder) -1] = 0;
}
folderLen = RoundTo4(strlen(folder)); // Length must be multiple of 4.
if (folderLen)
{
// NameValueLength - how long is the adjacent folder
memcpy(&buffer[offset],&folderLen,sizeof(folderLen));
offset += sizeof(folderLen);
// NameValueData - copy in the actual length read from input, not the rounded value.
// But bump the offset by the rounded amount, ready for next element. Gaps caused by
// rounding up are ignored.
memcpy(&buffer[offset],folder,strlen(folder));
offset += folderLen;
}
} while(folderLen);
// Fill out the RFH2 header block
memcpy(rfh2Header.Format, MQFMT_STRING,(size_t)MQ_FORMAT_LENGTH); // Message body will be a string
rfh2Header.CodedCharSetId = MQCCSI_INHERIT;
rfh2Header.StrucLength = offset; // We now know the complete length, including the fixed header
rfh2Header.NameValueCCSID = 1208L;
memcpy(buffer,&rfh2Header,sizeof(rfh2Header)); // Copy the header into the start of the buffer now we know lengths
// And tell the MQMD that there is an RFH2
memcpy(md.Format, MQFMT_RF_HEADER_2, (size_t)MQ_FORMAT_LENGTH);
// Message body is a single input string
printf("Enter body string:\n");
memset(inputLine,0,sizeof(inputLine));
body = fgets(inputLine,sizeof(inputLine)-1,stdin);
s = strlen(body);
if (body[s-1] == '\n')
{
body[s-1] = 0;
s--;
}
memcpy(&buffer[offset],body,s);
messageLen = offset + s;
pmo.Options = MQPMO_NO_SYNCPOINT | MQPMO_FAIL_IF_QUIESCING;
MQPUT(hConn, hObj, &md, &pmo, messageLen, buffer, &CC,&RC);
if (RC != MQRC_NONE)
{
printf("MQPUT ended with RC code %s [%d]\n", MQRC_STR(RC),RC);
}
MQCLOSE(hConn, &hObj, 0, &CC, &RC);
MQDISC(&hConn, &CC, &RC);
return(0);
}
#!/bin/sh
make -f Makefile
if [ $? -ne 0 ]
then
exit 1
fi
q="DEV.QUEUE.1"
qm="QM1"
. setmqenv -m $qm -k
export PATH=$PATH:/opt/mqm/samp/bin
echo "CLEAR QL($q)" | runmqsc $qm
# Message body
msg="Hello at `date`"
# These strings are complete folders
f1="<myfolder content='properties'><colour>red</colour></myfolder>"
f1a="<myfolder2'><colour>yellow</colour></myfolder2>" # Can use this to see behaviour when not marked as properties
f2="<usr><colour>green</colour><size>large</size></usr>"
cat << EOF | rfh2put $q $qm
$f1
$f2
$msg
EOF
# Get the message showing raw RFH2
amqsbcg $q $qm 3
# Get the message showing properties
amqsbcg $q $qm 1
# Get the message removing RFH2 entirely
amqsbcg $q $qm 2
echo
java -cp /opt/mqm/java/lib/com.ibm.mq.allclient.jar:. JmsBrowser -m $qm -d $q -h localhost -l SYSTEM.DEF.SVRCONN | grep -v "Prop: JMS"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment