This is part of a series of small blog posts which will cover some of the smaller, perhaps less likely to be noticed, features of IBM MQ. Read other posts in this series.
There are many cases where you might need to communicate with one queue manager through another queue manager. This is sometimes referred to as "going via" another queue manager. It is commonly, but in no way solely, used for administration tasks, for example sending MQSC commands, or using a GUI admin tool using PCF messages like MQ Explorer or MO71.
It is often described as requiring a transmission queue of the same name as the target queue manager sender/receiver channel pairs to deliver the messages. Often there is also a return route with the same in the opposite direction, as shown in the diagram below.

While this is indeed one way to configure a system where you wish to communicate with one queue manager (QM2) via another queue manager (QM1), it is certainly not the only way. The only actual requirement is the ability to resolve the MQOPEN of "Q on QM2" which means being able to resolve the routing to the name queue manager. Once the message gets to QM2, resolution to the queue can then be successful, but until then, other queue manager are simply trying to get the message to QM2.
Another way to resolve the routing to a named queue manager is if the queue manager's are part of the same cluster, When a queue manager is a member of a cluster, an application connected to it can discover how to sent messages to a queue (even a non-clustered queue) on another member queue manager, for example the SYSTEM.ADMIN.COMMAND.QUEUE. While this is very useful for MQ administration going via another queue manager, you must also be alert and ensure your security is set up to ensure this is not wide open for anyone to use to send in what could be quite destructive commands (e.g. DELETE QLOCAL!).

If you're not using clustering, you still don't have to use the first method, there are other, slightly more complex methods of configuration using queue manager alias, and reply-to-queue aliases. These however, require your application to be aware of the fact that the reply-to-queue alias it used to fill in the MQMD ReplyTo fields is not the same queue as it should be getting it's replies from. Most MQ administration tools are not set up to be able to do this, so I have not included this particular setup as an example in this blog post. If anyone is interested in seeing how to route requests and responses over a different set of transmissions queues and channels, for example to apply encryption to them, let me know in the comments, and I will create a separate blog post for it.
Troubleshooting Via mode
When using remote messaging, as via mode is doing, the troubleshooting you need to do is different to when you are directly connected to your target queue manager.
You can use the DISPLAY CHSTATUS command to see whether you message(s) go across the channel, and to see whether your replies comes back. If you see the MSGS attribute increase, you know they got this far and therefore know on which system to dig further.
Your application does not get to see all the return codes directly, some of the failures to put messages will be seen by the channels. What does a channel do when it gets a bad return code on an MQPUT? It writes the message to the Dead-Letter Queue (DLQ) with a header (MQDLH) describing the failure (provided the message does not use the report option MQRO_DISCARD).
Most of the failures are likely to be with the return route - your replies don't appear for example. Make sure you have a DLQ on both systems, and check the messages that arrive there. Here's an example of a message on the DLQ from a failure case.
Message Descriptor (MQMD)
Version :1
Report :01000000
01000000 Exception reports required
Message Type :1 (Request msg)
Expiry :-1
Feedback :0 (None)
Format :'MQDEAD '
Persistence :0 (Not Persistent)
Message Id :414D5120514D322020202020202020202C34C75C2484B516
A M Q Q M 2 , 4 . \ $ . . .
Correl. Id :000000000000000000000000000000000000000000000000
. . . . . . . . . . . . . . . . . . . . . . . .
ReplyToQ :'AMQ.5CC7342424E84408 '
ReplyToQMgr :'QM1 '
UserId :'mqgusr1 '
[ 252 bytes] Message Content
[ 252 bytes] Dead Letter Queue Header (MQDLH)
StrucId :'DLH '
Version :1
Reason :2035 (Not authorized)
Dest. Queue :'AMQ.5CC7342424E84408 '
Dest. QMgr :'QM1 '
Format :'MQADMIN '
PutApplType :7 (Queue Manager)
PutApplName :'C:\mqm9110\bin64\runmqsc.exe'
[ 80 bytes] Admin Header (MQCFH)
Type :1 (Command)
Struc Length :36
Version :1
Command :38 (Escape Command)
Sequence No. :1
Control :1 (Last)
CompCode :0 (OK)
Reason :0 (OK)
Parm Count :2
[ 44 bytes] Integer (MQCFIN)
Type :3 (Integer)
Struc Length :16
Parameter Id :1017 (Escape Type)
Value :1 [0x'1']
[ 28 bytes] String (MQCFST)
Type :4 (String)
Struc Length :28
Parameter Id :3014 (Escape Text)
CCSID :0 (Queue Manager)
String Length:8
Value :'DIS QMGR'
In this case, the user ID I used (mqgusr1) to connect with on QM1, does not have the required authority to do anything on QM2, and so when the command server attempts to issue the command on its behalf, it fails
So there you have it. There are several configurations you can use to achieve going via another queue manager - it is not necessary to be forced into the model of a transmission queue with the same name as the target queue manager, especially if you are already set up as a cluster.
I was prompted to write this post because of a question on mqseries.net.
#Little-Gem#IBMMQ#ChampionsCorner