Author |
Message
|
souciance |
Posted: Wed Feb 26, 2020 9:50 am Post subject: PCF call to get queue name from AS400 machine |
|
|
Disciple
Joined: 29 Jun 2010 Posts: 169
|
Hello,
Our scenario is as follows. We have a dotnet core application that uses the IBM MQ dotnet client apis. It issues PCF commands using PCFMessageAgent and PCFMessage to get list of queues with queue depth greater than zero.
The dotnet app runs on a windows machine.
When issuing this call against an MQ queue manager installed on a windows machine we get the queue name and everything works fine.
When issuing this call against an MQ queue manager that is installed on an AS400 with codepage 37 the queue names we get back are just jibberish like ?????@@@ . We have tried different ways to convert the queue name but nothing has worked.
Does anyone know what command to issue for MQ to convert the queue name to UTF8 or ASCII?
Thanks |
|
Back to top |
|
 |
Vitor |
Posted: Wed Feb 26, 2020 1:26 pm Post subject: Re: PCF call to get queue name from AS400 machine |
|
|
 Grand High Poobah
Joined: 11 Nov 2005 Posts: 26093 Location: Texas, USA
|
souciance wrote: |
When issuing this call against an MQ queue manager that is installed on an AS400 with codepage 37 the queue names we get back are just jibberish like ?????@@@ . |
Codepage 37 is an EBCDIC page.
souciance wrote: |
We have tried different ways to convert the queue name but nothing has worked. |
Name 3.
souciance wrote: |
Does anyone know what command to issue for MQ to convert the queue name to UTF8 or ASCII? |
I'd expect a get with convert to do it, hence my question about what you've tried. EBCDIC -> ASCII isn't exactly an unusual conversion of payload. _________________ Honesty is the best policy.
Insanity is the best defence. |
|
Back to top |
|
 |
souciance |
Posted: Wed Feb 26, 2020 1:51 pm Post subject: Re: PCF call to get queue name from AS400 machine |
|
|
Disciple
Joined: 29 Jun 2010 Posts: 169
|
Vitor wrote: |
souciance wrote: |
When issuing this call against an MQ queue manager that is installed on an AS400 with codepage 37 the queue names we get back are just jibberish like ?????@@@ . |
Codepage 37 is an EBCDIC page.
souciance wrote: |
We have tried different ways to convert the queue name but nothing has worked. |
Name 3.
souciance wrote: |
Does anyone know what command to issue for MQ to convert the queue name to UTF8 or ASCII? |
I'd expect a get with convert to do it, hence my question about what you've tried. EBCDIC -> ASCII isn't exactly an unusual conversion of payload. |
We are not trying to convert the payload. We are issuing PCF calls to get a list of queue names with a certain depth. It is the names that look gibberish when sending requests to AS400 queue managers. We are not looking to look at the payload. |
|
Back to top |
|
 |
PaulClarke |
Posted: Wed Feb 26, 2020 2:09 pm Post subject: |
|
|
 Grand Master
Joined: 17 Nov 2005 Posts: 1002 Location: New Zealand
|
Can you share what call you are using to get the command server response on your Windows machine ?
I think was Vitor was suggesting is that you use the MQGMO_CONVERT option on the MQGET and if that does not work what reason code do you get ? _________________ Paul Clarke
MQGem Software
www.mqgem.com |
|
Back to top |
|
 |
hughson |
Posted: Wed Feb 26, 2020 2:25 pm Post subject: |
|
|
 Padawan
Joined: 09 May 2013 Posts: 1959 Location: Bay of Plenty, New Zealand
|
Could you show your code? Assume you are using getParameterValue? Is there an exception thrown that might provide some reason for the failure to convert the string data?
Cheers,
Morag _________________ Morag Hughson @MoragHughson
IBM MQ Technical Education Specialist
Get your IBM MQ training here!
MQGem Software |
|
Back to top |
|
 |
