Enhancement to MQ Auditor

Capitalware has an MQ solution called MQ Auditor.

MQ Auditor is a solution that allows a company to audit/track all MQ API calls performed by MQ applications that are connected to a queue manager.

I have enhanced MQ Auditor with a new keyword called ExcludePCFMessages. It has a default value of ‘N’. When it is set to ‘Y’, MQ Auditor will exclude messages with a MQMD format value of either MQADMIN or MQEVENT.

I have completed a wide variety of tests and everything looks good.

If anyone would like to test out the latest release then send the email to support@capitalware.com

Regards,
Roger Lacroix
Capitalware Inc.

Capitalware, IBM i (OS/400), IBM MQ, Linux, MQ Auditor, Unix, Windows Comments Off on Enhancement to MQ Auditor

Capitalware Product Advisory – MQ Auditor

A bug was discovered in Capitalware’s MQ Auditor related to PCF response message for the PCF MQCMD_INQUIRE_Q_NAMES command. The PCF response message to the MQCMD_INQUIRE_Q_NAMES command has 2 parts: list of queues and list of queue types. To format the queue types (i.e. local, alias, etc.), the code used a 1024 byte static array. The formatting of each queue type is a single digit number followed by a colon “:”. Hence, it means 2 bytes are used per queue type and that a maximum of 512 queues (1024/2) can be processed. If the PCF MQCMD_INQUIRE_Q_NAMES command requests data for more than 512 queues then MQ Auditor crashes and MQ generates an FDC.

I have updated the code to use a dynamic buffer rather than a static array.

Note: If you have excluded the “AMQ.*” temporary dynamic queues in the IniFile then MQ Auditor will not process PCF response messages. Hence, the issue will not affect you.
i.e.

UseExcludeQueues = Y           
ExcludeQueues = AMQ.*

To receive the latest release of MQ Auditor, please send an email to support@capitalware.com

Regards,
Roger Lacroix
Capitalware Inc.

Capitalware, IBM i (OS/400), IBM MQ, Linux, MQ Auditor, Unix, Windows Comments Off on Capitalware Product Advisory – MQ Auditor

IBM MQ Knowledge Center Icons

IBM keeps added more and more icons in the MQ Knowledge Center to highlight which platforms and/or versions that a particular feature is supported on. You can find a complete list and explanation of the icons on the following MQ Knowledge Center page:
https://www.ibm.com/docs/en/ibm-mq/latest?topic=mq-release-platform-icons-in-product-documentation

Regards,
Roger Lacroix
Capitalware Inc.

Education, HPE NonStop, IBM i (OS/400), IBM MQ, IBM MQ Appliance, Linux, macOS (Mac OS X), Unix, Windows, z/OS Comments Off on IBM MQ Knowledge Center Icons

IBM MQ Fix Pack 9.1.0.8 Released

IBM has just released Fix Pack 9.1.0.8 for IBM MQ V9.1 LTS:
https://www.ibm.com/support/pages/downloading-ibm-mq-9108

Regards,
Roger Lacroix
Capitalware Inc.

Fix Packs for MQ, IBM i (OS/400), IBM MQ, IBM MQ Appliance, Linux, Unix, Windows Comments Off on IBM MQ Fix Pack 9.1.0.8 Released

Microsoft OpenJDK Builds

I had to rub my eyes and read the announcement twice!! 🙂

Microsoft announces the general availability of Microsoft Build of OpenJDK:
https://devblogs.microsoft.com/java/announcing-general-availability-of-microsoft-build-of-openjdk/

Java at Microsoft spans from Azure to Minecraft, across SQL Server to Visual Studio Code, LinkedIn and beyond! We use more Java than one can imagine.

The Microsoft Build of OpenJDK is a new no-cost long-term supported distribution and Microsoft’s new way to collaborate and contribute to the Java ecosystem.

I downloaded JDK 11 from Microsoft, tested with a variety of MQ/Java programs this afternoon and everything worked as expected.

Microsoft is offering OpenJDK builds for Windows (of course), Linux and macOS (Mac OS X). There are early access builds for Linux on ARM64 and Windows on ARM64.

