|
RSS Feed - WebSphere MQ Support
|
RSS Feed - Message Broker Support
|
 |
|
IBM MQ (iSeries) - COMPLETION CODE DEFAULTING to Zero? |
« View previous topic :: View next topic » |
Author |
Message
|
plivingstone |
Posted: Tue Jul 28, 2015 5:35 am Post subject: IBM MQ (iSeries) - COMPLETION CODE DEFAULTING to Zero? |
|
|
Novice
Joined: 11 Nov 2014 Posts: 11
|
Hi
we have a Windows c# application that puts messages on an iSeries Websphere MQ Queue for core system processing.
This application puts tens of thousands of messages on the iSeries MQ every day, runs round the clock, and has been reliable and resilient for 5 years.
Yesterday 5 messages (in a batch of 10) put on the MQ were not received from the iSeries side, yet on our side we appear to have got COMPLETION CODE MQCC_OK (value = 0)
Here is our code:
Code: |
foreach (DataRow dRow in mqRequests.Rows)
{
try
{
queuePutMessage = new MQMessage();
queuePutMessageOptions = new MQPutMessageOptions();
queuePutMessage.WriteString(dRow[(int)Common.InboundSQLFields.EDB_Message].ToString());
queuePutMessage.Format = MQC.MQFMT_STRING; //
MQFMT_STRING = "MQSTR ";
/* Put message on Queue */
pMQQueue.Put(queuePutMessage, queuePutMessageOptions);
switch (pMQQueue.CompletionCode){
case MQC.MQCC_OK:
/* Message successfully PUT on return MQ */
dRow[(int)Common.InboundSQLFields.MQ_Put_Date] = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fffffff");
dRow[(int)Common.InboundSQLFields.Message_Status] = "Complete";
dRow[(int)Common.InboundSQLFields.Last_Modified_Date] = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fffffff");
break;
case MQC.MQCC_WARNING:
// with warning
dRow[(int)Common.InboundSQLFields.Message_Status] = "Warning:\t" + pMQQueue.ReasonCode + '\t' + pMQQueue.ReasonName;
dRow[(int)Common.InboundSQLFields.Last_Modified_Date] = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fffffff");
/* Write to log */
Common.logBuilder("WebSphereMQ --> putMessages <--", "MQWarning", Common.ActiveMQ, dRow[(int)Common.InboundSQLFields.Message_Type].ToString(), "Exception");
emailer.messageMonitorEmail(dRow[(int)Common.InboundSQLFields.Message_Type].ToString(), Common.ActiveMQ, "Warning:\t" + pMQQueue.ReasonCode + '\t' + pMQQueue.ReasonName);
break;
case MQC.MQCC_FAILED:
dRow[(int)Common.InboundSQLFields.Message_Status] = "Error:\t" + pMQQueue.ReasonCode + '\t' + pMQQueue.ReasonName;
dRow[(int)Common.InboundSQLFields.Last_Modified_Date] = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fffffff");
/* Write to log */
Common.logBuilder("WebSphereMQ --> putMessages <--", "MQFAIL", Common.ActiveMQ, dRow[(int)Common.InboundSQLFields.Message_Type].ToString(), "Exception");
emailer.messageMonitorEmail(dRow[(int)Common.InboundSQLFields.Message_Type].ToString(), Common.ActiveMQ, "Warning:\t" + pMQQueue.ReasonCode + '\t' + pMQQueue.ReasonName);
break;
}
}
catch (MQException mqe)
{
dRow[(int)Common.InboundSQLFields.Message_Status] = "Error";
dRow[(int)Common.InboundSQLFields.Last_Modified_Date] = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fffffff");
/* Write to log */
Common.logBuilder("WebSphereMQ --> putMessages <--", "MQException", Common.ActiveMQ, mqe.Message, "Exception");
emailer.exceptionEmail(mqe);
// Return nothing
return;
}
catch (Exception ex)
{
dRow[(int)Common.InboundSQLFields.Message_Status] = "Error";
dRow[(int)Common.InboundSQLFields.Last_Modified_Date] = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fffffff");
/* Write to log */
Common.logBuilder("WebSphereMQ --> putMessages <--", "Exception", Common.ActiveMQ, ex.Message, "Exception");
emailer.exceptionEmail(ex);
// Return nothing
return;
}
} |
so the process is:
1. Loop through all the messages to be put on the MQ
2. For each one, create an MQ Message and put it on the queue
3. Check the Completion Code which is an INT and therefore DEFAULTS to ZERO, which BTW is = MQCC_OK
4. Update the datatable, if the Completion Code = MQCC_OK we can assume the message has been received with no error, otherwise we update the datatable for that message either with the MQ Warning message or the Fail message...
Now, in the .NET Framework an INT is a STRUCT, which defaults to 0, so if no COMPLETION CODE is sent by the MQ we seem to have an MQCC_OK
So, is it possible that a message is rejected or failed on the MQ, but because we have an INT defaulting to zero, we appear to have received an OK from the MQ? Surely the secure communication between the client/server with handshakes would prevent this?
If that is possible (however unlikely), how can we prevent this situation we have where I have marked 5 messages on the database as Complete based on MQC.MQCC_OK but the iSeries doesn't appear to have received them (again, code running for several years) |
|
Back to top |
|
 |
