ISF002I MASTER SDSF SYSLOG INDEX FULL

I have a z/OS LPAR via IBM’s RDP (Remote Development Program). Yesterday, I started receiving the following error message every time I went to SDSF’s log panel:

ISF002I MASTER SDSF SYSLOG INDEX FULL

I’m a developer and not a SysAdmin. At first I ignored it then got annoyed and did some internet searches. I found some commands but nothing worked for me. I found this command that the person said would delete all entries older than 90 days but it did not work for me.
I.e.

$P O JOBQ,READY,Q=x,A>90

I opened a ticket with IBM’s RDP support and here was there response:

Go to the SDSF O panel and delete all SYSLOGs entries that you no longer want by placing a P to the left of the output.

After some help from a fellow MQ ListServer person, I now understand why the above “P” command did not work for me. You need to know the class for the Q (Queue) parameter.

First go to SDSF O panel and set your prefix to “*”. i.e. PRE *

Next look at the “C” (class) column, (see highlight in picture):

My SYSLOG entries are class ‘C’. Therefore, the correct command (for me) is:

$P O JOBQ,READY,Q=C,A>90

This command will delete all SYSLOG entries older than 90 days.

Hope this helps other developers who are not SysAdmins with their z/OS LPAR SYSLOG issues. 🙂

Regards,
Roger Lacroix
Capitalware Inc.

Operating Systems, z/OS Leave a comment

IBM Champion Again.

Proud to be named as an IBM Champion for my contributions to IBM MQ community for the 2nd year in a row!
https://www.ibm.com/developerworks/champion/

Regards,
Roger Lacroix
Capitalware Inc.

MQ Leave a comment

Beta testers needed for MQ Channel Connection Inspector

All,

Capitalware is ready for beta testers for a new solution called: MQ Channel Connection Inspector.

Have you ever had client applications or remote queue managers attempt to connect to your queue manager but failed and the user claimed they used the “correct values”.

I’ve created a new solution to quickly diagnose this problem and need some beta testers to give me some feedback. MQ Channel Connection Inspector (MQCCI) is an MQ Channel Security Exit. For those who don’t know, a channel security exit is ONLY invoked/called by the MCA for MQCONN/X and MQDISC API calls (so it is very light-weight). The MCA passes the MQCD and MQCXP structures to the channel security exit. Those structures contain SSL/TLS fields, MCAUserId, batch size, retry information, etc. The MQCD structure has 82 fields and the MQCXP structure 26 fields (see MQ’s cmqxc.h file for more details).

I have designed MQCCI to output any or all of the fields from the MQCD and MQCXP structures (user selectable). The information is written to a CSV (Comma-Separated-Values) file. Right now, the output is in the format of “field=value,field=value,field=value,etc.”. The “value” data has been converted to human-readable format. The first question for beta testers is this an acceptable format or would you prefer a true CSV/spreadsheet format. i.e. where the field/column names are in row 1 and only the values are in rows 2 through to the last row.

Current format:

2018/01/10 17:25:07.712373, CONN, QMgrName=MQWT1, ChlName=TEST.EXIT, CD_MaxMsgLength=4194304, CD_PutAuthority=MQPA_DEFAULT, CD_MCAUserIdentifier=barney, CD_ConnectionName=10.10.10.10, CD_RemoteUserIdentifier=barney, CXP_RemoteProduct=MQCC, CXP_RemoteVersion=0800,

