0

As a requirement of our partner, We have to make MQ connections on different ports. And the requirement is to configure separate CCDT files for each port because. All connections are made on one client application (one Process).

Because our client application is one Process I can't configure the below environment variables for each port separately.

How environment variables are set for configuring Client Channel Definition (This is .NET C#):

        Environment.SetEnvironmentVariable("MQCHLLIB", @"C:\ProgramData\IBM\MQ");
        Environment.SetEnvironmentVariable("MQCHLTAB", "AMQCLCHL<PORT>.TAB");

Our problem; We have to set these environment variables on connection level and not on Process or Global level. Any suggestions?

Update below is from info gathered in comments and Chat:

  1. Requirement is to configure Header and Message compression with XMS.NET.
  2. Per IBM's answer to IBM Community Forums post "Header and message compression on IBM.XMS with C# .NET" XMS.NET can only utilize compression using a CCDT.
  3. CCDT Entries have QMNAME(*).
  4. Difference between CCDT entries is only the PORT.
JoshMc
  • 10,239
  • 2
  • 19
  • 38
Ozkan
  • 3,880
  • 9
  • 47
  • 78
  • Options: 1. Anything specified in the CCDT should be able to be specified in your program directly. 2. You can pull your JNDI information from a binding file. Each CF can point to a different CCDT. 3. Instead of your the ENV variables use `mqclient.ini` to point to the CCDT. The first place MQ will look for the ini is in the current working directory, change to a port specified directory before each connection, since you are multi threaded this will have similar problems as setting ENV, as long as you can implement locking so only 1 thread connects at a time either ENV or ini could work. – JoshMc Jul 16 '18 at 09:43
  • 4. Dump contents of all individual CCDT files and create a single combined CCDT. As long as `QMNAME` and `CHANNEL` name are unique for each it is probably the easiest. – JoshMc Jul 16 '18 at 09:46
  • @JoshMc but our partner clearly says to use separate CCDT files for each connection. Here is a quote: "The application must not rely on the CCDT to load-balance the connections to the Queue Managers, as CCDT doesn’t guarantee connections will be established to all Queue Managers. The application must explicitly create the connections against the queue managers, using 1 distinct CCDT per Queue Manager" – Ozkan Jul 16 '18 at 09:50
  • Look at each CCDT and see how many entries are present and for each entry look at CHL, QMNAME, PORT. Provide sanitized values in the question for further input. – JoshMc Jul 16 '18 at 09:55
  • I created these CCDT using runmqsc -n myself so I can recreate them if necessary – Ozkan Jul 16 '18 at 09:57
  • @JoshMc and option 1 is impossible for us because only way of setting channel compression using XMS is with CCDT. – Ozkan Jul 16 '18 at 09:58
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/176042/discussion-between-ozkan-and-joshmc). – Ozkan Jul 16 '18 at 09:58
  • Are you sure there is no binding file parameter for compression? – JoshMc Jul 16 '18 at 09:59
  • What do you mean with a binding file? Didn't encounter that as client. Compression is done like this: DEFINE CHANNEL .... COMPHDR() COMPMSG() ..... Can we continue in chat please? – Ozkan Jul 16 '18 at 10:02
  • Can you dynamically build your CF objects in the code. Looks like it is possible to dynamically set the values on the CF in JMS, so based on IBM's goal of XMS being like JMS it should be possible in XMS. https://www.ibm.com/support/knowledgecenter/en/SSFKSJ_8.0.0/com.ibm.mq.dev.doc/q032550_.htm – JoshMc Jul 16 '18 at 18:08
  • @JoshMc MQConnectionFactory is not İBM.XMS. I have similar question here : http://www.mqseries.net/phpBB2/viewtopic.php?t=75476&sid=4d708dbcc2bc2ed558785a8863cc221c – Ozkan Jul 16 '18 at 19:26
  • 1
    Ozkan, with MQ 9 2 or higher you can now use a JSON CCDT that no longer has a limit on the channel name being unique, so you could create a JSON CCDT with four entries (one per port) and just specify the QMNAME on each as a different value. In your code where you specify the QMNAME to connect to just use the same value with a '*' prefix. – JoshMc Nov 22 '22 at 10:41

2 Answers2

1

Are you saying that once you start your application (process), it will connect & disconnect to/from different queue managers in one execution? If so, then setting the environment variables then changing them on the fly will not work.

A better approach is to have an INI file with 4 sections - 1 per port. Have your application load the particular section from the INI file, create a Hashtable with those particular values and pass the Hashtable to the MQQueueManager class.

