What you will learn

  1. Where common errors occur
  2. Where to look for debug information
  3. How to find out information about your MQ objects

First things first

Here’s the scenario: you’ve just coded your application, compiled it and run it for the first time. Exciting times! Oh no, something isn’t quite right, it generated an error message.

Don’t panic! It happens even to the very best devs. It’s time to debug, but where should we start?

There are many reasons why an application might fail, so how do we know if it’s a problem with messaging code: the MQ API calls or MQ related objects?

Visit the IBM Knowledge Centre for more detailed documentation on problem determination. You can also visit this page to learn about some best practices for making apps with MQ.

If your error message contains an MQ reason code, for example AMQ2035 2035 MQRC_NOT_AUTHORIZED, then it’s likely that something went wrong with the interaction with MQ.

Often it’s obvious from the error message what went wrong, you can fix your code and move on. However, sometimes a little more debug is required. The following sections walk through some basic debug steps and provide some hints and tips to get you moving again.

Hang on a minute, my application hasn’t compiled yet!

I’ve been trying to compile my code, but keep getting errors that look something like this

symbol:   variable WMQConstants
 location: class SessionBuilder
./com/ibm/mq/demo/SessionBuilder.java:93: error: cannot find symbol
     cf.setStringProperty(WMQConstants.CLIENT_ID, SUBSCRIPTION_NAME);
                          ^
 symbol:   variable WMQConstants
 location: class SessionBuilder
        

If your code isn’t compiling for any reason, here are the common culprits:

  • Do you have a jdk installed in order to use javac? Try typing java -version on a command line to check.
  • Do you have the jms.jar and com.ibm.mq.allclient.jar available?
  • Check your classpath. Have you typed the location of the jars correctly?
  • Make sure you are using the correct file directory separators for your operating system in commands.

Help! I got an MQ reason code, what next?

I’ve tried to run my code, but all I get are exceptions like the ones below:

Exception in thread "main" com.ibm.msg.client.jms.DetailedJMSSecurityRuntimeException: JMSWMQ2013: The security authentication was not valid that was supplied for QueueManager 'qm1' with connection mode 'Client' and host name 'localhost(1414)'.
Please check if the supplied username and password are correct on the QueueManager to which you are connecting.
	at com.ibm.msg.client.jms.DetailedJMSSecurityException.getUnchecked(DetailedJMSSecurityException.java:270)
	at com.ibm.msg.client.jms.internal.JmsErrorUtils.convertJMSException(JmsErrorUtils.java:173)
	at com.ibm.msg.client.jms.admin.JmsConnectionFactoryImpl.createContext(JmsConnectionFactoryImpl.java:478)
	at com.ibm.mq.samples.jms.JmsPutGet.main(JmsPutGet.java:98)
Caused by: com.ibm.mq.MQException: JMSCMQ0001: IBM MQ call failed with compcode '2' ('MQCC_FAILED') reason '2035' ('MQRC_NOT_AUTHORIZED').
	at com.ibm.msg.client.wmq.common.internal.Reason.createException(Reason.java:203)
	at com.ibm.msg.client.wmq.internal.WMQConnection.(WMQConnection.java:424)
	at com.ibm.msg.client.wmq.factories.WMQConnectionFactory.createV7ProviderConnection(WMQConnectionFactory.java:8475)
	at com.ibm.msg.client.wmq.factories.WMQConnectionFactory.createProviderConnection(WMQConnectionFactory.java:7815)
	at com.ibm.msg.client.jms.admin.JmsConnectionFactoryImpl._createConnection(JmsConnectionFactoryImpl.java:303)
	at com.ibm.msg.client.jms.admin.JmsConnectionFactoryImpl.createContext(JmsConnectionFactoryImpl.java:444)
	... 1 more
        

Looking through the exception details can give you lots of information. In the example above you can see the connection information the application is trying to use; queue manager name, connection mode and host name and port. It also gives you some information on what the problem might be. On the seventh line you can see the return code issued for the point the application failed, in this case 2035. A list of MQ reason codes is documented here

The IBM MQ queue manager error logs are a great place to get more detail on the problem that occurred. Essentially we’re looking for the queue managers perspective of what went wrong. The error logs are located in the MQ data directory on the system where the queue manager is running.

In Docker containers:

docker exec -ti <container_id> /bin/bash
cd /var/mqm/qmgrs/<your_queue_manager_name>/errors/

On Linux:

cd /var/mqm/qmgrs/<your_queue_manager_name>/errors/

On Windows systems:

cd <mq_installation_path>\QMGRS\<your_queue_manager_name>\ERRORS\

Next we take a look in the error log file. The most recent log entries are added to the bottom of the file. You can use an editor to view the logs or e.g. in Docker or Linux:

cat AMQERR01.LOG

Here you can see an entry from when a 2035 return code was produced:

08/08/18 18:40:40 - Process(415.18) User(root) Program(amqzlaa0)
                    Host(723001ebc6b2) Installation(Installation1)
                    VRMF(9.1.0.0) QMgr(qm1)
                    Time(2018-08-08T18:40:40.693Z)
                    CommentInsert1(app)
                    CommentInsert2(JmsPutGet (JMS))
                    CommentInsert3(Pipe returned 2035 [FAILED])