20 years later, Microsoft is fully supporting Java. Either the world is upside down or just gone mad. 🙂

Regards,
Roger Lacroix
Capitalware Inc.

Java, JMS, Linux, macOS (Mac OS X), Open Source, Programming, Windows Comments Off on Microsoft OpenJDK Builds

Java MQ Code to Clear a Queue of Messages

If you have done the following runmqsc command to clear a queue:

CLEAR QLOCAL( {QueueName} )

And you wanted to do the same thing via a program, here is a fully functioning Java MQ example that will connect to a remote queue manager, issue a PCF “Clear Queue” command, get the PCF response messages and output if the PCF command was successful or not. You can download the source code from here.

Note: The PCF “Clear Queue” command will fail if an application has the queue open.

For more information about the PCF “Clear Queue” command, go to MQ KnowLedge Center 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.MQQueueManager;
import com.ibm.mq.constants.CMQC;
import com.ibm.mq.constants.CMQCFC;
import com.ibm.mq.constants.MQConstants;
import com.ibm.mq.headers.MQDataException;
import com.ibm.mq.headers.pcf.PCFMessage;
import com.ibm.mq.headers.pcf.PCFMessageAgent;

/**
 * Program Name
 *  MQClearQueue01
 *
 * Description
 *  This java class issues a PCF "Clear Q" command for a queue to delete all messages 
 *  in the queue of a remote queue manager.
 *    
 *  Note: The PCF "Clear Q" command will fail if an application has the queue open.
 *
 * Sample Command Line Parameters
 *  -m MQA1 -h 127.0.0.1 -p 1414 -c TEST.CHL -q TEST.Q1 -u UserID -x Password
 *
 * @author Roger Lacroix
 */
public class MQClearQueue01
{
   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;

