Working from Home – Open Source Software

The other day I wrote about working from home, since I recently upgraded both my desktop and laptop to Windows 10 64-bit, I thought I should review/list the open source software I use to get the job done.

You don’t need to go broke setting up your PC/laptop with software. Here is a list of open source (or free) software that I use:

Eclipse (for Java and C development) is, in my opinion, the best IDE for programmers.
Microsoft Visual Studio Community 2015
AdoptOpenJDK
Open Object REXX
Apache HTTP Server
Inno Setup is an installer for Windows programs.
LibreOffice (alternative to Microsoft Office)
Thunderbird is an email client (alternative to Outlook)
Firefox is a web browser
Adobe Reader is a PDF viewer
WinAmp is a great music player
Irfanview is a graphic viewer
Kee Pass 2 a tool for managing your passwords
PuTTY for logging into Unix / Linux servers
TN5250J for logging into IBM i (OS/400) servers
x3270 for logging into z/OS (mainframe) servers
TightVNC for controlling other servers (Windows, Linux or Unix)
FAR is a great file manager
Visual Diff is a really good program that compares the contents of 2 files
7-Zip is a file archiver
Virtual CloneDrive allows you to mount ISO, BIN & CCD files
Cobian and RoboCopy are great programs to backup / synchronize your files (BACKUP YOUR FILES!!!)

Even though I have Microsoft Visual Studio Community IDE installed, I don’t use it. I use Eclipse and makefiles for my C development. I rarely do any GUI development in C, so switching back and forth between Visual Studio IDE and Eclipse just slows me down. Hence, I can code much faster if I just stay in Eclipse and do all of my development in it. And yes, I said I use makefiles. Developers get so freaked-out when you say makefiles. But there is nothing wrong with using makefiles. All it means is that the developer needs to understand what components his/her project uses. I have to use makefiles on AIX, HP-UX, Linux, Solaris, IBM i (OS/400) and z/OS (JCL actually), so what is wrong with using makefiles on Windows? Absolutely nothing.

I create/update all of the product manuals (open source, licensed as free and commercial) using LibreOffice. I currently have roughly 100 product manuals and I have no issues using LibreOffice. It works really well and I like the 1-click button to create a PDF.

Finally, if you are a developer or not, make sure you backup your stuff. Besides, Cobian and RoboCopy, there are lots of open source programs to backup your important files, pictures, code, documents, etc. It doesn’t matter what you use, just use something.

Regards,
Roger Lacroix
Capitalware Inc.

.NET, C, C#, C++, Capitalware, Java, JMS, Open Source, Programming, Rexx, Windows Comments Off on Working from Home – Open Source Software

Customer Requested Enhancement to MQMR

MQ Message Replication (MQMR) is an MQ API Exit. An MQ API Exit is configured to run within the queue manager’s address space (or the application’s address space if the application connects in bindings mode to the queue manager).

For MQMR v1.1.0, a customer requested that information be added to the replicated messages, so that the consumer application would know what the source queue manager names and source queue names were. This was done with via MQ’s named properties.

In MQMR v2.0.0, 2 auxiliary programs were added: mq2sdb and sdb2mq. These programs allowed the customer to offload replicated messages to an SQLite database and the ability to reload the message to a queue.

I also published the format of the tables in the SQLite database.

Recently, a customer requested that the source queue manager names and source queue names be written to the SQLite database. At first, I was a little reluctant to do it because I had published the format of the table in the SQLite database but then I realize that I could add 2 columns to the end of the table plus add 2 new tables to handle the information without affecting other customer’s applications.

(1) mq2sdb program has a new keyword called: IncludeSourceInfo. IncludeSourceInfo specifies whether or not the source queue manager name and queue name (if present) be written to the SQLite database. The default value is N.

(2) sdb2mq program has 3 new keywords: UseSelect, SelectQMgrName & SelectQName. UseSelect specifies whether or not the rows of the IBM_MQ_MESSAGES table will be selected by either queue manager name or queue name or both. The default value is N.

