|
RSS Feed - WebSphere MQ Support
|
RSS Feed - Message Broker Support
|
 |
|
java code not waiting for reply queue msg |
« View previous topic :: View next topic » |
Author |
Message
|
tilted |
Posted: Fri Sep 03, 2004 5:10 pm Post subject: java code not waiting for reply queue msg |
|
|
Newbie
Joined: 03 Sep 2004 Posts: 3
|
hello all. first off i'll admit im new to MQSeries.. so im hoping that my problem is a simple one that im just overlooking. let me explain whats happening.
i have a pretty typical request/reply setup:
1) server-A puts a msg on the request queue at server-B.
2) server-B retrieves msg off request queue and does something with it.
3) server-B puts new msg on reply queue at server-A.
4) server-A retrieves msg off replay queue.
ive written some test classes on each server to test my MQ setup and also learn how to go about writing the java code for this. what i have written works fine if the Reply queue is empty. the whole process laid out above works like a charm. the problem occurs when i have a msg sitting in the reply queue THEN execute the steps above. at this point server-A pulls the existing message off the reply queue without waiting for the correct one to show up from server-B (i know server-A is the problem because it retrieves the existing msg well before server-B gets a chance to place the new reply msg on the queue).
im pasting some of the code from server-A below. if somebody can find my mistake i'd be most grateful. im thinking there is something wrong with my variable setup or correlationId usage.
thanks
kevin
________________________________________________________
Code: |
public void sendMsg(String msgString)
{
try
{
MQPutMessageOptions pmo = new MQPutMessageOptions();
pmo.options = MQC.MQPMO_NEW_MSG_ID;
outMsg.format = MQC.MQFMT_STRING;
outMsg.writeString(msgString);
outQueue.put(outMsg, pmo);
byte[] correlId = outMsg.messageId;
inMsg.correlationId = correlId;
}
catch (MQException mq)
{
System.out.println("MQ exception." + mq.getMessage());
mq.printStackTrace();
}
catch (Exception e)
{
System.out.println("error: " + e.getMessage());
e.printStackTrace();
}
}
public void getMsg()
{
try
{
MQGetMessageOptions gmo = new MQGetMessageOptions();
gmo.waitInterval = 20000;
gmo.options = MQC.MQGMO_WAIT | MQC.MQGMO_FAIL_IF_QUIESCING;
gmo.matchOptions = MQC.MQMO_MATCH_CORREL_ID;
inQueue.get(inMsg, gmo);
}
catch (MQException mq)
{
System.out.println("MQ exception." + mq.getMessage());
mq.printStackTrace();
}
catch (Exception e)
{
System.out.println("error: " + e.getMessage());
e.printStackTrace();
}
}
public void start()
{
outMsg = new MQMessage();
inMsg = new MQMessage();
try
{
MQEnvironment.hostname = hostName;
MQEnvironment.channel = channel;
MQEnvironment.port = port;
MQEnvironment.properties.put(MQC.TRANSPORT_PROPERTY, MQC.TRANSPORT_MQSERIES_BINDINGS);
MQQueueManager qMgr = new MQQueueManager(qMgrName);
/* put msg on request queue */
int openOptions = MQC.MQOO_OUTPUT | MQC.MQOO_FAIL_IF_QUIESCING;
outQueue = qMgr.accessQueue(requestQName, openOptions);
sendMsg(msgText);
outQueue.close();
/* retrieve msg from reply queue */
openOptions = MQC.MQOO_INPUT_SHARED | MQC.MQOO_FAIL_IF_QUIESCING;
inQueue = qMgr.accessQueue(replyQName, openOptions);
getMsg();
inQueue.close();
qMgr.disconnect();
}
catch (MQException mqe)
{
System.out.println("MQ error occured while sending request: " + mqe.getMessage());
mqe.printStackTrace();
}
}
|
|
|
Back to top |
|
 |
RogerLacroix |
Posted: Fri Sep 03, 2004 7:23 pm Post subject: |
|
|
 Jedi Knight
