In order to compile and run this program, PCF package (MS0B) is needed and can be downloaded from IBM. You will also need "com.ibm.mq.jar" and IBM's "j2ee.jar". They can be found from IBM's WSAD or RAD IDE development tools.
/* * blog/javaclue/ibmmq/MessageAgeMonitor.java * * Copyright (C) 2009 JackW * * This program is free software: you can redistribute it and/or modify it under the terms of the * GNU Lesser General Public License as published by the Free Software Foundation, either version 3 * of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License along with this library. * If not, see <http://www.gnu.org/licenses/>. */ package blog.javaclue.ibmmq; import java.util.GregorianCalendar; import org.apache.log4j.Logger; import com.ibm.mq.MQC; import com.ibm.mq.MQEnvironment; import com.ibm.mq.MQException; import com.ibm.mq.MQGetMessageOptions; import com.ibm.mq.MQMessage; import com.ibm.mq.MQQueue; import com.ibm.mq.MQQueueManager; /** * Simple message age monitor program that uses IBM MQ Java to read PCF-format * messages from a queue. */ public class MessageAgeMonitor implements Runnable { protected static Logger logger = Logger.getLogger(MessageAgeMonitor.class); protected static boolean isDebugEnabled = logger.isDebugEnabled(); final private String qmgrName; final private String host; final private int port; final private String queueName; final private int alertAge; // in seconds final private String channel; final static int Polling_Freq = 30 * 1000; // 30 seconds MessageAgeMonitor(String qmgrName, String host, int port, String queueName, String channel, int alertAge) { this.qmgrName = qmgrName; this.host = host; this.port = port; this.channel = channel; this.queueName = queueName; this.alertAge = alertAge; } public void run() { if (isDebugEnabled) logger.debug("Starting Message Age monitor for " + queueName + "..."); while (true) { checkAge(); try { Thread.sleep(Polling_Freq); // sleep for 30 seconds } catch (InterruptedException e) { logger.info("The monitor has been interrupted, exit..."); break; } } } private void checkAge() { MQQueueManager qm = null; MQQueue queue = null; if (isDebugEnabled) { logger.debug("Connecting to " + qmgrName + " at " + host + ":" + port + " over " + channel); } try { // Turn off unnecessary output before we start MQEnvironment.disableTracing (); MQException.log = null; MQEnvironment.hostname = host; MQEnvironment.port = port; MQEnvironment.channel = channel; qm = new MQQueueManager (""); queue = qm.accessQueue (queueName, MQC.MQOO_BROWSE | MQC.MQOO_FAIL_IF_QUIESCING); MQMessage message = new MQMessage (); MQGetMessageOptions gmo = new MQGetMessageOptions (); gmo.options = MQC.MQGMO_BROWSE_FIRST | MQC.MQGMO_NO_WAIT | MQC.MQGMO_CONVERT; message.messageId = null; message.correlationId = null; queue.get (message, gmo); // get message put date time GregorianCalendar cal = message.putDateTime; long ageInMillis = new java.util.Date().getTime() - cal.getTime().getTime(); int ageInSeconds = (int) ageInMillis/1000; if (isDebugEnabled) logger.debug("Put Date: " + cal.getTime() + " age in seconds: " + ageInSeconds); if (ageInSeconds > alertAge) { logger.info(qmgrName + "/" + queueName + " age = " + ageInSeconds + ", exceeded alert threshold: " + alertAge); // XXX: add your code here to send out alert } } catch (MQException mqe) { if (mqe.reasonCode == MQException.MQRC_NO_MSG_AVAILABLE) { if (isDebugEnabled) { logger.debug("Queue " + qmgrName + "/" + queueName + " is empty."); } } else { logger.error("MQException caught", mqe); } } finally { if (queue != null && queue.isOpen()) { try { queue.close(); } catch (Exception e) { logger.error("Exception caught during queue.close()", e); } } if (qm != null) { if (qm.isOpen()) { try { qm.close(); } catch (Exception e) { logger.error("Exception caught during qm.close()", e); } } if (qm.isConnected()) { try { qm.disconnect(); } catch (Exception e) { logger.error("Exception caught during qm.disconnect()", e); } } } } } public static void main (String [] args) { String qmgrName = "QMGR"; String host = "localhost"; int port = 1450; String channel = "SYSTEM.DEF.SVRCONN"; String queueName = "TEST_QUEUE"; MessageAgeMonitor monitor = new MessageAgeMonitor(qmgrName, host, port, queueName, channel, 60); new Thread(monitor).start(); } }
This post is probably where I got the most useful information for my research. Thanks for posting, maybe we can see more on this.
ReplyDeleteAre you aware of any other websites on this
IBM-MQ WEBSPHERE Online training
Two improvements suggested:
ReplyDelete1. Do a zero-length get to fetch only the MQMD
gmo.options |= MQConstants.MQGMO_ACCEPT_TRUNCATED_MSG;
get (message, gmo , 0 ); // zero length message
catch-and-ignore
MQConstants.MQRC_TRUNCATED_MSG_ACCEPTED
the .get() still worked even if it throws an exception.
2. check cal for nullness. I've run into a case where someone PUT a no-Context message and the MQMD PUTDATE and PUTTIME being blank result in a null GregorianCalendar