Vitor |
Posted: Tue Jul 28, 2015 5:50 am Post subject: Re: IBM MQ (iSeries) - COMPLETION CODE DEFAULTING to Zero? |
|
|
 Grand High Poobah
Joined: 11 Nov 2005 Posts: 26093 Location: Texas, USA
|
plivingstone wrote: |
So, is it possible that a message is rejected or failed on the MQ, but because we have an INT defaulting to zero, we appear to have received an OK from the MQ? Surely the secure communication between the client/server with handshakes would prevent this? |
Assuming that you're using a client, then yes it would. But all that code is telling you is that the message was successfully put to the queue hosted on the iSeries. It tells you nothing about what happened after that.
plivingstone wrote: |
Yesterday 5 messages (in a batch of 10) put on the MQ were not received from the iSeries side, yet on our side we appear to have got COMPLETION CODE MQCC_OK (value = 0) |
So how do you know that these were not received? Granted that they've not been processed but is it not equally (or more likely) that they were successfully put to the queue exactly as the CC indicates & picked up by the iSeries which then a) failed to process them successfully & b) failed to handle the error by rolling the message back to the queue? _________________ Honesty is the best policy.
Insanity is the best defence. |
|
Back to top |
|
 |
bruce2359 |
Posted: Tue Jul 28, 2015 5:51 am Post subject: |
|
|
 Poobah
Joined: 05 Jan 2008 Posts: 9469 Location: US: west coast, almost. Otherwise, enroute.
|
A bit more information please.
Does the c program connect to a qmgr on the Windows box? If so, the CC=0 results from the app MQPUTting a msg on the transmission queue.
If this is the case, then you will need to look at the dead-letter-queue on the iSeries qmgr to see if the missing messages are there. _________________ I like deadlines. I like to wave as they pass by.
ב''ה
Lex Orandi, Lex Credendi, Lex Vivendi. As we Worship, So we Believe, So we Live. |
|
Back to top |
|
 |
plivingstone |
Posted: Tue Jul 28, 2015 5:54 am Post subject: |
|
|
Novice
Joined: 11 Nov 2014 Posts: 11
|
Hi,
Thanks for your answer.
The c# app puts the messages on a queue manager hosted on the iSeries ... |
|
Back to top |
|
 |
Vitor |
Posted: Tue Jul 28, 2015 5:59 am Post subject: |
|
|
 Grand High Poobah
Joined: 11 Nov 2005 Posts: 26093 Location: Texas, USA
|
plivingstone wrote: |
The c# app puts the messages on a queue manager hosted on the iSeries ... |
And successfully based on the CC you're getting. So what leads you to the conclusion that they were not in fact successfully delivered apart from the fact they don't show up at the end of the iSeries core processing? _________________ Honesty is the best policy.
Insanity is the best defence. |
|
Back to top |
|
 |