For those 3rd party applications that customers use to offload replicated messages from a target queue, here are the new tables in the SQLite database:

CREATE TABLE IBM_MQ_MESSAGES(Version            INT,
                             Report             INT,
                             MsgType            INT,
                             Expiry             INT,
                             Feedback           INT,
                             Encoding           INT,
                             CodedCharSetId     INT,
                             Priority           INT,
                             Persistence        INT,
                             BackoutCount       INT,
                             PutApplType        INT,
                             MsgSeqNumber       INT,
                             Offset             INT,
                             MsgFlags           INT,
                             OriginalLength     INT,
                             Format             CHAR(8),
                             ReplyToQ           CHAR(48),
                             ReplyToQMgr        CHAR(48),
                             UserIdentifier     CHAR(12),
                             ApplIdentityData   CHAR(32),
                             PutApplName        CHAR(28),
                             PutDate            CHAR(8),
                             PutTime            CHAR(8),
                             ApplOriginData     CHAR(4),
                             MsgId              BLOB,
                             CorrelId           BLOB,
                             AccountingToken    BLOB,
                             GroupId            BLOB,
                             Data               BLOB,
                             Source_QMgr_Id     INT,
                             Source_Queue_Id    INT );

CREATE TABLE SOURCE_QMGR_NAMES(Id               INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT UNIQUE,
                               QMgrName         CHAR(48) NOT NULL UNIQUE );

CREATE TABLE SOURCE_QUEUE_NAMES(Id              INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT UNIQUE,
                                QueueName       CHAR(48) NOT NULL UNIQUE );

I have completed a wide variety of tests and everything looks good. The customer is now also testing the latest release of MQMR.

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

Regards,
Roger Lacroix
Capitalware Inc.

Capitalware, Database, IBM i (OS/400), IBM MQ, Linux, MQ Message Replication, Unix, Windows Comments Off on Customer Requested Enhancement to MQMR

memmem() Function for a C Program

Last week, I needed a function for a C program that would search a string not null terminated for a string not null terminated. Hence, I could not use strstr() function because it requires the strings to be null terminated. So, I checked my trusty C Runtime Library Reference and found nothing that matched.

Now most people would hit the internet and do a search for what they need. But for these kinds of functions, I always check the Snippets archive that I have first. A long time ago, there used to be a Snippets web site run by Bob Stout. Unfortunately, he died in 2011 and his web site disappeared a little while later. Luckily, the Way Back Machine has a full archive of his Snippets web site. A lot of people have posted/hosted his Snippets ‘97 archive but really everyone should be using the Snippets 2003 archive (latest release). I have the Snippets 2003 archive available to download here. The great feature of Bob Stout’s Snippets archive is that he licensed all code as public domain. Over the years, I have used many functions from Bob Stout’s Snippets archive and it has been truly helpful.

In the Snippets archive, there is an important file that describes each program/function called ‘snippets.ndx’. I did a quick search of the file and found the perfect function that matched my needs called memmem(). I copied the function to my program, tested it on Windows and it worked perfectly.

Life was great then I went to do a build on Linux and got the follow error:

error: conflicting types for ‘memmem’
void *memmem(const void *buf, const void *pattern, size_t buflen, size_t len)

I immediately shock my head and said WTF! I did “man memmem” command and sure enough, there is a memmem() function on Linux that does what I want. The parameter list is different but really it is just the order of the parameters.

I then did some internet searches and noticed a lot of people were doing searches for “memmem on Windows”. So, I got the bright idea of rearranging the parameter list for Snippets memmem() function (and use the same variable names as Linux) and post the updated code as public domain in Bob Stout’s name.

So here you go, a cross-platform version of memmem() function with defines to handle Linux:

#if !defined(__linux__)
/**
 * Function Name
 *  memmem
 *
 * Description
 *  Like strstr(), but for non-text buffers that are not NULL delimited.
 *
 *  public domain by Bob Stout
 *
 * Input parameters
 *  haystack    - pointer to the buffer to be searched
 *  haystacklen - length of the haystack buffer
 *  needle      - pointer to a buffer that will be searched for
 *  needlelen   - length of the needle buffer
 *
 * Return Value
 *  pointer to the memory address of the match or NULL.
 */