For more information about reading an INI file see: https://code.msdn.microsoft.com/windowsdesktop/Reading-and-Writing-Values-85084b6a

I would set your 1414 section of the INI file as:

[Port1414]
mq.qmname=MQA1
mq.channel=TEST.CHL
mq.hostname=10.10.10.10
mq.port=1414
mq.userid=MyUserId
mq.inputq=SOME.INPUT.QUEUE
mq.outputq=SOME.OUTPUT.QUEUE

And for 1415 section of the INI file as:

[Port1415]
mq.qmname=MQA1
mq.channel=TEST.CHL
mq.hostname=10.10.10.10
mq.port=1415
mq.userid=MyUserId
mq.inputq=SOME.INPUT.QUEUE2
mq.outputq=SOME.OUTPUT.QUEUE2

and the same for the 1415 & 1416.

After reading the particular section of the INI file, you would do:

Hashtable qMgrProp = new Hashtable();
qMgrProp.Add(MQC.TRANSPORT_PROPERTY, MQC.TRANSPORT_MQSERIES_MANAGED);
qMgrProp.Add(MQC.CHANNEL_PROPERTY, channelName);
qMgrProp.Add(MQC.HOST_NAME_PROPERTY, hostname);
qMgrProp.Add(MQC.PORT_PROPERTY, 1414);
qMgrProp.Add(MQC.USER_ID_PROPERTY, userId);

MQQueueManager qMgr = new MQQueueManager(qManager, qMgrProp);
Roger
  • 7,062
  • 13
  • 20
  • But I have to use CCDT with XMS. You show me MQQueueManager which is not XMS and without CCDT. Thanks anyway – Ozkan Jul 16 '18 at 17:48
  • A CCDT is one of many ways that an application can load MQ configuration values from. You didn't mention XMS in your question. My post is still valid, you just use MQ XMS class for the queue manager. The reason your partner is saying to use a CCDT file is that there are a lot of newbies using MQ and using a CCDT file will help keep the errors to a minimum. – Roger Jul 16 '18 at 18:12
  • The reason we need CCDT is because we only can configure channel compression using CCDT. İn .net ibm.xms there is no other way – Ozkan Jul 16 '18 at 19:20
  • İ mentioned xms in the question tags btw – Ozkan Jul 16 '18 at 19:21
  • check this question: http://www.mqseries.net/phpBB2/viewtopic.php?t=75476&sid=4d708dbcc2bc2ed558785a8863cc221c – Ozkan Jul 16 '18 at 19:29
  • Been there, done that with C & Java - which should work in .NET. See my comments about Java & compression here: http://www.mqseries.net/phpBB2/viewtopic.php?t=62445 You can use the same MQ Hashtable properties in C# .NET – Roger Jul 16 '18 at 19:38
  • Yes but @Roger when I configure the app that way, it isn't IBM.XMS anymore. Those classes are located in another dll named amqmdnet instead of IBM.XMS.dll. XMSFactoryFactory is used to create connectionfactory, and this class doesn't accept hdrcomplist or msgcomplist. There is no option to set these compression lists using xms. I only found a method in MQEnvironment but this is also not in IBM.XMS, this is also located in the dll amqmdnet – Ozkan Jul 16 '18 at 19:45
  • Open a PMR with IBM – Roger Jul 17 '18 at 19:11
1

Option 1 (This seems simpler if it works since you remove the need for CCDT which you are using because it was the only previously known way to specify compression options):

Based on a combination of documentation for both JMS and XMS I think the following may work, please try it, if this does not work then I will remove this from my answer, if it does work then I'll update with links to the mixture of documentation.

var factory = XMSFactoryFactory.GetInstance(XMSC.CT_WMQ);
var cf = factory.CreateConnectionFactory();
cf.SetStringProperty(XMSC.WMQ_HOST_NAME, host);
cf.SetIntProperty(XMSC.WMQ_PORT, port);
cf.SetStringProperty(XMSC.WMQ_CHANNEL, channel);
//empty string "" or "*" would work equally well for XMSC.WMQ_QUEUE_MANAGER to accept any queue manager name
cf.SetStringProperty(XMSC.WMQ_QUEUE_MANAGER, "");
cf.SetIntProperty(XMSC.WMQ_CONNECTION_MODE, XMSC.WMQ_CM_CLIENT_UNMANAGED);
cf.SetStringProperty(XMSC.WMQ_HEADER_COMP, "SYSTEM NONE");
cf.SetStringProperty(XMSC.WMQ_MSG_COMP, "ZLIBFAST ZLIBHIGH RLE NONE");
connection = cf.CreateConnection();