bruce2359 |
Posted: Tue Jul 28, 2015 6:01 am Post subject: |
|
|
 Poobah
Joined: 05 Jan 2008 Posts: 9469 Location: US: west coast, almost. Otherwise, enroute.
|
plivingstone wrote: |
Hi,
Thanks for your answer.
The c# app puts the messages on a queue manager hosted on the iSeries ... |
More precision, please.
Does the c app MQCONNect to the iSeries qmgr OR to the Windows qmgr? _________________ I like deadlines. I like to wave as they pass by.
ב''ה
Lex Orandi, Lex Credendi, Lex Vivendi. As we Worship, So we Believe, So we Live. |
|
Back to top |
|
 |
plivingstone |
Posted: Tue Jul 28, 2015 6:15 am Post subject: |
|
|
Novice
Joined: 11 Nov 2014 Posts: 11
|
bruce2359 wrote: |
plivingstone wrote: |
Hi,
Thanks for your answer.
The c# app puts the messages on a queue manager hosted on the iSeries ... |
More precision, please.
Does the c app MQCONNect to the iSeries qmgr OR to the Windows qmgr? |
Sorry, yes, we do an MQ Connect, connecting to the iSeries queue manager.
On Windows we only have an MQ Client tools installed. |
|
Back to top |
|
 |
plivingstone |
Posted: Tue Jul 28, 2015 7:02 am Post subject: |
|
|
Novice
Joined: 11 Nov 2014 Posts: 11
|
Vitor wrote: |
plivingstone wrote: |
The c# app puts the messages on a queue manager hosted on the iSeries ... |
And successfully based on the CC you're getting. So what leads you to the conclusion that they were not in fact successfully delivered apart from the fact they don't show up at the end of the iSeries core processing? |
I think you're right, they must have been delivered, and something very rare happened on the iSeries...certainly we haven't seen a situation like this with Card Authorizations before...and also nothing on the dead letter queue
Thanks everyone for your help. |
|
Back to top |
|
 |
RogerLacroix |
Posted: Tue Jul 28, 2015 4:08 pm Post subject: |
|
|
 Jedi Knight
Joined: 15 May 2001 Posts: 3264 Location: London, ON Canada
|
You should not be checking the CompletionCode of the MQQueue class when you do a Put() method. The code should look like:
Code: |
foreach (DataRow dRow in mqRequests.Rows)
{
try
{
outMsg = new MQMessage();
pmo = new MQPutMessageOptions();
outMsg.WriteString(dRow[(int)Common.InboundSQLFields.EDB_Message].ToString());
outMsg.Format = MQC.MQFMT_STRING; // MQFMT_STRING = "MQSTR ";
/* Put message on Queue */
pMQQueue.Put(outMsg, pmo);
dRow[(int)Common.InboundSQLFields.MQ_Put_Date] = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fffffff");
dRow[(int)Common.InboundSQLFields.Message_Status] = "Complete";
dRow[(int)Common.InboundSQLFields.Last_Modified_Date] = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fffffff");
}
catch (MQException mqe)
{
switch (mqe.CompletionCode)
{
case MQC.MQCC_WARNING:
// with warning
dRow[(int)Common.InboundSQLFields.Message_Status] = "Warning: CC=" + mqe.CompletionCode + ' : RC=' + mqe.ReasonCode;
dRow[(int)Common.InboundSQLFields.Last_Modified_Date] = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fffffff");
/* Write to log */
Common.logBuilder("WebSphereMQ --> putMessages <--", "MQWarning", Common.ActiveMQ, dRow[(int)Common.InboundSQLFields.Message_Type].ToString(), "Exception");
emailer.messageMonitorEmail(dRow[(int)Common.InboundSQLFields.Message_Type].ToString(), Common.ActiveMQ, "Warning: CC=" + mqe.CompletionCode + ' : RC=' + mqe.ReasonCode);
break;
case MQC.MQCC_FAILED:
dRow[(int)Common.InboundSQLFields.Message_Status] = "Error: CC=" + mqe.CompletionCode + ' : RC=' + mqe.ReasonCode;
dRow[(int)Common.InboundSQLFields.Last_Modified_Date] = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fffffff");
/* Write to log */
Common.logBuilder("WebSphereMQ --> putMessages <--", "MQFAIL", Common.ActiveMQ, dRow[(int)Common.InboundSQLFields.Message_Type].ToString(), "Exception");
emailer.messageMonitorEmail(dRow[(int)Common.InboundSQLFields.Message_Type].ToString(), Common.ActiveMQ, "Warning: CC=" + mqe.CompletionCode + ' : RC=' + mqe.ReasonCode);
break;
}
/* Write to log */
Common.logBuilder("WebSphereMQ --> putMessages <--", "MQException", Common.ActiveMQ, mqe.Message, "CC=" + mqe.CompletionCode + ' : RC=' + mqe.ReasonCode);
emailer.exceptionEmail(mqe);
// Return nothing
return;
}
catch (Exception ex)
{
dRow[(int)Common.InboundSQLFields.Message_Status] = "Error:\t" + ex.Message;
dRow[(int)Common.InboundSQLFields.Last_Modified_Date] = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fffffff");
/* Write to log */
Common.logBuilder("WebSphereMQ --> putMessages <--", "Exception", Common.ActiveMQ, ex.Message, "Exception");
emailer.exceptionEmail(ex);
// Return nothing
return;
}
} |
Regards,
Roger Lacroix
Capitalware Inc. _________________ Capitalware: Transforming tomorrow into today.
Connected to MQ!
Twitter |
|
Back to top |
|
 |
