MQRC_UNKNOWN_ALIAS_BASE_Q when connecting with IBM MQ cluster using CCDT and Spring Boot JMSTemplate - spring-boot

I have a Spring Boot app using JMSListener + IBMConnectionFactory + CCDT for connecting an IBM MQ Cluster.
A set the following connection properties:
- url pointing to a generated ccdt file
- username (password not required, since test environment)
- queuemanager name is NOT defined - since it's the cluster's task to decide, and a few google results, including several stackoverflow ones indicate that in my case qmgr must be set to empty string.
When my Spring Boot JMSListener tries to connect to the queue, the following MQRC_UNKNOWN_ALIAS_BASE_Q error occurs:
2019-01-29 11:05:00.329 WARN [thread:DefaultMessageListenerContainer-44][class:org.springframework.jms.listener.DefaultMessageListenerContainer:892] - Setup of JMS message listener invoker failed for destination 'MY.Q.ALIAS' - trying to recover. Cause: JMSWMQ2008: Failed to open MQ queue 'MY.Q.ALIAS'.; nested exception is com.ibm.mq.MQException: JMSCMQ0001: IBM MQ call failed with compcode '2' ('MQCC_FAILED') reason '2082' ('MQRC_UNKNOWN_ALIAS_BASE_Q').
com.ibm.msg.client.jms.DetailedInvalidDestinationException: JMSWMQ2008: Failed to open MQ queue 'MY.Q.ALIAS'.
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)
In the MQ error log I see the following:
01/29/2019 03:08:05 PM - Process(27185.478) User(mqm) Program(amqrmppa)
Host(myhost) Installation(Installation1)
VRMF(9.0.0.5) QMgr(MyQMGR)
AMQ9999: Channel 'MyCHL' to host 'MyIP' ended abnormally.
EXPLANATION:
The channel program running under process ID 27185 for channel 'MyCHL'
ended abnormally. The host name is 'MyIP'; in some cases the host name
cannot be determined and so is shown as '????'.
ACTION:
Look at previous error messages for the channel program in the error logs to
determine the cause of the failure. Note that this message can be excluded
completely or suppressed by tuning the "ExcludeMessage" or "SuppressMessage"
attributes under the "QMErrorLog" stanza in qm.ini. Further information can be
found in the System Administration Guide.
----- amqrmrsa.c : 938 --------------------------------------------------------
01/29/2019 03:15:14 PM - Process(27185.498) User(mqm) Program(amqrmppa)
Host(myhost) Installation(Installation1)
VRMF(9.0.0.5) QMgr(MyQMGR)
AMQ9209: Connection to host 'MyIP' for channel 'MyCHL' closed.
EXPLANATION:
An error occurred receiving data from 'MyIP' over TCP/IP. The connection
to the remote host has unexpectedly terminated.
The channel name is 'MyCHL'; in some cases it cannot be determined and so
is shown as '????'.
ACTION:
Tell the systems administrator.
Since the MQ error log contains QMgr(MyQMGR), which MyQMGR value I did not set in the connection properties, I assume the routing seems to be fine: the MQ Cluster figured out a qmgr to use.
The alias exists and points to an existing q. Bot the target q and the alias are added to the cluster via the CLUSTER(clustname) command.
What can be wrong?

