Author |
Message
|
KeithPark |
Posted: Thu Jun 02, 2005 6:39 am Post subject: Problems getting multiple messages from a queue |
|
|
 Apprentice
Joined: 12 Nov 2002 Posts: 25
|
Hi
I am trying to get 2 messages from a local queue.
On our unix box (AIX 5.1, MQ Series 5.3, JRE 1.4.2) the second message is corrupting the first.
However, when using a client connection from my desktop it runs fine, with both messages being extracted correctly. We have recently had this Unix box upgraded so that is where my major suspicion is pointing but not sure why it would not do it on the client.
Any suggestions gratefully recieved...
Thanks
Keith |
|
Back to top |
|
 |
vennela |
Posted: Thu Jun 02, 2005 6:51 am Post subject: |
|
|
 Jedi Knight
Joined: 11 Aug 2002 Posts: 4055 Location: Hyderabad, India
|
Quote: |
the second message is corrupting the first. |
What do you mean corrupting?
How does your code look like |
|
Back to top |
|
 |
KeithPark |
Posted: Thu Jun 02, 2005 7:02 am Post subject: |
|
|
 Apprentice
Joined: 12 Nov 2002 Posts: 25
|
Hi
The code is as below and is looped through twice to get both messages:
See below for a the code for the complete method
I am sending 2 compressed files. When I look at the output the data from the second message appears to be overwriting the data from the first, but only up to the length of the first message - ie the second message is longer but when it replaces the first it is truncated to match the correct data length for the first.
Hope that makes some sort of sense.
Thanks
Keith
Last edited by KeithPark on Fri Jun 03, 2005 5:18 am; edited 1 time in total |
|
Back to top |
|
 |
vennela |
Posted: Thu Jun 02, 2005 7:07 am Post subject: |
|
|
 Jedi Knight
Joined: 11 Aug 2002 Posts: 4055 Location: Hyderabad, India
|
Looks like you are instantiating the Message Object outside the loop instead of inside the loop. But unfortunately that part of code is not posted. |
|
Back to top |
|
 |
KeithPark |
Posted: Fri Jun 03, 2005 12:26 am Post subject: |
|
|
 Apprentice
Joined: 12 Nov 2002 Posts: 25
|
Hi
Here is the code for the entire method, which as you can see has the message instantiated inside the loop:
Code: |
public synchronized void getMessages(Vector vMessages, int nTimeout) throws SourceException
{
//Clear vector
vMessages.removeAllElements();
for (int msg = 0; msg < msgsToRead; msg++)
{
try
{
MQMessage theMessage = new MQMessage();
//Specify the get message options
MQGetMessageOptions gmo = new MQGetMessageOptions();
//Retrieve get message options from MQOptionsFactory
gmo = MQOptionsFactory.getGetMessageOptions(context, sInstanceName);
//Get the Message off the Queue
mqInputQueue.get(theMessage,gmo);
if (theMessage != null)
{
// Read the messageId into a String.
String sMessageId = new String(theMessage.messageId);
//Add the mesage to the Vector
vMessages.addElement(theMessage);
//Got message OK
logger.log(Severity.DEBUG, new LogFormatter(this, "getMessages",
sInstanceName + " got message <" + sMessageId + ">"), null);
}
else
{
break;
}
}
catch(FactoryException e)
{
logger.log(Severity.ERROR, new LogFormatter(this, "getMessages",
"<" + sInstanceName +
"> Could not get MQ get-Message-Options from MQOptionsFactory <"),e);
throw new SourceException("<" + sInstanceName +
"> Could not get MQ get-Message-Options from MQOptionsFactory >");
}
catch(Exception exe)
{
logger.log(Severity.ERROR, new LogFormatter(this, "getMessages",
"<" + sInstanceName +
"> Could not define MQMessage <"),exe);
throw new SourceException("<" + sInstanceName +
"> Could not define MQMessage >");
}
catch(MQException mqex)
{
if (mqex.reasonCode == 2033)
{
logger.log(Severity.DEBUG, new LogFormatter(this, "getMessages",
"Queue <" + sMQQueueName + "> : Reason Code = " + mqex.reasonCode),
mqex);
}
else
{
logger.log(Severity.ERROR, new LogFormatter(this, "getMessages",
"<" + sInstanceName +
"> Could not retrieve message from Queue : Reason Code = <" + mqex.reasonCode + ">"),mqex);
if(MQOptionsFactory.isExceptionMessageLevel(mqex))
{
throw new SourceMessageException(null,"<" + sInstanceName +
"> Could not retrieve message from Queue : ReasonCode = <" + mqex.reasonCode + ">");
}
else
{
throw new SourceException("<" + sInstanceName +
"> Could not retrieve message from Queue : ReasonCode = <" + mqex.reasonCode + ">");
}
}
}
}
} |
The following get message options were set:
OptionsFactory.setOptionsUsingProperties - Set option Data.Wait = No.
OptionsFactory.setGetWaitInterval - Set option Data.WaitInterval = UNLIMITED.
OptionsFactory.setOptionsUsingProperties - Set option Data.Syncpoint = Yes.
The other point I have is that if the message was instantiated in the wrong place I would expect it to produce a corrupt output over the client as well as on the Unix box, which it is not.
Keith
Last edited by KeithPark on Fri Jun 03, 2005 5:17 am; edited 1 time in total |
|
Back to top |
|
 |