AMQ5534E: User ID 'app' authentication failed

EXPLANATION:
The user ID and password supplied by the 'JmsPutGet (JMS)' program could not be
authenticated.
Additional information: 'Pipe returned 2035 [FAILED]'.
ACTION:
Ensure that the correct user ID and password are provided by the application.
Ensure that the authentication repository is correctly configured. Look at
previous error messages for any additional information.

Connection problems

One of the most common areas to find problems is in the initial connection. This would give you a reason code such as MQ Reason Code 2538 MQRC_HOST_NOT_AVAILABLE or 2059 MQRC_Q_MGR_NOT_AVAILABLE. There are a few places errors can be introduced, some initial things to look at are:

  • Check you can ping the host where the queue manager is running.
  • Check that you are using the correct port for the connection to the queue manager.

    The MQ Badge Challenge application will use 1414 unless you set the environment variable MQ_BADGE_QM_PORT to be something different. You may need to do this if you cannot use port 1414 for any reason, e.g. you have multiple Docker instances or queue managers running and port 1414 is already being used. To use a different port number you will need to expose a different port. You can then set your port environment variable:

    In a Windows terminal:

    set MQ_BADGE_QM_PORT=<your_port>

    On Linux:

    export MQ_BADGE_QM_PORT=<your_port>
  • Check that you are using the correct host for the connection to the queue manager.

    The MQ Badge Challenge application will use ‘localhost’ unless you set the environment variable MQ_BADGE_QM_HOSTNAME to be something different. You may need to do this if you are running your queue manager in an older version of Docker. The latest version of Docker maps the host ip address to localhost, however Docker Toolkit, which is the current option for running Docker on Windows 7, maps the host ip to the Virtual Machine ip address. To find this ip address you can run the following command in docker

    docker-machine ip

    You can then run the command

    set MQ_BADGE_QM_HOSTNAME=<your_ip_address>

    in a Windows terminal for this host address to be used in your application.

  • Check you are using the correct queue manager and channel names in your application connection details. These are case-sensitive. In the MQ Badge Challenge application, the environment variables MQ_BADGE_QM_NAME and MQ_BADGE_QM_CHANNEL have also been externalised if you do not wish to use the default values.
  • Check that your queue manager is running:

    On the system where your queue manager is hosted, run the dspmq command directly in a terminal window:

    dspmq

    For Docker instances you would use the following command to gain command line access and run dspmq:

    docker exec -ti <container_id> dspmq

    The output of dspmq is a list of the queue managers on the system and their status:

    QMNAME(QM1)                                               STATUS(Running)

Configuration errors

My application connects, but fails to run?

The main areas to check carefully are if all of your MQ object names match what is expected. For example, the following error is produced when the wrong queue name is given:

com.ibm.msg.client.jms.DetailedInvalidDestinationException: JMSWMQ2008: Failed to open MQ queue ‘purchase_queue’.
JMS attempted to perform an MQOPEN, but IBM MQ reported an error.
Use the linked exception to determine the cause of this error. Check that the specified queue and queue manager are defined correctly.
    at com.ibm.msg.client.wmq.common.internal.Reason.reasonToException(Reason.java:513)
    at com.ibm.msg.client.wmq.common.internal.Reason.createException(Reason.java:215)
    at com.ibm.msg.client.wmq.internal.WMQMessageProducer.checkJmqiCallSuccess(WMQMessageProducer.java:1263)
    at com.ibm.msg.client.wmq.internal.WMQMessageProducer.checkJmqiCallSuccess(WMQMessageProducer.java:1220)
    at com.ibm.msg.client.wmq.internal.WMQMessageProducer.access$800(WMQMessageProducer.java:75)
    at com.ibm.msg.client.wmq.internal.WMQMessageProducer$SpiIdentifiedProducerShadow.initialise(WMQMessageProducer.java:816)
    at com.ibm.msg.client.wmq.internal.WMQMessageProducer.(WMQMessageProducer.java:1196)
    at com.ibm.msg.client.wmq.internal.WMQSession.createProducer(WMQSession.java:1127)
    at com.ibm.msg.client.jms.internal.JmsSessionImpl.createProducer(JmsSessionImpl.java:1504)
    at com.ibm.mq.jms.MQSession.createProducer(MQSession.java:661)
    at com.ibm.mq.demo.TicketRequester.put(TicketRequester.java:88)
    at com.ibm.mq.demo.Reseller.main(Reseller.java:65)
Caused by: com.ibm.mq.MQException: JMSCMQ0001: IBM MQ call failed with compcode ‘2’ (‘MQCC_FAILED’) reason ‘2085’ (‘MQRC_UNKNOWN_OBJECT_NAME’).
    at com.ibm.msg.client.wmq.common.internal.Reason.createException(Reason.java:203)
    ... 10 more
        

In this case the logs are telling us that the queue ‘purchase_queue’ does not exist. Next steps would be to check your configuration using runmqsc (see section 8) and/or change your code accordingly.

Security issues