Short Answer
MQ Clustering is not used for a consumer application to find a queue to GET messages from.
MQ Clustering is used when a producer application PUTs messages to direct them to a destination.
Further reading
Clustering is used when messages are being sent to help provide load balancing to multiple instances of a clustered queue. In some cases people use this for hot/cold failover by having two instances of a queue and keeping only one PUT(ENABLED).
If an application is a producer that is putting messages to a clustered queue, it only needs to be connected to a queue manager in the cluster and have permissions to put to that clustered queue. MQ based on a number of different things will handle where to send that message.
Prior to v7.1 there was only two ways to provide access to remote clustered queues:
Using a QALIAS:
Define a local QALIAS which has a TARGET set to the clustered queue name
Note this QALIAS does not itself need to be clustered.
Grant permission to put to the local QALIAS.
Provide permissions to PUT to the SYSTEM.CLUSTER.TRANSMIT.QUEUE.
The first option allows for granting granular access to an application for specific clustered queues in the cluster. The second option allows for the application to put to any clustered queue in the cluster or any queue on any clustered queue manager in the cluster.
At 7.1 IBM added a new optional behavior, this was provided with the setting ClusterQueueAccessControl=RQMName in the Security stanza of the qm.ini. If this is enabled (it is not the default), then you can actually provide permission for the app to PUT to the remote clustered queues directly without the need for a local QALIAS.
What clustering is not for is consuming applications such as your example of a JMSListener.
An application that will consume from any QLOCAL (clustered or not) must be connected to the queue manager where the QLOCAL is defined.
If you have a situation where there are multiple instances of a clustered QLOCAL that are PUT(ENABLED), you would need to ensure you have consumers connected directly to each queue managers that an instance is hosted on.
Based on your comment you have a CCDT with an entry such as:
CHANNEL('MyCHL') CHLTYPE(CLNTCONN) QMNAME('MyQMGR') CONNAME('node1url(port1),node2url(port2)')
If there are two different queue managers with different queue manager names listening on node1url(port1) and node2url(port2), then you have different ways to accomplish this from the app side.
When you specify the QMNAME to connect to the app will expect the name to match the queue manager you connect to unless it meets one of the following:
If you specify *MyQMGR it will find the channel or channels with QMNAME('MyQMGR') and pick one and connect and will not enforce that the remote queue manager name must match.
If in your CCDT you have QNAME(''), it is set to NULL, then in your app you can specify a empty queue manager name or only a space and it will find this entry in the CCDT and will not enforce that the remote queue manager name must match.
In your app you specify the queue manager name as *, MQ will use any channel in the CCDT and will not enforce that the remote queue manager name must match.
One limitation of CCDT is that channel name must be unique in the CCDT. Even if the QMNAME is different you can't have a second entry with the same channel name.
When you connect you are hitting the entry with two CONNAME's and getting connected to the first IP(port), you would only get to the second IP(port) if at connect time the first is not available, MQ will try the second, or if you are connected and have RECONNECT enabled and then the first goes down MQ will try to connect to the first then second.
If you want to have both clustered queue PUT(ENABLED) to receive traffic then you want to be able to specifically connect to each of the two queue managers to read those queues.
I would suggest you add a new channel on each queue manager that has a different QM specific name that is also different from the existing name, something like this:
CHANNEL('MyCHL1') CHLTYPE(CLNTCONN) QMNAME('MyQMGR1') CONNAME('node1url(port1)')
CHANNEL('MyCHL2') CHLTYPE(CLNTCONN) QMNAME('MyQMGR2') CONNAME('node2url(port2)')
This would be in addition to the existing entry.
For your putting components you can continue to use the channel that can connect to either queue manager.
For your getting components you can configure at least two of them, one to connect to each queue manager using the new queue manager specific CCDT entries, this way both queues are being consumed.

Related

Is it possible to connect more than one IBM MQ queue manager in the same same process?

Based on IBM MQ doc, I need to define a environment variable named MQSERVER for the MQ server address. So in one process, can I only have one MQ server address, is it correct?
Is there any other way to define MQ server address and have multiple MQ connections to different MQ servers?
You can specify the channel name, host, and port in the MQCD which is referenced from the MQCNO. In C you would pass this to the MQCONNX function.
You can also specify connection details (channel name, host, and port) in a CCDT (Client Channel Definition Table). You would point to the CCDT with the following environment variables (there are other ways but this is one way):
MQCHLLIB=/path/to/table
MQCHLTAB=table_filename.TAB
You could then use MQCONN (or MQCONNX) and specify just the queue manager name. MQ will find an entry in the CCDT that matches the queue manager name and use the connection details provided.
You specify the channel name, host, and port in the MQCD which is referenced from the MQCNO. In C it is the MQCONNX call that allows this. If you specify things in the CCDT then you point to the CCDT with MQCHLLIB=/path/to/table and MQCHLTAB=table_filename.TAB, then you can issue a normal MQCONN (or MQCONNX) call and specify just the queue manager name. It will find this QMNAME in the CCDT and use the connection details provided in the CCDT. – JoshMc 21 mins ago

MQ error code 2058 when connecting to queue manager by name