fjb_saper |
Posted: Wed Jul 29, 2015 6:32 am Post subject: |
|
|
 Grand High Poobah
Joined: 18 Nov 2003 Posts: 20756 Location: LI,NY
|
How did you define your batch of 10 messages? Did you use a transaction? Did you use a COMMIT? Did you use persistent messages? Did you experience a bounce for the ISeries qmgr?
And did you check Roger's coding update?  _________________ MQ & Broker admin |
|
Back to top |
|
 |
plivingstone |
Posted: Wed Jul 29, 2015 6:34 am Post subject: |
|
|
Novice
Joined: 11 Nov 2014 Posts: 11
|
fjb_saper wrote: |
How did you define your batch of 10 messages? Did you use a transaction? Did you use a COMMIT? Did you use persistent messages? Did you experience a bounce for the ISeries qmgr?
And did you check Roger's coding update?  |
Thanks for all your answers, yes I saw Rogers coding suggestion ... |
|
Back to top |
|
 |
plivingstone |
Posted: Wed Jul 29, 2015 6:36 am Post subject: |
|
|
Novice
Joined: 11 Nov 2014 Posts: 11
|
RogerLacroix wrote: |
You should not be checking the CompletionCode of the MQQueue class when you do a Put() method. The code should look like:
Code: |
foreach (DataRow dRow in mqRequests.Rows)
{
try
{
outMsg = new MQMessage();
pmo = new MQPutMessageOptions();
outMsg.WriteString(dRow[(int)Common.InboundSQLFields.EDB_Message].ToString());
outMsg.Format = MQC.MQFMT_STRING; // MQFMT_STRING = "MQSTR ";
/* Put message on Queue */
pMQQueue.Put(outMsg, pmo);
dRow[(int)Common.InboundSQLFields.MQ_Put_Date] = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fffffff");
dRow[(int)Common.InboundSQLFields.Message_Status] = "Complete";
dRow[(int)Common.InboundSQLFields.Last_Modified_Date] = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fffffff");
}
catch (MQException mqe)
{
switch (mqe.CompletionCode)
{
case MQC.MQCC_WARNING:
// with warning
dRow[(int)Common.InboundSQLFields.Message_Status] = "Warning: CC=" + mqe.CompletionCode + ' : RC=' + mqe.ReasonCode;
dRow[(int)Common.InboundSQLFields.Last_Modified_Date] = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fffffff");
/* Write to log */
Common.logBuilder("WebSphereMQ --> putMessages <--", "MQWarning", Common.ActiveMQ, dRow[(int)Common.InboundSQLFields.Message_Type].ToString(), "Exception");
emailer.messageMonitorEmail(dRow[(int)Common.InboundSQLFields.Message_Type].ToString(), Common.ActiveMQ, "Warning: CC=" + mqe.CompletionCode + ' : RC=' + mqe.ReasonCode);
break;
case MQC.MQCC_FAILED:
dRow[(int)Common.InboundSQLFields.Message_Status] = "Error: CC=" + mqe.CompletionCode + ' : RC=' + mqe.ReasonCode;
dRow[(int)Common.InboundSQLFields.Last_Modified_Date] = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fffffff");
/* Write to log */
Common.logBuilder("WebSphereMQ --> putMessages <--", "MQFAIL", Common.ActiveMQ, dRow[(int)Common.InboundSQLFields.Message_Type].ToString(), "Exception");
emailer.messageMonitorEmail(dRow[(int)Common.InboundSQLFields.Message_Type].ToString(), Common.ActiveMQ, "Warning: CC=" + mqe.CompletionCode + ' : RC=' + mqe.ReasonCode);
break;
}
/* Write to log */
Common.logBuilder("WebSphereMQ --> putMessages <--", "MQException", Common.ActiveMQ, mqe.Message, "CC=" + mqe.CompletionCode + ' : RC=' + mqe.ReasonCode);
emailer.exceptionEmail(mqe);
// Return nothing
return;
}
catch (Exception ex)
{
dRow[(int)Common.InboundSQLFields.Message_Status] = "Error:\t" + ex.Message;
dRow[(int)Common.InboundSQLFields.Last_Modified_Date] = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fffffff");
/* Write to log */
Common.logBuilder("WebSphereMQ --> putMessages <--", "Exception", Common.ActiveMQ, ex.Message, "Exception");
emailer.exceptionEmail(ex);
// Return nothing
return;
}
} |
Regards,
Roger Lacroix
Capitalware Inc. |
Thanks Roger, next time we do a revision of the code (later on this year), this change will be in there...
I was under the impression that if the completion code is populated by the MQ class, then an exception isn't thrown...obviously we had it wrong and anything other than "OK" is an exception. |
|
Back to top |
|
 |