Another common area that can cause problems is authentication. Security problems generally return a reason code of AMQ2035 2035 MQRC_NOT_AUTHORIZED. If you see this then you know that a connection has been attempted, but there is likely something wrong with the username or password being used. Looking in the error logs will tell you the User ID that is being authenticated.

In the MQ Badge Challenge application, the username and password are coded into the application to be supplied to the queue manager. Check that the correct values have been set. If you are using anything other than the default application username and password, these values can either be changed in the code we have provided, or the default values can be overridden by setting the environment variables MQ_BADGE_USERNAME and MQ_BADGE_PASSWORD

Further information about client application security can be found here.

Publish/subscribe errors

Problems with publish/subscribe are usually due to one of the following reasons:

  • The subscriber topic strings do not match with the publisher.
  • The subscription was created after the publication was sent.
  • An error occurred in the publication but was not checked by the publishing application.

These would result in not receiving the messages you were expecting.

Interact with the queue manager using MQSC.

MQSC commands enable you to perform administration tasks to configure your queue manager and work with queue manager objects such as channels and queues.

It can be really helpful to know how to find out about the attributes set on different MQ objects (e.g. qmgrs, queues, channels), particularly if you’re not familiar with the default settings. One of the ways to do this is to use MQSC. See here for reference.

For Docker instances you will need command line access in the container running the queue manager:

docker exec -ti <container_id> /bin/bash

From here (or the command line of any platform):

runmqsc <your_queue_manager_name>

When you see,

Starting MQSC for queue manager <your_queue_manager_name>

the interface is ready for your input.

You can use the DISPLAY command to explore some of the objects in the MQ Badge Challenge. e.g. DISPLAY CHANNEL(DEV.APP.SVRCONN), DISPLAY TOPIC('newTickets') and DISPLAY QUEUE('purchase').

The output of DISPLAY QUEUE(‘purchase’) will look something like this:

   DISPLAY QUEUE('purchase')
       14 : DISPLAY QUEUE('purchase')
   AMQ8409I: Display Queue details.
      QUEUE(purchase)                         TYPE(QLOCAL)
      ACCTQ(QMGR)                             ALTDATE(2018-09-11)
      ALTTIME(13.13.45)                       BOQNAME( )
      BOTHRESH(0)                             CLUSNL( )
      CLUSTER( )                              CLCHNAME( )
      CLWLPRTY(0)                             CLWLRANK(0)
      CLWLUSEQ(QMGR)                          CRDATE(2018-09-11)
      CRTIME(13.13.45)                        CURDEPTH(0)
      CUSTOM( )                               DEFBIND(OPEN)
      DEFPRTY(0)                              DEFPSIST(NO)
      DEFPRESP(SYNC)                          DEFREADA(NO)
      DEFSOPT(SHARED)                         DEFTYPE(PREDEFINED)
      DESCR( )                                DISTL(NO)
      GET(ENABLED)                            HARDENBO
      IMGRCOVQ(QMGR)                          INITQ( )
      IPPROCS(1)                              MAXDEPTH(5000)
      MAXMSGL(4194304)                        MONQ(QMGR)
      MSGDLVSQ(PRIORITY)                      NOTRIGGER
      NPMCLASS(NORMAL)                        OPPROCS(0)
      PROCESS( )                              PUT(ENABLED)
      PROPCTL(COMPAT)                         QDEPTHHI(80)
      QDEPTHLO(20)                            QDPHIEV(DISABLED)
      QDPLOEV(DISABLED)                       QDPMAXEV(ENABLED)
      QSVCIEV(NONE)                           QSVCINT(999999999)
      RETINTVL(999999999)                     SCOPE(QMGR)
      SHARE                                   STATQ(QMGR)
      TRIGDATA( )                             TRIGDPTH(1)
      TRIGMPRI(0)                             TRIGTYPE(FIRST)
      USAGE(NORMAL)

Interesting attributes to note here are maxdepth, which is the number of messages the queue can hold; and curdepth, which is the number of messages currently held on the queue. If the number of messages on the queue reaches the maxdepth, the application will fail with an MQ Reason Code 2053 MQRC_Q_FULL. A couple of ways to solve this problem would be to increase the default maxdepth of 5000, or to make sure the sending application can handle a reason code of 2053 (MQRC_Q_FULL) by e.g. pausing the application or putting the messages to another queue.

Interact with the queue manager using the MQ Console.

Another way to interact with your queue managers is with the MQ Console. As well as being able to browse and change object attributes, you can also use the Console to help validate your setup by putting a test message on a queue. (Another way to validate your setup would be to run the samples, such as amqsputc, if you have access to them.)

I can’t connect in my browser?

  • You might find that going to https://localhost:9443/ibmmq/console/ doesn’t work if you are running your queue manager in docker. Use the docker command docker-machine ip to check the ip address you should use in place of localhost.
  • Check if port 9443 has been assigned for the MQ Console to use when you started your container. Make sure you are using the right port number if you changed this for any reason.

But I can’t see any information about my queues?

  • If the MQ objects you are interested in don’t automatically appear on the Console page, use the Add widget button to display the information you would like to see.

Congratulations! You debugged like a pro and everything totally works.
Go forth and develop.