fschofer |
Posted: Fri Jun 03, 2005 1:11 am Post subject: |
|
|
 Knight
Joined: 02 Jul 2001 Posts: 524 Location: Mainz, Germany
|
Hi,
where did you find this options ?
Quote: |
The following get message options were set:
OptionsFactory.setOptionsUsingProperties - Set option Data.Wait = No.
OptionsFactory.setGetWaitInterval - Set option Data.WaitInterval = UNLIMITED.
OptionsFactory.setOptionsUsingProperties - Set option Data.Syncpoint = Yes. |
Please take a look in the Using Java Handbook for the allowed variables of MQGetMessageOptions.
Greetings
Frank |
|
Back to top |
|
 |
KeithPark |
Posted: Fri Jun 03, 2005 5:14 am Post subject: |
|
|
 Apprentice
Joined: 12 Nov 2002 Posts: 25
|
Hi
Quote: |
where did you find this options ? |
These are local interpretations of the Get Message Options - they may not be exactly as described in the manual in this code snippet but map back to the correct variables in another class. This basically say's we are using no wait, and syncpoint control, which unless I am reading things wrong is an acceptable combination.
Further investigation has confirmed that the problem is occuring when you have MQ Series server 5.3 installed & running a local queue manager on the same machine as the java is running on. It does not occur with MQ Series 5.2 or with a Client connection (although I cannot be sure which version of the Client we are using but that is possibly 5.2).
I now have a local copy of MQ Series running on my desktop and can see the first message being added to the Vector, and then as soon as the second message is taken from the queue the content of the first message in the vector is corrupted with data from the second message. That would indicate that despite instantiating a new instance of the MQMessage there is still references to the first instance being held & being updated.
 |
|
Back to top |
|
 |
jefflowrey |
Posted: Fri Jun 03, 2005 5:31 am Post subject: |
|
|
Grand Poobah
Joined: 16 Oct 2002 Posts: 19981
|
Quote: |
That would indicate that despite instantiating a new instance of the MQMessage there is still references to the first instance being held & being updated. |
And let's be clear. The thing that is doing this is your code, somehow.
You seem to be working with an inhouse API that has wrapped MQ. Is it possible that the MQMessage class your code is using is not the straight C++ MQMessage class?
You should try to simplify your code down to the basics - something that reads messages from a queue and sticks them into a vector. Try working with one of the sample programs.
Also, you are doing
Code: |
for (int msg = 0; msg < msgsToRead; msg++) |
This is a bad design. You should read the queue until the Get gives you a 2033. You should not inq the qdepth first. _________________ I am *not* the model of the modern major general. |
|
Back to top |
|
 |
KeithPark |
Posted: Fri Jun 03, 2005 5:53 am Post subject: |
|
|
 Apprentice
Joined: 12 Nov 2002 Posts: 25
|
Quote: |
And let's be clear. The thing that is doing this is your code, somehow. |
Accepted - and that is where I expect the fix to be but given that the code works with V5.2 then it would seem to indicate that something else has changed within MQ or the MQ java classes.
I am debugging the extended MQMessage to try & find why it is corrupting.
Quote: |
This is a bad design |
That may be the way it appears but our application requires a specific number of messages (which is not necessarily all the messages in the queue) so in the context we use it I don't think it is an unreasonable way to do things. The msgsToRead is not the qdepth.
 |
|
Back to top |
|
 |
jefflowrey |
Posted: Fri Jun 03, 2005 6:03 am Post subject: |
|
|
Grand Poobah
Joined: 16 Oct 2002 Posts: 19981
|
KeithPark wrote: |
jefflowrey wrote: |
This is a bad design |
That may be the way it appears but our application requires a specific number of messages(which is not necessarily all the messages in the queue) so in the context we use it I don't think it is an unreasonable way to do things.
 |