Or a true CSV/spreadsheet format would be (row # 1 would only be in the CSV file once):

"Date/Time", "API Call", Queue Manager Name", "Channel Name", "CD_MaxMsgLength", "CD_PutAuthority", "CD_MCAUserIdentifier", "CD_ConnectionName", "CD_RemoteUserIdentifier", "CXP_RemoteProduct", "CXP_RemoteVersion",
"2018/01/10 17:25:07.712373", "CONN", "MQWT1", "TEST.EXIT", 4194304, "MQPA_DEFAULT", "barney", "10.10.10.10", "barney", "MQCC", "0800",
"2018/01/10 17:25:09.446511", "CONN", "MQWT1", "TEST.EXIT", 4194304, "MQPA_DEFAULT", "wilma", "10.10.10.20", "wilma", "MQCC", "0800",

I plan on building MQ Channel Connection Inspector for AIX, HP-UX (RISC & IA64), Solaris (SPARC & x86_64), Linux (x86, x86_64, POWER & zSeries), Windows and IBM i (OS/400) and z/OS. MQ Channel Connection Inspector will support WMQ v6.0, v7.0, v7.1, v7.5, v8.0 & v9.0.

Beta testing MQ Channel Connection Inspector is absolutely free including support (no strings attached).

If you interesting in trying it out, please send an email to support@capitalware.com to request a trial of MQ Channel Connection Inspector,

Regards,
Roger Lacroix
Capitalware Inc.

Capitalware, IBM i (OS/400), Linux, MQ, Security, Unix, Windows, z/OS Leave a comment

Java/JMS MQ Applications and Maven

IBM has made available the MQ Redistributable Client (Java/JMS portion) on Maven. Mark Taylor of IBM has a blog posting on it and how to configure your files to use it:
https://developer.ibm.com/messaging/2018/01/09/developing-mq-java-applications-maven/

Regards,
Roger Lacroix
Capitalware Inc.

Java, JMS, Linux, Mac OS X, MQ, Programming, Unix, Windows Leave a comment

I’m Already Sick of Winter!

Its January 9th, 2018 and I’m already sick of winter. Polar vortex, snow and more snow. I know it is early January and I’m Canadian but I’m sick of it. Snow banks are over 6 feet (2 meters) tall. I want Spring and not in 2 and half months but now. 🙁

Here’s a picture looking up my street (click to see a larger image):

Here’s another picture looking down my street (click to see a larger image):

Snow and cold is great for Christmas holidays but when the holidays are over, the snow needs to go too (just like the Christmas tree). I really need to move somewhere where it is warm this time of year. 🙂

Regards,
Roger Lacroix
Capitalware Inc.

General 1 Comment

New: MQ Batch Toolkit v3.0.0

Capitalware Inc. would like to announce the official release of MQ Batch Toolkit v3.0.0. MQ Batch Toolkit allows users to manipulate, monitor and manage messages in a queue of an IBM MQ (formally WebSphere MQ & MQSeries) queue manager from a command-line or shell scripting environment.

Starting with MQ Batch Toolkit v3.0.0, the licensing model has changed to be subscription based model meaning there will be no upfront software cost, only a yearly subscription fee.

New lower price: The cost for MQ Batch Toolkit is now $49.00 USD per user for a 1-year subscription.

For more information about MQ Batch Toolkit go to:
http://www.capitalware.com/mqbt_overview.html

    Changes for MQ Batch Toolkit v3.0.0:

  • Added BackupTopic function to subscribe to a topic and write the messages to a VEQ file.
  • Added RestoreTopic function to read a VEQ file and publish the messagse to a topic.
  • Added ReportTopic function to generate a report (PDF, RTF or HTML) from topic messages.
  • Added Subscribe function to subscribe to a topic and output the message data to the screen (console).
  • Added Publish function to publish a message to a topic.
  • Added TopicList function that will retrieve a list of topics from a local or remote queue manager.
  • Added SubscribeServer (SS) function that will continuously consume messages of a topic.
  • Added PublishServer (PBS) function that will publish (put) messages to a topic.
  • Added TopicMonitor (TM) function that will continuously monitor the topics of a queue manager writing the information to a CSV (Comma Separated Value) file.
  • Added SubscriptionMonitor (SUBM) function that continuously monitor the subscriptions of a queue manager writing the information to a CSV (Comma Separated Value) file.
  • Added QueueStatusMonitor (QSTM) function that will continuously monitor the queues of a queue manager writing the information to a CSV (Comma Separated Value) file.
  • Added Register function to allow an end-user to register the license key and retrieve an Access Code.
  • Added ‘-C’ parameter (Convert on Get) for ClearQByString function.
  • Added ‘-N’ parameter (Named Properties) for Report function.
  • Added JVM environment variables: com.ibm.mq.cfg.useIBMCipherMappings=false & com.ibm.jsse2.disableSSLv3=false
  • Added more SSL/TLS CipherSpecs
  • Added Send and receive exits for queue manager access profile (AddProfile & AlterProfile).
  • Updated GetServer to output the message payload to the console of the message received.
  • Fixed the error message for path to security exit JAR file for AddProfile and AlterProfile
  • MQ Batch Toolkit is now built as a 64-bit executable for Linux, macOS and Windows.
  • Updated docs (English only)

Regards,
Roger Lacroix
Capitalware Inc.

Capitalware, Linux, Mac OS X, MQ, MQ Batch Toolkit, Windows Comments Off on New: MQ Batch Toolkit v3.0.0

Merry Christmas and Happy New Year

I would like to wish everyone a Merry Christmas, Happy Hanukkah, Happy Kwanzaa, etc… and a Happy New Year. 🙂

Regards,
Roger Lacroix
Capitalware Inc.

General 1 Comment

Debian 9.3 Released

Debian Project has just released Debian 9.3.
https://www.debian.org/News/2017/2017120902

Debian is a free operating system (OS) for your computer. An operating system is the set of basic programs and utilities that make your computer run. Debian uses the Linux kernel (the core of an operating system), but most of the basic OS tools come from the GNU project; hence the name GNU/Linux.

Regards,
Roger Lacroix
Capitalware Inc.

Linux, Open Source, Operating Systems Comments Off on Debian 9.3 Released

Sample Java Code to Subscribe to an IBM MQ Topic

Here is blog posting # 2 on subscribing to a topic in IBM MQ. More code examples – here is a Java IBM MQ (non-JMS) sample program to subscribe to a topic within a queue manager of IBM MQ. It will receives messages until ‘no messages available’ exception which is set for 30 seconds.

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 com.ibm.mq.MQException;
import com.ibm.mq.MQGetMessageOptions;
import com.ibm.mq.MQMessage;
import com.ibm.mq.MQQueueManager;
import com.ibm.mq.MQTopic;
import com.ibm.mq.constants.CMQC;

/**
 * Program Name
 *  MQSub01
 *
 * Description
 *  This java class will connect to a queue manager, subscribe to a topic and receive messages.
 *
 * Sample Command Line Parameters
 *  -h 127.0.0.1 -p 1414 -c TEST.CHL -m MQA1 -t topicString -o topicObject -u userId -x password
 *
 * @author Roger Lacroix, Capitalware Inc.
 */
public class MQSub01
{
   private static final SimpleDateFormat  lOGGER_TIMESTAMP = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss.SSS");
   
   private Hashtable<String, String> params = null;
   private Hashtable<String, Object> mqht = null;
   private String qMgrName;
   private String topicString = null;
   private String topicObject = null;

   /**
    * The constructor
    */
   public MQSub01()
   {
      super();
      MQSub01.logger("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("-u") && params.containsKey("-x");
      
      // Need at least one
      if ( (!params.containsKey("-t")) && (!params.containsKey("-o")) )
         b = false;
      
      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");
         topicString = (String) params.get("-t");
         topicObject = (String) params.get("-o");
         
         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));
         }
         
         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 topic, receive messages, close topic and disconnect.
    *
    */
   private void testSub()
   {
      int openOptionsForGet = CMQC.MQSO_CREATE | CMQC.MQSO_FAIL_IF_QUIESCING | CMQC.MQSO_MANAGED | CMQC.MQSO_NON_DURABLE;
      MQQueueManager _qMgr = null;
      MQTopic subscriber = null;
      MQGetMessageOptions gmo = new MQGetMessageOptions();
      gmo.options = CMQC.MQGMO_WAIT + CMQC.MQGMO_FAIL_IF_QUIESCING;
      gmo.waitInterval = 30000;  // wait up to 30 seconds
      MQMessage mqMsg = null;
      String msgText = null;
      boolean more = true;

      try
      {
         _qMgr = new MQQueueManager(qMgrName, mqht);
         MQSub01.logger("connected to queue manager: " + qMgrName);
         
         subscriber = _qMgr.accessTopic( topicString,
                                         topicObject,
                                         CMQC.MQTOPIC_OPEN_AS_SUBSCRIPTION,
                                         openOptionsForGet);
         logger("subscribed to topic: " + subscriber.getName());

         while (more)
         {
            try
            {
               mqMsg = new MQMessage();
               mqMsg.messageId = CMQC.MQMI_NONE;
               mqMsg.correlationId = CMQC.MQCI_NONE;
               subscriber.get(mqMsg, gmo);
               msgText = mqMsg.readStringOfByteLength(mqMsg.getMessageLength());
               MQSub01.logger("received message: " + msgText);
            }
            catch (MQException e)
            {
               more = false;
               MQSub01.logger("MQException CC=" +e.completionCode + " : RC=" + e.reasonCode);
            }
            catch (IOException e)
            {
               more = false;
               MQSub01.logger("IOException " + e.getLocalizedMessage());
            }
         }
      }
      catch (MQException e)
      {
         MQSub01.logger("MQException CC=" +e.completionCode + " : RC=" + e.reasonCode);
      }
      finally
      {
         try
         {
            if (subscriber != null)
               subscriber.close();
         }
         catch (MQException e)
         {
            MQSub01.logger("MQException CC=" +e.completionCode + " : RC=" + e.reasonCode);
         }

         try
         {
            if (_qMgr != null)
               _qMgr.disconnect();
         }
         catch (MQException e)
         {
            MQSub01.logger("MQException CC=" +e.completionCode + " : RC=" + e.reasonCode);
         }
      }
      
      MQSub01.logger("Is now ending.");
   }

   /**
    * 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)
   {
      MQSub01 mqs = new MQSub01();

      try
      {
         mqs.init(args);
         mqs.testSub();
      }
      catch (IllegalArgumentException e)
      {
         System.out.println("Usage: java MQSub01 -h host -p port -c channel -m QueueManagerName -t topicString -o topicObject -u userId -x password");
         System.exit(1);
      }

      System.exit(0);
   }
}

Things to note:

  • The allParamsPresent and init methods makes sure all of the required parameters are present at program startup.
  • The testSub method does the following:
    • Connects to the queue manager
    • Opens the specified topic as a subscription by either Topic String or Topic Object or both
    • Loop while there are more messages – the wait interval is set to 30 seconds
    • When Reason Code of 2033 (MQRC_NO_MSG_AVAILABLE) exception is thrown then exit the loop
    • Closes the topic
    • Disconnects from the queue manager

Regards,
Roger Lacroix
Capitalware Inc.

IBM i (OS/400), Java, Linux, Mac OS X, MQ, Programming, Unix, Windows, z/OS Comments Off on Sample Java Code to Subscribe to an IBM MQ Topic

Sample Java Code to Publish to an IBM MQ Topic

Programmers always have questions about coding Pub/Sub in IBM MQ. I’ll do 2 blog posting: one on publishing to a topic and the next one on subscribing to a topic in IBM MQ. Since everyone likes code examples, here is a Java IBM MQ (non-JMS) sample program to publish a message to a topic within a queue manager of IBM MQ.

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 com.ibm.mq.MQException;
import com.ibm.mq.MQMessage;
import com.ibm.mq.MQPutMessageOptions;
import com.ibm.mq.MQQueueManager;
import com.ibm.mq.MQTopic;
import com.ibm.mq.constants.CMQC;

/**
 * Program Name
 *  MQPub01
 *
 * Description
 *  This java class will connect to a queue manager and publish a message to a topic.
 *
 * Sample Command Line Parameters
 *  -h 127.0.0.1 -p 1414 -c TEST.CHL -m MQA1 -t topicString -o topicObject -u userId -x password
 *
 * @author Roger Lacroix, Capitalware Inc.
 */
public class MQPub01
{
   private static final SimpleDateFormat  lOGGER_TIMESTAMP = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss.SSS");
   
   private Hashtable<String, String> params = null;
   private Hashtable<String, Object> mqht = null;
   private String qMgrName;
   private String topicString = null;
   private String topicObject = null;

   /**
    * The constructor
    */
   public MQPub01()
   {
      super();
      MQPub01.logger("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("-u") && params.containsKey("-x");
      
      // Need at least one
      if ( (!params.containsKey("-t")) && (!params.containsKey("-o")) )
         b = false;
      
      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");
         topicString = (String) params.get("-t");
         topicObject = (String) params.get("-o");
         
         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));
         }
         
         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 topic, write a message, close topic and disconnect.
    *
    */
   private void testPub()
   {
      int openOutputOptions  = CMQC.MQOO_OUTPUT + CMQC.MQOO_FAIL_IF_QUIESCING;
      MQPutMessageOptions pmo = new MQPutMessageOptions();
      MQQueueManager _qMgr = null;
      MQTopic publisher = null;
      MQMessage mqMsg = null;
      String line = "This is a test message from MQPub01.";

      try
      {
         _qMgr = new MQQueueManager(qMgrName, mqht);
         MQPub01.logger("connected to queue manager: " + qMgrName);
         
         publisher = _qMgr.accessTopic( topicString, 
                                        topicObject,
                                        CMQC.MQTOPIC_OPEN_AS_PUBLICATION, 
                                        openOutputOptions);
         MQPub01.logger("opened topic: " + publisher.getName());
         
         mqMsg = new MQMessage();
         mqMsg.messageId = CMQC.MQMI_NONE;
         mqMsg.correlationId = CMQC.MQCI_NONE;
         mqMsg.writeString(line);
         publisher.put(mqMsg, pmo);
         MQPub01.logger("message published: " + line);
      }
      catch (MQException e)
      {
         MQPub01.logger("MQException CC=" +e.completionCode + " : RC=" + e.reasonCode);
      }
      catch (IOException e)
      {
         MQPub01.logger("IOException " + e.getLocalizedMessage());
      }
      finally
      {
         try
         {
            if (publisher != null)
               publisher.close();
         }
         catch (MQException e)
         {
            MQPub01.logger("MQException CC=" +e.completionCode + " : RC=" + e.reasonCode);
         }

         try
         {
            if (_qMgr != null)
               _qMgr.disconnect();
         }
         catch (MQException e)
         {
            MQPub01.logger("MQException CC=" +e.completionCode + " : RC=" + e.reasonCode);
         }
      }
      
      MQPub01.logger("Is now ending.");
   }

   /**
    * 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)
   {
      MQPub01 mqp = new MQPub01();

      try
      {
         mqp.init(args);
         mqp.testPub();
      }
      catch (IllegalArgumentException e)
      {
         System.out.println("Usage: java MQPub01 -h host -p port -c channel -m QueueManagerName -t topicString -o topicObject -u userId -x password");
         System.exit(1);
      }

      System.exit(0);
   }
}

Things to note:

  • The allParamsPresent and init methods makes sure all of the required parameters are present at program startup.
  • The testPub method does the following:
    • Connects to the queue manager
    • Opens the specified topic by either Topic String or Topic Object or both
    • Puts a message to the topic
    • Closes the topic
    • Disconnects from the queue manager

Regards,
Roger Lacroix
Capitalware Inc.

IBM i (OS/400), Java, Linux, Mac OS X, MQ, Programming, Unix, Windows, z/OS Comments Off on Sample Java Code to Publish to an IBM MQ Topic