RogerLacroix |
Posted: Wed Jul 29, 2015 7:43 am Post subject: |
|
|
 Jedi Knight
Joined: 15 May 2001 Posts: 3264 Location: London, ON Canada
|
plivingstone wrote: |
I was under the impression that if the completion code is populated by the MQ class, then an exception isn't thrown...obviously we had it wrong and anything other than "OK" is an exception. |
You are mixing up Procedural languages with Object Oriented languages.
For Procedural languages, the MQ API call returns the Completion Code and Reason Code for the call which the code then tests.
Code: |
MQPUT(Hcon, Hobj, &md, &pmo, buflen, tempBuf, &CompCode, &Reason);
if (CompCode != MQCC_OK)
{
// handle error
}
|
For Object Oriented languages (Java/JMS, C#, etc...), everything is assumed to be ok UNLESS an exception is thrown. If an MQException is thrown then 'Houston, we have a problem'. The most important information in an MQException is the Completion Code and Reason Code values.
Generally speaking, an MQException is bad but there are conditions when an MQException is ok.
i.e. Maybe your code can handle a partial message.
Code: |
catch (MQException mqe)
{
if ( (mqe.CompletionCode == MQC.MQCC_WARNING) &&
(mqe.ReasonCode == MQC.MQRC_TRUNCATED_MSG_ACCEPTED) )
{
// handle a partial message
}
else
{
// handle error
}
} |
Regards,
Roger Lacroix
Capitalware Inc. _________________ Capitalware: Transforming tomorrow into today.
Connected to MQ!
Twitter |
|
Back to top |
|
 |
|
|
 |
|
Page 1 of 1 |
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
|
|
|