souciance |
Posted: Thu Feb 27, 2020 12:50 am Post subject: |
|
|
Disciple
Joined: 29 Jun 2010 Posts: 169
|
Hello,
Here is part of our code. Below is to create a queue manager.
Code: |
QueueManager qm = new QueueManager(name, hostNport, "1414", channel);
Queue qu = new Queue();
qu._QueueManager = qm;
MQEnvironment.Hostname = hostNport;
MQEnvironment.Port = Int32.Parse(port);
MQEnvironment.Channel = channel; |
Here is the main code to connect to a queue and get the queue name.
Code: |
PCFMessage RequestMessage = new PCFMessage(MQC.MQCMD_INQUIRE_Q);
RequestMessage.AddParameter(MQC.MQCA_Q_NAME, "*");
MQGetMessageOptions msgopt = new MQGetMessageOptions();
PCFMessage[] pcfResponse = MessageAgent.Send(RequestMessage);
for (int i = 0; i < pcfResponse.Length; i++)
{
Queue mqQueue = new Queue();
mqQueue._Type = pcfResponse[i].GetIntParameterValue(MQC.MQIA_Q_TYPE);
if (mqQueue._Type == 1)
{
mqQueue._QueueName = pcfResponse[i].GetStringParameterValue(MQC.MQCA_Q_NAME).Trim();
mqQueue._QueueDepth = pcfResponse[i].GetIntParameterValue(MQC.MQIA_CURRENT_Q_DEPTH);
|
The problem is that the value of the QueueName is just jibberish. I think we need a way to tell MQ to convert the CCSID when sending the response back to us. |
|
Back to top |
|
 |
RogerLacroix |
Posted: Thu Feb 27, 2020 1:11 pm Post subject: |
|
|
 Jedi Knight
Joined: 15 May 2001 Posts: 3264 Location: London, ON Canada
|
souciance wrote: |
Code: |
Queue mqQueue = new Queue();
mqQueue._Type = pcfResponse[i].GetIntParameterValue(MQC.MQIA_Q_TYPE);
if (mqQueue._Type == 1)
{
mqQueue._QueueName = pcfResponse[i].GetStringParameterValue(MQC.MQCA_Q_NAME).Trim();
mqQueue._QueueDepth = pcfResponse[i].GetIntParameterValue(MQC.MQIA_CURRENT_Q_DEPTH); |
|
What is the "Queue" class? Is "_QueueName" of type String or MQQueue? Because I see for "_QueueManager" it appears of type QueueManager.
If it is of type MQQueue then that would explain the gibberish.
Regards,
Roger Lacroix
Capitalware Inc. _________________ Capitalware: Transforming tomorrow into today.
Connected to MQ!
Twitter |
|
Back to top |
|
 |
hughson |
Posted: Thu Feb 27, 2020 2:28 pm Post subject: |
|
|
 Padawan
Joined: 09 May 2013 Posts: 1959 Location: Bay of Plenty, New Zealand
|
souciance wrote: |
Code: |
PCFMessage RequestMessage = new PCFMessage(MQC.MQCMD_INQUIRE_Q);
RequestMessage.AddParameter(MQC.MQCA_Q_NAME, "*");
MQGetMessageOptions msgopt = new MQGetMessageOptions();
PCFMessage[] pcfResponse = MessageAgent.Send(RequestMessage);
for (int i = 0; i < pcfResponse.Length; i++)
{
Queue mqQueue = new Queue();
mqQueue._Type = pcfResponse[i].GetIntParameterValue(MQC.MQIA_Q_TYPE);
if (mqQueue._Type == 1)
{
mqQueue._QueueName = pcfResponse[i].GetStringParameterValue(MQC.MQCA_Q_NAME).Trim();
mqQueue._QueueDepth = pcfResponse[i].GetIntParameterValue(MQC.MQIA_CURRENT_Q_DEPTH);
|
|
What do you see if you just print out the value from pcfResponse[i].GetStringParameterValue(MQC.MQCA_Q_NAME) before assigning it to mqQueue._QueueName?
Cheers,
Morag _________________ Morag Hughson @MoragHughson
IBM MQ Technical Education Specialist
Get your IBM MQ training here!
MQGem Software |
|
Back to top |
|
 |
souciance |
Posted: Wed Mar 04, 2020 4:31 am Post subject: |
|
|
Disciple
Joined: 29 Jun 2010 Posts: 169
|
hughson wrote: |
souciance wrote: |
Code: |
PCFMessage RequestMessage = new PCFMessage(MQC.MQCMD_INQUIRE_Q);
RequestMessage.AddParameter(MQC.MQCA_Q_NAME, "*");
MQGetMessageOptions msgopt = new MQGetMessageOptions();
PCFMessage[] pcfResponse = MessageAgent.Send(RequestMessage);
for (int i = 0; i < pcfResponse.Length; i++)
{
Queue mqQueue = new Queue();
mqQueue._Type = pcfResponse[i].GetIntParameterValue(MQC.MQIA_Q_TYPE);
if (mqQueue._Type == 1)
{
mqQueue._QueueName = pcfResponse[i].GetStringParameterValue(MQC.MQCA_Q_NAME).Trim();
mqQueue._QueueDepth = pcfResponse[i].GetIntParameterValue(MQC.MQIA_CURRENT_Q_DEPTH);
|
|
What do you see if you just print out the value from pcfResponse[i].GetStringParameterValue(MQC.MQCA_Q_NAME) before assigning it to mqQueue._QueueName?
Cheers,
Morag |
Hello again, sorry for the delay. Been a bit sick.
But here is the main gist of the code:
Code: |
MQEnvironment.Hostname = hostNport;
MQEnvironment.Port = port;
MQEnvironment.Channel = channel;
PCFMessageAgent MessageAgent = new PCFMessageAgent(name);
PCFMessage reqeuestMessage = new PCFMessage(MQC.MQCMD_INQUIRE_Q);
reqeuestMessage.AddParameter(MQC.MQCA_Q_NAME, "*");
reqeuestMessage.AddParameter(MQC.MQIA_Q_TYPE, MQC.MQQT_LOCAL);
reqeuestMessage.AddParameter(MQC.MQIACF_Q_ATTRS,
new int[] { MQC.MQCA_Q_NAME,
MQC.MQIA_Q_TYPE,
MQC.MQIA_CURRENT_Q_DEPTH });
PCFMessage[] pcfResponse = MessageAgent.Send(reqeuestMessage);
for (int i = 0; i < pcfResponse.Length; i++)
{
string QueueName = pcfResponse[i].GetStringParameterValue(MQC.MQCA_Q_NAME);
int QueueDepth = pcfResponse[i].GetIntParameterValue(MQC.MQIA_CURRENT_Q_DEPTH);
Console.WriteLine($"Queue {QueueName} found with depth {QueueDepth}");
} |
Here is the output:
Queue ??????K???????K??????????K?????@@@@@@@@@@@@@@@@@ found with depth 2
Queue ??????K???????K????????K?????@@@@@@@@@@@@@@@@@@@ found with depth 0
Queue ??????K??????K?????K?????@@@@@@@@@@@@@@@@@@@@@@@ found with depth 0
Queue ??????K????K??????K?????@@@@@@@@@@@@@@@@@@@@@@@@ found with depth 1
Queue ??????K???????K??????????K?????@@@@@@@@@@@@@@@@@ found with depth 0
Queue ??????K???????K?????K?????@@@@@@@@@@@@@@@@@@@@@@ found with depth 0
Queue ??????K??????K??????????K?????@@@@@@@@@@@@@@@@@@ found with depth 0
Queue ??????K???????K??????????K?????@@@@@@@@@@@@@@@@@ found with depth 1
Queue ??????K?????????K?????@@@@@@@@@@@@@@@@@@@@@@@@@@ found with depth 2
Queue ??????K?????K????K???????@@@@@@@@@@@@@@@@@@@@@@@ found with depth 0
Queue ??????K?????K????K??????@@@@@@@@@@@@@@@@@@@@@@@@ found with dept
How can we get the actual queue names? The queue manager on the ISeries has codepage 37. |
|
Back to top |
|
 |
fjb_saper |
Posted: Wed Mar 04, 2020 6:58 am Post subject: |
|
|
 Grand High Poobah
Joined: 18 Nov 2003 Posts: 20756 Location: LI,NY
|
What CCSID did you assign to the PCFMessageAgent ? Try and assign it CCSID 1208 and see if it makes a difference.  _________________ MQ & Broker admin |
|
Back to top |
|
 |
hughson |
Posted: Wed Mar 04, 2020 12:21 pm Post subject: |
|
|
 Padawan
Joined: 09 May 2013 Posts: 1959 Location: Bay of Plenty, New Zealand
|
fjb_saper wrote: |
What CCSID did you assign to the PCFMessageAgent ? |
We can see from the provided code that it has not been explicitly set, which would mean it would default to MQCCSI_Q_MGR which is supposed to pick up the CCSID of the client locale.
fjb_saper wrote: |
Try and assign it CCSID 1208 and see if it makes a difference.  |
In case you don't know how to do this, I think you need:-
Code: |
MessageAgent.setCharacterSet(1208) |
Cheers
Morag _________________ Morag Hughson @MoragHughson
IBM MQ Technical Education Specialist
Get your IBM MQ training here!
MQGem Software |
|
Back to top |
|
 |
tczielke |
Posted: Wed Mar 04, 2020 12:52 pm Post subject: |
|
|
Guardian
Joined: 08 Jul 2010 Posts: 941 Location: Illinois, USA
|
I can run similar logic on a proprietary Java MQ monitor that is running on Linux x86 and executing PCF commands against a z/OS queue manager with a CCSID of 37, and this works fine with getting the queue names back in ASCII without having to explicitly set any CCSID in the code. Below is a snippet. In my snippet, this.agent is a PCFMessageAgent.
Have you opened a PMR with IBM for help here?
Code: |
private void processQDepthGtX(MQAlerts mqAlerts) {
boolean goodResult = false;
while (!goodResult && this.qMgr != null)
{
try {
PCFMessage pcfCmd = new PCFMessage(MQConstants.MQCMD_INQUIRE_Q_STATUS);
pcfCmd.addParameter(MQConstants.MQCA_Q_NAME, "*");
pcfCmd.addParameter(MQConstants.MQIACF_Q_STATUS_ATTRS, new int [] {MQConstants.MQCA_Q_NAME,MQConstants.MQIA_CURRENT_Q_DEPTH});
PCFMessage[] pcfResponse = this.agent.send(pcfCmd);
for (int i=0; i < pcfResponse.length; i++)
{
Object obj = pcfResponse[i].getParameterValue(MQConstants.MQCA_Q_NAME);
if (obj != null && obj instanceof String)
{
String qName = (String) obj;
Pattern pattern = Pattern.compile(mqAlerts.objMask);
Matcher matcher = pattern.matcher(qName);
if (matcher.matches())
{
obj = pcfResponse[i].getParameterValue(MQConstants.MQIA_CURRENT_Q_DEPTH);
if (obj != null && obj instanceof Integer)
{
int qDepth = ((Integer)obj).intValue();
if (qDepth > mqAlerts.qDpthGTX)
{
MQActiveAlerts mqActiveAlerts = this.mqaaht.get("QDGTX-" + mqAlerts.alertId + "-" + qName);
if (mqActiveAlerts == null)
{
mqActiveAlerts = new MQActiveAlerts();
mqActiveAlerts.key = "QDGTX-" + mqAlerts.alertId + "-" + qName;
mqActiveAlerts.alertName = "Queue Depth Greater Than " + mqAlerts.qDpthGTX;
mqActiveAlerts.alertType = "QDGTX";
mqActiveAlerts.objName = qName;
mqActiveAlerts.startTimeMillis = System.currentTimeMillis();
mqActiveAlerts.lastTouchTimeMillis = mqActiveAlerts.startTimeMillis;
mqActiveAlerts.delay = mqAlerts.delay;
mqActiveAlerts.ntfyIntv = mqAlerts.ntfyIntv;
mqActiveAlerts.ntfyGpId = mqAlerts.ntfyGpId;
if (mqActiveAlerts.ntfyGpId != 0)
this.buildEmailList(mqActiveAlerts);
this.mqaaht.put("QDGTX-" + mqAlerts.alertId + "-" + qName, mqActiveAlerts);
}
else
{
mqActiveAlerts.lastTouchTimeMillis = System.currentTimeMillis();
mqActiveAlerts.delay = mqAlerts.delay;
mqActiveAlerts.ntfyIntv = mqAlerts.ntfyIntv;
mqActiveAlerts.ntfyGpId = mqAlerts.ntfyGpId;
}
this.processActiveAlerts(mqActiveAlerts);
}
}
}
}
}
goodResult = true;
} catch (Exception ex) {
try { Thread.sleep(MQMonitor.connDelay); } catch (Exception ex2) { }
try {this.agent.disconnect();} catch (Exception ex2) {};
try {this.qMgr.disconnect();} catch (Exception ex2) {};
this.connectMQ();
}
}
}
|
_________________ Working with MQ since 2010. |
|
Back to top |
|
 |
souciance |
Posted: Wed Mar 04, 2020 1:36 pm Post subject: |
|
|
Disciple
Joined: 29 Jun 2010 Posts: 169
|
hughson wrote: |
fjb_saper wrote: |
What CCSID did you assign to the PCFMessageAgent ? |
We can see from the provided code that it has not been explicitly set, which would mean it would default to MQCCSI_Q_MGR which is supposed to pick up the CCSID of the client locale.
fjb_saper wrote: |
Try and assign it CCSID 1208 and see if it makes a difference.  |
In case you don't know how to do this, I think you need:-
Code: |
MessageAgent.setCharacterSet(1208) |
Cheers
Morag |
Thanks for the hint but that method only seems to be available in the java version. There seems to be way to set the character set in the dotnet api, which given that it is 2020 seems somewhat strange. |
|
Back to top |
|
 |
souciance |
Posted: Wed Mar 04, 2020 1:40 pm Post subject: |
|
|
Disciple
Joined: 29 Jun 2010 Posts: 169
|
tczielke wrote: |
I can run similar logic on a proprietary Java MQ monitor that is running on Linux x86 and executing PCF commands against a z/OS queue manager with a CCSID of 37, and this works fine with getting the queue names back in ASCII without having to explicitly set any CCSID in the code. Below is a snippet. In my snippet, this.agent is a PCFMessageAgent.
Have you opened a PMR with IBM for help here?
Code: |
private void processQDepthGtX(MQAlerts mqAlerts) {
boolean goodResult = false;
while (!goodResult && this.qMgr != null)
{
try {
PCFMessage pcfCmd = new PCFMessage(MQConstants.MQCMD_INQUIRE_Q_STATUS);
pcfCmd.addParameter(MQConstants.MQCA_Q_NAME, "*");
pcfCmd.addParameter(MQConstants.MQIACF_Q_STATUS_ATTRS, new int [] {MQConstants.MQCA_Q_NAME,MQConstants.MQIA_CURRENT_Q_DEPTH});
PCFMessage[] pcfResponse = this.agent.send(pcfCmd);
for (int i=0; i < pcfResponse.length; i++)
{
Object obj = pcfResponse[i].getParameterValue(MQConstants.MQCA_Q_NAME);
if (obj != null && obj instanceof String)
{
String qName = (String) obj;
Pattern pattern = Pattern.compile(mqAlerts.objMask);
Matcher matcher = pattern.matcher(qName);
if (matcher.matches())
{
obj = pcfResponse[i].getParameterValue(MQConstants.MQIA_CURRENT_Q_DEPTH);
if (obj != null && obj instanceof Integer)
{
int qDepth = ((Integer)obj).intValue();
if (qDepth > mqAlerts.qDpthGTX)
{
MQActiveAlerts mqActiveAlerts = this.mqaaht.get("QDGTX-" + mqAlerts.alertId + "-" + qName);
if (mqActiveAlerts == null)
{
mqActiveAlerts = new MQActiveAlerts();
mqActiveAlerts.key = "QDGTX-" + mqAlerts.alertId + "-" + qName;
mqActiveAlerts.alertName = "Queue Depth Greater Than " + mqAlerts.qDpthGTX;
mqActiveAlerts.alertType = "QDGTX";
mqActiveAlerts.objName = qName;
mqActiveAlerts.startTimeMillis = System.currentTimeMillis();
mqActiveAlerts.lastTouchTimeMillis = mqActiveAlerts.startTimeMillis;
mqActiveAlerts.delay = mqAlerts.delay;
mqActiveAlerts.ntfyIntv = mqAlerts.ntfyIntv;
mqActiveAlerts.ntfyGpId = mqAlerts.ntfyGpId;
if (mqActiveAlerts.ntfyGpId != 0)
this.buildEmailList(mqActiveAlerts);
this.mqaaht.put("QDGTX-" + mqAlerts.alertId + "-" + qName, mqActiveAlerts);
}
else
{
mqActiveAlerts.lastTouchTimeMillis = System.currentTimeMillis();
mqActiveAlerts.delay = mqAlerts.delay;
mqActiveAlerts.ntfyIntv = mqAlerts.ntfyIntv;
mqActiveAlerts.ntfyGpId = mqAlerts.ntfyGpId;
}
this.processActiveAlerts(mqActiveAlerts);
}
}
}
}
}
goodResult = true;
} catch (Exception ex) {
try { Thread.sleep(MQMonitor.connDelay); } catch (Exception ex2) { }
try {this.agent.disconnect();} catch (Exception ex2) {};
try {this.qMgr.disconnect();} catch (Exception ex2) {};
this.connectMQ();
}
}
}
|
|
Yup we tried with the Java API and that works fine and it converts without having to set the character set. Unfortunately it doesn't seem like IBM has put the same methods available in the .net api. We were hoping to run a console dotnet core app for some basic admin stuff and not have to revert to java. |
|
Back to top |
|
 |
tczielke |
Posted: Wed Mar 04, 2020 2:40 pm Post subject: |
|
|
Guardian
Joined: 08 Jul 2010 Posts: 941 Location: Illinois, USA
|
My apologies. Your code snippet looked so much like Java PCF that I lost track that you were doing this in .NET. I haven't worked with .NET, but I would think the GetStringParameterValue would be responsible for parsing the MQCFST record that actually contains the queue name string and recognizing that the CCSID inside that MQCFST record is one that needs to be converted from EBCDIC to ASCII. So it sounds like a PMR to me, if it is not doing that.
CORRECTION: A PCF application that will take a raw PCF message and parse it (I have a C PCF program that does this) will do a GET with a convert and then the queue manager goes through and converts all the individual PCF records (like MQCFST) accordingly before handing the message to the application. I have a C PCF program that I run on Linux x86 and it can take PCF messages from z/OS and the MQCFST records (strings) are converted properly because of the GET with the convert. _________________ Working with MQ since 2010. |
|
Back to top |
|
 |
|