Joined: 15 May 2001 Posts: 3264 Location: London, ON Canada
|
Hi,
You should read the WMQ Application Programming Guide manual.
(1) After Server-A puts the request message, it needs to save the returned MsgID field.
(2) Server-B will temporary save the incoming message's MsgID then put it in the outbound reply message's CorrelID field.
(3) Server-A will do a 'Get by CorrelId' by putting the saved MsgID in the CorrelID field then setting the GMO options and performing the get. Hence, Server-A will ONLY get the reply message it is expecting.
Regards,
Roger Lacroix _________________ Capitalware: Transforming tomorrow into today.
Connected to MQ!
Twitter |
|
Back to top |
|
 |
tilted |
Posted: Sat Sep 04, 2004 11:03 am Post subject: |
|
|
Newbie
Joined: 03 Sep 2004 Posts: 3
|
hi roger.. let me see if im understanding this right:
(1) After Server-A puts the request message, it needs to save the returned MsgID field.
from Server-A:
Code: |
MQPutMessageOptions pmo = new MQPutMessageOptions();
pmo.options = MQC.MQPMO_NEW_MSG_ID;
outMsg.format = MQC.MQFMT_STRING;
outMsg.messageType = MQC.MQMT_REQUEST;
outMsg.replyToQueueName = replyQName;
outMsg.writeString(msgString);
outQueue.put(outMsg, pmo);
byte[] correlId = outMsg.messageId;
|
- im saving off the messageId of the request msg immediately after doing the put.
(2) Server-B will temporary save the incoming message's MsgID then put it in the outbound reply message's CorrelID field.
here is relevant Server-B code:
Code: |
MQGetMessageOptions gmo = new MQGetMessageOptions();
gmo.options = MQC.MQGMO_WAIT | MQC.MQGMO_FAIL_IF_QUIESCING;
inMsg.messageType = MQC.MQMT_REQUEST;
inQueue.get(inMsg, gmo);
byte[] correlId = inMsg.messageId;
....
outMsg.correlationId = correlId;
MQPutMessageOptions pmo = new MQPutMessageOptions();
outMsg.format = MQC.MQFMT_STRING;
outMsg.messageType = MQC.MQMT_REPLY;
outMsg.writeString(msgString);
outQueue.put(outMsg, pmo);
|
(3) Server-A will do a 'Get by CorrelId' by putting the saved MsgID in the CorrelID field then setting the GMO options and performing the get. Hence, Server-A will ONLY get the reply message it is expecting.
from Server-A:
Code: |
inMsg.messageType = MQC.MQMT_REPLY;
inMsg.correlationId = correlId;
MQGetMessageOptions gmo = new MQGetMessageOptions();
gmo.matchOptions = MQC.MQMO_MATCH_CORREL_ID;
gmo.waitInterval = 10000;
gmo.options = MQC.MQGMO_WAIT | MQC.MQGMO_FAIL_IF_QUIESCING;
inQueue.get(inMsg, gmo);
|
im assigning the reply msg correlationId to the saved byte[] from step 1. im also setting matchOptions to MATCH_CORREL_ID.
im still not sure why this isnt working. ive looked at some of the documentation but i cant see what im doing wrong.
maybe ive been messing with this too long and need a fresh set of eyes/point of view.
thanks
kevin |
|
Back to top |
|
 |
RogerLacroix |
Posted: Sat Sep 04, 2004 6:50 pm Post subject: |
|
|
 Jedi Knight
Joined: 15 May 2001 Posts: 3264 Location: London, ON Canada
|
Hi,
Off the top of my head, it looks right. You should start comparing MsgIDs and CorrelIDs one step at a time.
Regards,
Roger Lacroix _________________ Capitalware: Transforming tomorrow into today.
Connected to MQ!
Twitter |
|
Back to top |
|
 |
PeterPotkay |
Posted: Sun Sep 05, 2004 5:51 am Post subject: |
|
|
 Poobah