void *memmem(void *haystack, size_t haystacklen, void *needle, size_t needlelen)
{
   /* --------------------------------------------
    * Variable declarations.
    * --------------------------------------------
    */
   char *bf = (char*) haystack, *pt = (char*) needle, *p = bf;

   /* --------------------------------------------
    * Code section
    * --------------------------------------------
    */
   while (needlelen <= (haystacklen - (p - bf)))
   {
      if (NULL != (p = memchr(p, (int)(*pt), haystacklen - (p - bf))))
      {
         if (0 == memcmp(p, needle, needlelen))
            return p;
         else
            ++p;
      }
      else
         break;
   }

   return NULL;
}
#endif

Regards,
Roger Lacroix
Capitalware Inc.

C, HPE NonStop, IBM i (OS/400), Linux, macOS (Mac OS X), Open Source, Programming, Unix, Windows, z/OS Comments Off on memmem() Function for a C Program

Working from Home and Coronavirus aka COVID-19

It is funny that everyone is freaking out about working from home. I always found I got less done at the office than at home because I was always being interrupted every 2 minutes.

For most of my career, I have worked part-time at home. In 2001, I incorporated Capitalware and went out on my own. I liked how I could set my own rules on how much work I did from home. In 2007, I stopped all consulting work and gave it 110% to creating and supporting my own (Capitalware) software.

I had a desk and chair but the desk was really a 6 foot (2 meter) banquet table and the chair was very basic item. I ended up getting carpal tunnel syndrome in both wrist (it was really in right wrist) – in 2007 I believe. I found a good doctor who gave me a set of wrist exercises and a brace but the big thing he wanted me to do was get a proper desk and chair and set my arm alignment to the keyboard, so that the pressure would be removed from nerves. So, I went out and purchased a really nice mahogany desk and a proper multi-adjustable chair. It took about a year for the carpal tunnel to clear up and it is something I NEVER EVER want to go through again.

So, my advice to everyone working from home is get yourself a proper desk and chair to do your work at!!! Take it from someone who’s been there, done that.

The other comment I hear people make is about being bored or lonely at home. I play music while I work. I also have a TV tuner (USB) plugged into my PC, so when there is a business show I want to listen to, I put it on and put the display in the background. I would strongly suggest that people not play games or watch movies because you will never get any work done. 🙂

Many of you have met my wife, Cynthia, at the MQ Technical Conferences. She is a pharmacist. I had a heart attack back in 2010. So, she has been doing a lot of research about coronavirus aka COVID-19.

    Here’s what she has found out:

  • there is a strong link between people with cardiac diseases, hypertension, diabetes and COVID-19
  • there is a strong link between people with vitamin D deficiency (northern people) and COVID-19

So, the cardiac diseases, hypertension and diabetes link explains why it appears to affect older people because young people tend not to have these issues.

Basically, if you are on those drugs then you have 3 to 5 times more receptors, hence, a greater probably of getting COVID-19 and with more receptors means more attachment of the virus. i.e. It is like comparing cheap glue with Krazy or Gorilla glue. You don’t want to have COVID-19 make a strong bond to you!! Hence, if you don’t know what medicine you are taking ask your doctor or pharmacist. I just happen to be lucky that my wife is a pharmacist.

The funny part was when Cynthia read the articles about vitamin D deficiency, she ran upstairs grab a bottle of vitamin D pills and then handed me 1 and said I need to take 1 vitamin D pill every day. Now luckily, I am off all of the drugs I was on after my heart attack except for a statin drug and baby aspirin.

Finally, I wish the “experts” (BNN, Bloomberg, CNBC & Fox Business) would stop comparing coronavirus aka COVID-19 to the 2008 Financial Crisis – it is NOTHING like it. If you need to compare it to something then compare coronavirus aka COVID-19 to dust bowl from the Great Depression – that is a proper comparison!!!!