Option 2 directly specifying the CCDT locations to the XMSFactoryFactory and not relying on the environment variables:

Create the CF with a link to the CCDT directly instead of using Environment variables.

var factory = XMSFactoryFactory.GetInstance(XMSC.CT_WMQ);
var cf = factory.CreateConnectionFactory();
cf.SetIntProperty(XMSC.WMQ_CONNECTION_MODE, XMSC.WMQ_CM_CLIENT_UNMANAGED);
cf.SetStringProperty(XMSC.WMQ_CCDTURL, @"file://C:\ProgramData\IBM\MQ\AMQCLCHL<PORT>.TAB";
cf.SetStringProperty(XMSC.WMQ_QUEUE_MANAGER, "*");
connection = cf.CreateConnection();
JoshMc
  • 10,239
  • 2
  • 19
  • 38
  • Option 1 does not work unfortunately. Option 2 has no effect either. I set it to "file://C:\AMQCLCHL1414.TAB" for example but in the event viewer I can see it always looks for a file 'C:\ProgramData\IBM\MQ\AMQCLCHL.TAB' – Ozkan Jul 18 '18 at 06:34
  • Is it because I'm using IBM MQ Client 8.0.0.5? Maybe it's supported in v9? – Ozkan Jul 18 '18 at 06:37
  • 1
    This answer shows basically the same thing as I posted except they escape each ``\`` like ``\\`` where I added the `@` in front of the string so each did not need to be escaped. https://stackoverflow.com/questions/26142127/websphere-mq-changing-channel-definition-structure-using-xms-net-api/26190345#26190345 – JoshMc Jul 18 '18 at 08:17
  • 1
    [IV20954](http://www-01.ibm.com/support/docview.wss?uid=swg1IV20954) indicates that problems with XMS using CCDT were fixed in 7.0.1.10 and 7.1.0.2 so should be fixed in 8.0.0.5. This APAR also was reporting that the app would receive a `MQRC 2278` not that the setting was being ignored. Are you sure you have removed all references to the `MQCHLLIB`/`MQCHLTAB` environment variables as well as any `mqclient.ini` file pointing to a channel table located either in `C:\ProgramData\IBM\MQ` or in the current working directory of the application? – JoshMc Jul 18 '18 at 08:40
  • 1
    Can you run a .NET trace using the instructions on the IBM KC page "[Using the stand-alone IBM MQ .NET client](https://www.ibm.com/support/knowledgecenter/en/SSFKSJ_8.0.0/com.ibm.mq.dev.doc/q123550_.htm)". In this search for the string `AMQCLCHL.TAB` and see if you can determine where that is being picked up from or of the CCDT_URL setting is being ignored. – JoshMc Jul 18 '18 at 08:43
  • Is [IV20954](http://www-01.ibm.com/support/docview.wss?uid=swg1IV20954) for unmanaged connections? Because connection type + connection mode is configured as `XMSC.CT_WMQ`. We have connection mode configured as `XMSC.WMQ_CM_CLIENT_UNMANAGED`. We need to use unmanaged mode for SSL. I tried with CT_WMQ (client mode) then it reads the correct CCDT file as expected, in unmanaged mode it just ignores the file... – Ozkan Jul 18 '18 at 09:05
  • I'm busy with the trace now. – Ozkan Jul 18 '18 at 09:13
  • I try same settings, once with client mode and once with unmanaged mode. Event viewer gives different output related to CCDT. in unmanaged it looks for the default location: Client mode event viewer event: http://pasted.co/27db600f (CCDT does not exist but it looks in the right directory which is good) Unmanaged mode event viewer event: http://pasted.co/d5979a2c – Ozkan Jul 18 '18 at 09:20
  • @Ozkan IBM also said that the reason `XMSC.WMQ_CCDTURL` was not supported in Unmanaged XMS.NET was due to the underlying MQ C API libraries not supporting a way to set it programmatically, and they stated they planned to document this limitation in the IBM MQ Knowledge center. While it is true that the MQ C API libraries can not set the location of a CCDT programmatically up to and including MQ v8.0, at MQ v9.0 IBM did add a way to set this programmatically. I updated the PMR to point this out, I'll comment back or update my answer once IBM responds back if they will fix it in 9.0 and later. – JoshMc Jan 23 '19 at 05:05