I'm experiencing an odd behavior when running basic connectivity tests from my workstation to a remote MQ Server.
I am using amqssslc.exe to connect from a command prompt.
If I connect with nothing but a certificate store, it connects without issue, and returns a result indicating that it connected to the default queue manager, FOO:
C:\Program Files\IBM\MQ\Tools\c\Samples\Bin64>amqssslc.exe -k c:\mycerts\cert
Sample AMQSSSLC start
Connecting to the default queue manager
No client connection information specified.
Using SSL key repository stem c:\mycerts\cert
No OCSP configuration specified.
Connection established to queue manager FOO
Sample AMQSSSLC end
If I attempt to connect to the queue manager FOO, however, it returns a 2058 error, which typically indicates a queue manager name error.
C:\Program Files\IBM\MQ\Tools\c\Samples\Bin64>amqssslc.exe -k c:\mycerts\cert -m FOO
Sample AMQSSSLC start
Connecting to queue manager FOO
No client connection information specified.
Using SSL key repository stem c:\mycerts\cert
No OCSP configuration specified.
MQCONNX ended with reason code 2058
It does this even if I copy the name directly from the result. It fails quickly, and doesn't generate a log entry in my AMQERR01.LOG file.
Does this behavior indicate an issue with my CCDT file?
Update:
Per #JoshMc's suggestion, I ran the following command to get information about the vendor-supplied CCDT file:
echo DIS CHL(*) QMNAME CONNAME|runmqsc -n
The results indicated that no queue manager was specified in the file:
C:\Program Files\IBM\MQ\Tools\c\Samples\Bin64>echo DIS CHL(*) QMNAME CONNAME|runmqsc -n
5724-H72 (C) Copyright IBM Corp. 1994, 2016.
Starting local MQSC for 'MYQUEUE.TAB'.
1 : DIS CHL(*) QMNAME CONNAME
AMQ8414: Display Channel details.
CHANNEL(FOOCHANNEL) CHLTYPE(CLNTCONN)
CONNAME(CONNAME(xxx.xxx.xxx.xxx(1414),xxx.xxx.xxx.xxx(1414))
QMNAME( )
No commands have a syntax error.
If you review the source code located at C:\Program Files\IBM\MQ\Tools\c\Samples\Bin64\amqssslc.c you can see that it does the following:
If no queue manager name is specified it will set the queue manager name to NULL and print Connecting to the default queue manager
If no connection name is specified it will not setup the ClientConn, and ConnectOptions.ClientConnPtr is left at it's default NULL value, it will print No client connection information specified.
If a SSL key repository stem is specified it will set the SslConnOptions.KeyRepository to this value and print out Using SSL key repository stem <stem location> and then point ConnectOptions.SSLConfigPtr to the SslConnOptions.
After all of this it then issues a MQCONNX and specifies the the NULL queue manager name and the ConnectOptions. Because the ConnectOptions.ClientConnPtr is left at the default NULL value MQ will attempt to find the out how to connect to the queue manager via a few different other means. The order and where it looks for connection information is documented at the IBM v7.5 (or later) Knowledge Center page "Connecting IBM WebSphere MQ MQI client applications to queue managers". In your case it is picking up the CCDT file.
When you do not specify a queue manager name it looks for a entry in the CCDT with a blank QMNAME attribute and finds the CLNTCONN channel that you have defined where QMNAME is blank. A blank QMNAME on a CLNTCONN channel is a special case where the MQ client will connect to any queue manager name which is listening at CONNAME that you specify. Because you are specifying the SSL key repository stem it will use this key repository to connect to MQ with the SSLCIPH you have specified on CLNTCONN in the CCDT.
When you do specify the queue manager name FOO, it attempts to find a entry in the CCDT with the QMNAME attribute set to FOO, in your case it does not exist so you receive the 2058 or MQRC_Q_MGR_NAME_ERROR error.
Based on your update the CCDT channel does have a blank QMNAME attribute and the CONNAME lists two different IP(PORT) seperated by a common. With this configuration MQ will attempt first to connect to the first IP, if the connection times out or is ended for some other reason such as the channel on the queue manager being in STOPPED status, it will then attempt to connect to the second IP.
It is very possible they intend for you to connect with a blank or NULL queue manager name due to the benefit that the client will connect to any queue manager name that is listening on the CONNAME, in you case the first IP(PORT) might be queue manager FOO and the second IP(PORT) might be queue manager BAR.
If you want it to work with your CCDT when you specify -m FOO you would need to either create a new CCDT with a CLNTCONN channel with QMNAME(FOO), or add another CLNTCONN channel to your existing CCDT with QMNAME(FOO), note you can not have duplicate channel names in a single CCDT.
For more information on the CCDT and what queue manager name to specify see my answer to "Connecting to IBM MQ using CCDT file in JMS". The answer was related to JMS but the information applies to MQI clients as well.
You also have the option to specify all the details on the command line like Roger said. Run amqssslc.exe ? for usage information, it should look like this:
Sample AMQSSSLC start
Parameters: [-m QMgr]
[-c ChlName -x ConnName]
[-k KeyReposStem] [-s CipherSpec]
[-p any|rfc5280]
[-f] [-b none|128_bit|192_bit[,...] ]
[-o OcspURL]
I'm experiencing an odd behavior when running basic connectivity tests
from my workstation to a remote MQ Server.
Its not the program. You didn't specify enough parameters. Did you issue "amqssslc.exe ?" or look at the source? i.e. amqssslc.c
Where is the channel name? Where is the connection name? Where is the CipherSpec? etc...

Error AMQ4036 when trying to add a QueueManager to a Cluster in IBM MQ?

I am trying to setup a MQ Cluster that has the following config
There are 3 host machines, ubuntuvm-1, ubuntuvm-2 and ubuntuvm-3
ubuntuvm-1 has one Full repository queue manager and one partial repository queue manager. QM_FR1, QM_PR1
ubuntuvm-2 is same as above. QM_FR2, QM_PR2
ubuntuvm-3 has only one partial repository queue manager, QM_PR3
Following are the steps I have taken
I have created cluster receiver channels on each queue manager that point to its own queue manager.
I have created cluster sender channels that point to at least one full repository.
I have made sure that the channels are correct, i see the tests pass when I run them through the MQ Explorer.
I get an error when using MQ Explorer, I try to add the QM_FR1 queue manger to cluster (CLUSTER1).
Following is the error.
Access not permitted. You are not authorized to perform this operation. (AMQ4036)
Severity: 10 (Warning)
Explanation: The queue manager security mechanism has indicated that the userid associated with this request is not authorized to access the object.
Why am I getting this error and how do I fix this?
Please shout if you want me to provide more details.

IBM Cast Iron: MQ Put activity issues

I am trying to put a message into Websphere MQ queue from an Orchestration which is deployed on Cast Iron Live. I have used secure connector since the orchestation is deployed on Cast Iron. When I am trying to execute the flow, it fails and the message is not placed in MQ queue. The below are the errors:
Error while trying to call remote operation execute on Secure Connector for activity
com.approuter.module.mq.activity.MqPut and Secure Connector LocalSecureConnector,
error is Unable to put message on queue null. MQ returned error code 2538.
Unable to put message on queue null. MQ returned error code 2538.
Fault Name : Mq.Put.OperationActivityId : 163
Message: Unable to put message on queue null. MQ returned error code 2538.
Activity Name:Put MessageFault Time: 2015-07-15T05:40:29.711Z
Can someone please help me resolve this. Please let me know if any further details are required.
Here are the details:
Cast Iron flow is deployed on Cast Iron Cloud i.e Cast Iron Live
MQ is running on-premise
The port I am trying to connect is 1414.
Have a secure connector running on the machine where MQ is installed.
MQ version is 8.
In Cast Iron flow, I am using an MQ connector, by giving the hostname where MQ is running, port: 1414, Channel Name : SYSTEM.DEF.SVRCONN and username as mqm. Tired using my log on username, by adding it to mqm group. But this also dosent seem to work.
The return code is instructive:
2538 0x000009ea MQRC_HOST_NOT_AVAILABLE
This indicates that Cast Iron is attempting to contact MQ using a client connection and not finding a listener at the host/port that it is using.
There are a couple of possibilities here but not enough info to say which it might be. I'll explain and provide some diagnostics you can try.
The 2538 indicates an attempt to contact the QMgr has failed. This might be that, for example, the QMgr isn't listening on the configured port (1414) or that the MQ listener is not running.
The error code says the queue name is "null". The question doesn't specify which queue name the connector is configured with but presumably it's been configured with some queue name. This error code suggests the Secure Connector on the MQ server side doesn't have its configuration installed.
The Cast Iron docs advise connecting with an ID in the mqm group but do not mention that on any MQ version 7.1 or higher this is guaranteed to fail unless special provisions are made to allow the admin connection. It may be that it's actually failing for an authorization error and the connector not reporting the correct error.
If it is as simple as the listener not running, that's easy enough to fix. Just start it and make sure it's on 1414 as expected.
Next, ensure that the Secure Connector has the configuration that was created using the Cast Iron admin panel. You need to understand why the error code says the queue name is null.
Now enable Authorization Events and Channel Events in the QMgr and try to connect again. The connector on the MQ server should connect when started and if successful you can see this by looking at the MQ channel status. However, if unsuccessful, you can tell by looking at the event messages or the MQ error logs. Both of these will show authorization failures and connection attempts, if the connection has made it that far.
The reason I'm expecting 2035 Authorization Error failures is that any QMgr from v7.1 and up will by default allow an administrative connection on any channel. This is configured in the default set of CHLAUTH rules. The intent is that the MQ admin would have to explicitly provision admin access by adding one or more new CHLAUTH rules.
For reasons of security SYSTEM.DEF.* and SYSTEM.AUTO.* channels should never be used for legitimate connections. The Best Practice is to define a new SVRCONN, for example one named CAST.IRON.SVRCONN and then define a CHLAUTH rule to allow the administrative connection.
For example:
DEFINE CHL(CAST.IRON.SVRCONN) CHLTYPE(SVRCONN) TRPTYPE(TCP) REPLACE
SET CHLAUTH('CAST.IRON.SVRCONN') TYPE(ADDRESSMAP) +
ADDRESS('127.0.0.1') +
USERSRC(MAP) MCAUSER('mqm') +
ACTION(REPLACE)
SET CHLAUTH('CAST.IRON.SVRCONN') TYPE(BLOCKUSER) +
USERLIST('*NOBODY') +
WARN(NO) ACTION(REPLACE)
The first statement defines the new channel.
The next one allows the connections from 127.0.0.1 which is where the Secure Connector lives. (Presumably you installed the internal Secure Connection on the same server as MQ, yes?) Ideally the connector would use TLS on the channel and instead of IP filtering the CHLAUTH rule would filter based on the certificate Distinguished Name. This rule is not nearly so slective and allows anyone on the local host to be an MQ administrator by using this channel.
The last statement overrides the default CHLAUTH rule which blocks *MQADMIN with a new rule that blocks *NOBODY but just for that channel.

IBM Websphere MQ FTE (File Transfer Edition) - Agent cannot be published

I am quite new to MQ FTE and having issues to getting it work. Basically, I want to setup a simple environment between two queue managers that I can use to transfer files. Here is what i did:
One the first machine, I set up a queue manager and called it CMQ. Create a local queue called RECEIVED.MESSAGES and a remote queue SENT.MESSAGES. Also created a transmission queue.
Defined a transmission channels needed to communicate with the second queue manager.
One the second queue manager (SMQ), repeated the same process for creating local and remote queues, channels etc.
At this point, if I can both send and receive messages between the two Queue managers.
Next, on the first machine running queue manager CMQ, I carried out the following:
ran fteSetupCoordinate specifying the queue manager, host, port and channel SYSTEM.ADMIN.CONN
ran fteSetupCommand with the same details and specified host, port, channel (SYSTEM.ADMIN.CONN)
Ran the mqsc scipt file generated by fteSetupCoordinate.
Ran fteCreateAgent with QMgrName as CMQ, host, port and channel as SYSTEM.ADMIN.CONN
This is where the problem starts. The fteCreateAgent command end up with a message saying Agent was created successfully but could not registered with CMQ. The exact error is:
"BFGMQ1007I: The coordination queue manager cannot be contacted or has refused a connection attempt.
The WebSphere MQ reason code was 2058. The agent's presence will not be published.
I've tried every possible solution in forums and IBM's site including the troubleshooting found on this link:
But nothing works. As a result, the agent is never seen in MQ explorer. I also do not see the agent when I issue ftListAgent ..
Any ideas guys? Is there something I'm missing?
Thanks in advance
Get to know the mqrc command. It is your friend.
mqrc 2058
2058 0x0000080a MQRC_Q_MGR_NAME_ERROR
The error code you are getting back indicates that a connection was made to a QMgr but that it wasn't the one that was expected. That means either you have a typo in the QMgr name when you ran fteCreateAgent or you pointed the agent to the wrong QMgr.

Resources