Regards,
Roger Lacroix
Capitalware Inc.

General Comments Off on Working from Home and Coronavirus aka COVID-19

IBM MQ Fix Pack 9.0.0.9 Released

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.

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

IBM Integration Technical Conference 2020

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.

IBM i (OS/400), IBM MQ, Linux, Programming, Security, Unix, Windows, z/OS Comments Off on IBM Integration Technical Conference 2020

IBM Think 2020

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.

.NET, C, C#, C++, Education, IBM i (OS/400), IBM MQ, Java, JMS, Linux, Programming, Security, Unix, Windows, z/OS Comments Off on IBM Think 2020

Java’s Missing Byte Array Class

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.

  • public byte byteAt(int index)
  • public char charAt(int index)
  • public byte[] concat(byte[] suffixArray)
  • public boolean endsWith(byte[] suffixArray)
  • public boolean equals(Object other)
  • public boolean equals(Object other, int offset)
  • public byte[] getBytes()
  • public byte[] getBytes(int beginIndex)
  • public byte[] getBytes(int beginIndex, int endIndex)
  • public int getLength()
  • public int indexOf(byte[] searchFor)
  • public int indexOf(byte[] searchFor, int fromIndex)
  • public int indexOf(byte searchFor)
  • public int indexOf(byte searchFor, int fromIndex)
  • public int indexOf(String searchFor)
  • public int indexOf(String searchFor, int fromIndex)
  • public int indexOf(char searchFor)
  • public int indexOf(char searchFor, int fromIndex)
  • public boolean isEmpty()
  • public int lastIndexOf(byte[] searchFor)
  • public int lastIndexOf(byte[] searchFor, int fromIndex)
  • public int lastIndexOf(byte searchFor)
  • public int lastIndexOf(byte searchFor, int fromIndex)
  • public int lastIndexOf(String searchFor)
  • public int lastIndexOf(String searchFor, int fromIndex)
  • public int lastIndexOf(char searchFor)
  • public int lastIndexOf(char searchFor, int fromIndex)
  • public int length()
  • public byte[] replace(char oldChar, char newChar)
  • public byte[] replace(byte oldByte, byte newByte)
  • public byte[] replace(byte[] oldByteArray, byte[] newByteArray)
  • public byte[] resize(int newSize)
  • public byte[][] split(char delimiter)
  • public byte[][] split(byte delimiter)
  • public boolean startsWith(byte[] prefix)
  • public boolean startsWith(byte[] prefix, int offset)
  • public byte[] toByteArray()
  • public char[] toCharArray()
  • public String toHexArray()
  • public String toString()

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.

HPE NonStop, IBM i (OS/400), Java, JMS, Linux, macOS (Mac OS X), Open Source, Programming, Raspberry Pi, Unix, Windows, z/OS 3 Comments

Updated Request & Reply JMS/MQRFH2 Messaging Scenario

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:

  • Connect to a remote queue manager
  • Open an input queue, get a message, close the queue
  • Extract the MQRFH2 variables
  • Take a checksum of the incoming message payload
  • Use the checksum as a seed value for the random number generator
  • Generate Powerball numbers and a create reply payload with that information
  • Open the output queue
  • Create a new reply message with the extracted RFH2 values and the reply payload then send the reply message
  • Close the output queue and disconnect from the queue manager

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.

IBM i (OS/400), IBM MQ, Linux, macOS (Mac OS X), Programming, Unix, Windows, z/OS Comments Off on Updated Request & Reply JMS/MQRFH2 Messaging Scenario

Inhibit/Allow the Get & Put Actions of a Queue

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.

HPE NonStop, IBM i (OS/400), IBM MQ, IBM MQ Appliance, Java, Linux, macOS (Mac OS X), Open Source, Programming, Raspberry Pi, Unix, Windows, z/OS Comments Off on Inhibit/Allow the Get & Put Actions of a Queue