   public MQClearQueue01()
   {
      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("-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())
      {
         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();
      }
   }

   /**
    * Handle connecting to the queue manager, issuing PCF command then
    * looping through PCF response messages and disconnecting from
    * the queue manager.
    */
   private void doPCF()
   {
      MQQueueManager  qMgr   = null;
      PCFMessageAgent agent  = null;
      PCFMessage   request   = null;
      PCFMessage[] responses = null;
      String qMgrName  = (String) params.get("-m");
      String queueName = (String) params.get("-q");

      try
      {
         qMgr = new MQQueueManager(qMgrName, mqht);
         MQClearQueue01.logger("successfully connected to "+ qMgrName);

         agent = new PCFMessageAgent(qMgr);
         MQClearQueue01.logger("successfully created agent");

         // https://www.ibm.com/docs/en/ibm-mq/latest?topic=formats-clear-queue
         request = new PCFMessage(CMQCFC.MQCMD_CLEAR_Q);

         request.addParameter(CMQC.MQCA_Q_NAME, queueName);

         responses = agent.send(request);

         MQClearQueue01.logger("responses.length="+responses.length);

         for (int i = 0; i < responses.length; i++)
         {
            if ((responses[i]).getCompCode() == CMQC.MQCC_OK)
               MQClearQueue01.logger("Successfully cleared queue '"+queueName+"' of messages.");
            else
               MQClearQueue01.logger("Error: Failed to clear queue '"+queueName+"' of messages.");
         }
      }
      catch (MQException e)
      {
         MQClearQueue01.logger("CC=" +e.completionCode + " : RC=" + e.reasonCode + " [" + MQConstants.lookup(e.reasonCode, "MQRC_.*") + "]");
      }
      catch (IOException e)
      {
         MQClearQueue01.logger("IOException:" +e.getLocalizedMessage());
      }
      catch (MQDataException e)
      {
         if ( (e.completionCode == CMQC.MQCC_FAILED) && (e.reasonCode == CMQCFC.MQRCCF_OBJECT_OPEN) )
            MQClearQueue01.logger("Error: Failed to clear queue '"+queueName+"' of messages. An application has the queue open.");
         else
            MQClearQueue01.logger("CC=" +e.completionCode + " : RC=" + e.reasonCode + " [" + MQConstants.lookup(e.reasonCode, "MQRC_.*") + "]");
      }
      finally
      {
         try
         {
            if (agent != null)
            {
               agent.disconnect();
               MQClearQueue01.logger("disconnected from agent");
            }
         }
         catch (MQDataException e)
         {
            MQClearQueue01.logger("CC=" +e.completionCode + " : RC=" + e.reasonCode + " [" + MQConstants.lookup(e.reasonCode, "MQRC_.*") + "]");
         }

         try
         {
            if (qMgr != null)
            {
               qMgr.disconnect();
               MQClearQueue01.logger("disconnected from "+ qMgrName);
            }
         }
         catch (MQException e)
         {
            MQClearQueue01.logger("CC=" +e.completionCode + " : RC=" + e.reasonCode + " [" + MQConstants.lookup(e.reasonCode, "MQRC_.*") + "]");
         }
      }
   }

   /**
    * 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);
   }

   public static void main(String[] args)
   {
      MQClearQueue01 mqcq = new MQClearQueue01();

      try
      {
         mqcq.init(args);
         mqcq.doPCF();
      }
      catch (IllegalArgumentException e)
      {
         MQClearQueue01.logger("Usage: java MQClearQueue01 -m QueueManagerName -h host -p port -c channel -q QueueName -u UserID -x Password");
         System.exit(1);
      }

      System.exit(0);
   }
}

Regards,
Roger Lacroix
Capitalware Inc.

HPE NonStop, IBM i (OS/400), IBM MQ, IBM MQ Appliance, Java, Linux, macOS (Mac OS X), Open Source, PCF, Programming, Raspberry Pi, Unix, Windows Comments Off on Java MQ Code to Clear a Queue of Messages

Updates to My ByteArray Class

Last year, I posted a blog item called Java’s Missing Byte Array Class regarding the missing ByteArray class in Java and I published my ByteArray class for all to use.

I have fixed a bug in the getBytes method and added 2 new methods:

  • public int convertToInt_BE()
  • public void replaceAndResize(byte[] oldByteArray, byte[] newByteArray)

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.

HPE NonStop, IBM i (OS/400), Java, JMS, Linux, macOS (Mac OS X), Open Source, Programming, Raspberry Pi, Unix, Windows, z/OS Comments Off on Updates to My ByteArray Class

Ubuntu 21.04 Released

Canonical has just released Ubuntu v21.04.
http://releases.ubuntu.com/21.04/

Super-fast, easy to use and free, the Ubuntu operating system powers millions of desktops, netbooks and servers around the world. Ubuntu does everything you need it to. It’ll work with your existing PC files, printers, cameras and MP3 players. And it comes with thousands of free apps.

Regards,
Roger Lacroix
Capitalware Inc.

Linux, Open Source, Operating Systems Comments Off on Ubuntu 21.04 Released

Programmatically Get IBM MQ Version for Both Client and Queue Manager

Recently, on both StackOverflow and mqseries.net, people have been asking about getting both the client and queue manager versions numbers for MQ.

It is pretty easy to get both the client and queue manager from the command line.

For the IBM MQ installation that is running the queue manager, you simply issue the following command:

dspmqver

To determine the MQ JAR file version number, you simply issue the following command:

java -jar com.ibm.mq.jar

or if you are using the com.ibm.mq.allclient.jar MQ JAR then do:

java -jar com.ibm.mq.allclient.jar

Now in theory, an MQ application should not care about what version of the queue manager it is connecting to or what MQ JAR files the application is using but sometimes it is nice to have all of the information in an application log file, so that you don’t have chase for the information after the fact.

IBM has done a terrible job making this kind of information available from the MQJavaLevel class file found in the found in com.ibm.mq.jar and com.ibm.mq.allclient.jar files.

A long time ago, I stumbled across the MQJavaLevel class and did a bunch of testing to figure how to programmatically get the version information from it and write it to the application’s log file.

Note: The following is undocumented and is from me beating MQ up a little bit. 🙂

The MQJavaLevel class has a method called queryValue. It takes an integer parameter between 0 to 4 and returns a String value.

  • 0 – will retrieve the MQ name i.e. IBM MQ classes for Java
  • 1 – will retrieve the MQ version i.e. 9.1.3.0
  • 2 – will retrieve the MQ level value i.e. p913-L190628
  • 3 – will retrieve the MQ build type i.e. Production
  • 4 – will retrieve the MQ JAR file location i.e. D:/Program Files/IBM/MQ/java/lib/com.ibm.mq.jar

The problem is, IBM never exposed the queryValue method. It is so weird. So, the only way around it is to create your own Java class that extends the MQJavaLevel class. You can have a look at the MQLevel class in the open source project called Universal File Mover (UFM).

It is a simple class:

package com.capitalware.ufm.mq;

import com.ibm.mq.MQJavaLevel;

public class MQLevel extends MQJavaLevel
{
   /**
    * The constructor
    */
   public MQLevel()
   {
      super();
   }

   /**
    * Get the IBM name for the MQ JAR class.
    * @return
    */
   public String getName()
   {
      return queryValue(0);
   }

   /**
    * Get the version of the MQ JAR class.
    * @return
    */
   public String getVersion()
   {
      return queryValue(1);
   }
}

Therefore, at the top/beginning of your Java and/or Java/JMS code, if you want to dump out the MQ name and version then do the following:

try
{
   ClassLoader classLoader = ClassLoader.getSystemClassLoader();
   Class.forName("com.ibm.mq.MQJavaLevel", false, classLoader);
   MQLevel mql = new MQLevel();
   System.out.println("MQ JAR Version = " + mql.getName()+" V"+mql.getVersion());
}
catch(ClassNotFoundException e)
{
   System.out.println("MQ is not in the CLASSPATH.");
}

The output will look like:

MQ JAR Version = IBM MQ classes for Java V9.1.3.0

The above code will work for both Java and Java/JMS applications.

Getting the queue manager’s version number is a little different. You cannot directly get the version number from the MQQueueManager class or JMS Connection class. But you can get the queue manager’s command level which is the first 3 digits of the version number. 9.1.3 vs 9.1.3.0

For a Java (non-JMS) programs, you can do the following:

MQQueueManager qMgr = new MQQueueManager(qMgrName);
System.out.println("MQ Command Level: " + qMgr.getCommandLevel());

For a Java/JMS programs, you can do the following:

Connection conn = cf.createConnection(userid, password);
JmsPropertyContext propertyContext = (JmsPropertyContext) conn;
System.out.println("MQ Command Level: " + propertyContext.getIntProperty(WMQConstants.WMQ_COMMAND_LEVEL));

If you truly want the queue manager’s version number then you will need to use MQ PCF command.

Here is how to do it:

MQQueueManager qMgr = new MQQueueManager(qMgrName);
PCFMessageAgent agent = new PCFMessageAgent(qMgr);
PCFMessage request = new PCFMessage(CMQCFC.MQCMD_INQUIRE_Q_MGR);
request.addParameter(CMQCFC.MQIACF_Q_MGR_ATTRS, new int [] { CMQC.MQCA_VERSION });
PCFMessage[] responses = agent.send(request);

for (PCFMessage response : responses)
{
   if (response.getCompCode() == CMQC.MQCC_OK)
   {
      System.out.println("MQ Version: " + response.getStringParameterValue(CMQC.MQCA_VERSION));
   }
}

Regards,
Roger Lacroix
Capitalware Inc.

HPE NonStop, IBM i (OS/400), IBM MQ, IBM MQ Appliance, Java, JMS, Linux, macOS (Mac OS X), Open Source, PCF, Programming, Raspberry Pi, Unix, Windows Comments Off on Programmatically Get IBM MQ Version for Both Client and Queue Manager

FreeBSD v13.0 Released

The FreeBSD Release Engineering Team has just released FreeBSD v13.0.
https://www.freebsd.org/releases/13.0R/announce.html

FreeBSD is an advanced operating system for modern server, desktop, and embedded computer platforms. FreeBSD’s code base has undergone over thirty years of continuous development, improvement, and optimization. It is developed and maintained by a large team of individuals. FreeBSD provides advanced networking, impressive security features, and world class performance and is used by some of the world’s busiest web sites and most pervasive embedded networking and storage devices.

Regards,
Roger Lacroix
Capitalware Inc.

Open Source, Operating Systems Comments Off on FreeBSD v13.0 Released