Also, oops on the C++. I forgot which forum I was in...
Since your code is explicitly creating a new MQMessage object, you should not be getting the same one everytime.
It seems odd, but can you try
Code: |
vMessages.addElement((Object)theMessage); |
_________________ I am *not* the model of the modern major general. |
|
Back to top |
|
 |
KeithPark |
Posted: Fri Jun 03, 2005 6:11 am Post subject: |
|
|
 Apprentice
Joined: 12 Nov 2002 Posts: 25
|
Thanks for the suggestion, but no joy unfortunately...
 |
|
Back to top |
|
 |
fjb_saper |
Posted: Fri Jun 03, 2005 10:20 am Post subject: |
|
|
 Grand High Poobah
Joined: 18 Nov 2003 Posts: 20756 Location: LI,NY
|
Don't know if it is relevant but :
KeithPark wrote: |
// Read the messageId into a String.
String sMessageId = new String(theMessage.messageId); |
This is not a good idea. Treat messageId and correlation.Id as byte[]
Anything else will come back to bite you in the ....
And remember the conversion from byte[] into String is quite unpredictable where non character values are used. You are probably better off using a toHexValue of the wrapper... (Integer.toHexValue())
Enjoy  |
|
Back to top |
|
 |
jefflowrey |
Posted: Fri Jun 03, 2005 11:23 am Post subject: |
|
|
Grand Poobah
Joined: 16 Oct 2002 Posts: 19981
|
The following code works for me. You might test it on your system and see what it does.
Code: |
package test;
import java.io.EOFException;
import java.io.IOException;
import java.util.Iterator;
import java.util.Vector;
import com.ibm.mq.MQC;
import com.ibm.mq.MQException;
import com.ibm.mq.MQGetMessageOptions;
import com.ibm.mq.MQMessage;
import com.ibm.mq.MQQueue;
import com.ibm.mq.MQQueueManager;
public class MessageListTester {
public static void main(String[] args) {
MessageListTester mst = new MessageListTester();
mst.start();
}
public void start() {
Vector v = new Vector();
try {
MQQueueManager qMgr = new MQQueueManager("");
int openOptions = MQC.MQOO_INPUT_SHARED;
MQQueue myQueue = qMgr.accessQueue("SYSTEM.DEFAULT.LOCAL.QUEUE",
openOptions, null, null, null);
MQGetMessageOptions gmo = new MQGetMessageOptions();
gmo.options = MQC.MQGMO_WAIT | MQC.MQGMO_FAIL_IF_QUIESCING;
boolean stop = false;
while (!stop) {
MQMessage myMessage = new MQMessage();
try {
myQueue.get(myMessage, gmo);
} catch (MQException e) {
System.out.println("MQ exception: CC = " + e.completionCode
+ " RC = " + e.reasonCode);
stop = true;
}
if (!stop) {
v.addElement((Object) myMessage);
}
}
myQueue.close();
qMgr.disconnect();
} catch (MQException e) {
e.printStackTrace();
}
Iterator i = v.iterator();
while (i.hasNext()) {
MQMessage element = (MQMessage) i.next();
String msgData;
try {
msgData = element.readStringOfCharLength(element
.getDataLength());
System.out.println(msgData);
} catch (EOFException e1) {
e1.printStackTrace();
} catch (IOException e1) {
e1.printStackTrace();
}
}
}
}
|
Note that this is built on v6, not v5.3. I think "readStringOfCharLength" is new for v6 - I'm not positive. I was going to use just "readString", but it told me it was deprecated. Again, I think only with v6. _________________ I am *not* the model of the modern major general. |
|
Back to top |
|
 |
KeithPark |
Posted: Mon Jun 06, 2005 1:09 am Post subject: |
|
|
 Apprentice
Joined: 12 Nov 2002 Posts: 25
|
Hi
I have tried your sample - with the readStringOfCharLength changed to readString - and still got the same corrupt result.
That was running on my desktop using a local queue manager.
 |
|
Back to top |
|
 |
jefflowrey |
Posted: Mon Jun 06, 2005 3:04 am Post subject: |
|
|
Grand Poobah
Joined: 16 Oct 2002 Posts: 19981
|
When I ran my test, I put ten messages holding an integer (0 to 9! ) on SYSTEM.DEFAULT.LOCAL.QUEUE, first. I got 9 to 0 on the console as output, and a 2033 error.
I would open a PMR with IBM.
You aren't, by the way, using the MA88 Java classes with 5.3, are you? You should be using the versions that come with the 5.3 install. _________________ I am *not* the model of the modern major general. |
|
Back to top |
|
 |
|