Joined: 15 May 2001 Posts: 7722
|
If this was my program, I would:
Eliminate this line:
Code: |
inMsg.messageType = MQC.MQMT_REPLY
|
You don't set the message type when you consume a message, only when you produce it. You can check for the message type after you got the message to see what type it is.
Eliminate these lines:
Code: |
MQGetMessageOptions gmo = new MQGetMessageOptions();
gmo.matchOptions = MQC.MQMO_MATCH_CORREL_ID;
|
You shouldn't need these. What you should be doing prior to every GET attempt is initializing both MessageID and CorrelID, to insure no garbage from a previous call, set the CorrelID to a value you want, and then issue the MQGET. You don't explicitly need to set the match options. Simply having a value other than nulls in the ID fileds will tell MQ that you are trying to match on those values.
Prior to running your MQGET on the reply message, use another tool to verify the reply message is really on the reply queue and is committed. If another tool can see it (like Roger's MQ Visual Browse, http://www.mqseries.net/phpBB2/viewtopic.php?t=15264 , or the MQ sample amqsbcg), then you know your app should see it.
Once you get this fixed, and the reply message is succesfully retrieved while other messages or on the queue (good test by the way, I have seen apps released to production on the assumption that their current reply message will always be at the head of the queue), I would change the app on server B not to blindly move the Message ID of the request into the Correl ID of the reply. Instead, it should check the MQMD_Report field of the request message to see what the requesting app wants done with the IDs (MsgID to CorrelID, or CorrelID to CorrelID). This way, the sending side can change, or another app with different ID requirements, can use the app on Server B with no modifications.
If you really want to get crafty, set the Exception_Report_With_Full_Data option on the outgoing request message. If that request message can't make it to the destination queue for any reason, a report message conatining the reason why it couldn't be delivered is sent by MQ to your reply queue. In your requesting program, just add a section that checks for message type right after the MQGET completes. If it all worked, the message type will be REPLY, and you process normally. If there was a problem delivering the request message, the message type will be REPORT, and the path in your code can print out the reason code in the report message, or do whatever. Instead of people calling you saying their message is lost, they get an error saying XYZ queue is full, or XYZ queue is PUT-Inhibited, etc. The replying app does not have to change at all. This only helps if the request message would have ended up on a DLQ somewhere. If it is any other type of problem, then you are still going to get a 2033 on the requesting side. But, it can help in some cases. _________________ Peter Potkay
Keep Calm and MQ On |
|
Back to top |
|
 |
tilted |
Posted: Sun Sep 05, 2004 12:01 pm Post subject: |
|
|
Newbie
Joined: 03 Sep 2004 Posts: 3
|
thanks for the replies fellas. i have the app working.. not like i would expect it to but it is now waiting until the correct msg shows up in the reply queue.
the only way for it to work at this point is to set BOTH the inMsg messageId and correlationId to the saved messageId from the request. i eliminated the unnecessary entries you pointed out Peter. where my problem may be is here
Quote: |
What you should be doing prior to every GET attempt is initializing both MessageID and CorrelID, to insure no garbage from a previous call, set the CorrelID to a value you want, and then issue the MQGET.
|
im thinking i wasnt initializing the messageId properly before the GET. i will have to play with that so i can get it to where its just matching the correlationId and not forced to match both.
thanks
Kevin |
|
Back to top |
|
 |
bower5932 |
Posted: Mon Sep 06, 2004 5:22 am Post subject: |
|
|
 Jedi Knight
Joined: 27 Aug 2001 Posts: 3023 Location: Dallas, TX, USA
|
There are a couple of C++ programs at:
http://www.developer.ibm.com/tech/sampmq.html
that manipulate the message and correlation ids. Look for mqreqro.cpp and mqsrvro.cpp. You can see the fields that they manipulate which should help you in your java. |
|
Back to top |
|
 |
PeterPotkay |
Posted: Mon Sep 06, 2004 4:41 pm Post subject: |
|
|
 Poobah
Joined: 15 May 2001 Posts: 7722
|
Post your code where you were initializing the Message ID. Sounds like you were doing it not quite correctly. If you move " " to the field, that is NOT initialized, and MQ is trying to find a message that has " " in the Message ID, which is why the GET fails. _________________ Peter Potkay
Keep Calm and MQ On |
|
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
|
|
|
|