I've found some interesting behavior... I can't decide if it's a bug or incompetence, but currently leaning towards incompetence.
This code will not enter the loop, even if there are messages waiting:
Message msg;
while ((msg = consumer.receiveNoWait()) != null) {
System.out.println(msg);
}
This code DOES enter the loop, notice the null assignment:
Message msg = null;
while ((msg = consumer.receiveNoWait()) != null) {
System.out.println(msg);
}
This code is running on Glassfish 3.1.1b10 HotSpot 1.6_26 on Windows 32bit. I can't think of an explanation why the first block doesn't work!
EDIT/UPDATE July 13, 2011:
First, I began stopping the Glassfish domain and deleting it between deploys per request, and this still occurs :)
Second, I cannot sync on Destination or Consumer, as this is Java EE code. But, I can assure there are messages available. There's about 500 of them available an no consumers. In fact, creating a QueueBrowser tells me there's messages available!
Third, this program prints "WORKS!" every time!!! ARGH!!!
public static void main(String[] args) {
Object obj;
if ((obj = getNotNull()) != null) {
System.out.println("worked!");
} else {
System.out.println("failed!");
}
}
static Object getNotNull() {
return new Object();
}
Lastly, I was speaking about my own incompetence. ;)
As Ryan said, seems like a race condition. The bytecodes for both codes are the same, with the exception of an extra "astore":
public static void code1() throws javax.jms.JMSException;
Code:
0: getstatic #2; //Field consumer:Ljavax/jms/MessageConsumer;
3: invokeinterface #3, 1; //InterfaceMethod javax/jms/MessageConsumer.receiveNoWait:()Ljavax/jms/Message;
8: dup
9: astore_0
10: ifnull 23
13: getstatic #4; //Field java/lang/System.out:Ljava/io/PrintStream;
16: aload_0
17: invokevirtual #5; //Method java/io/PrintStream.println:(Ljava/lang/Object;)V
20: goto 0
23: return
public static void code2() throws javax.jms.JMSException;
Code:
0: aconst_null
1: astore_0
2: getstatic #2; //Field consumer:Ljavax/jms/MessageConsumer;
5: invokeinterface #3, 1; //InterfaceMethod javax/jms/MessageConsumer.receiveNoWait:()Ljavax/jms/Message;
10: dup
11: astore_0
12: ifnull 25
15: getstatic #4; //Field java/lang/System.out:Ljava/io/PrintStream;
18: aload_0
19: invokevirtual #5; //Method java/io/PrintStream.println:(Ljava/lang/Object;)V
22: goto 2
25: return
}
If you want to test this theory, try this code:
Message msg;
String dummy = null;
while ((msg = consumer.receiveNoWait()) != null) {
System.out.println(msg);
}
It's a noop, but the bytecode is almost the same as the second code (changes "astore_0" to "astore_1").
BTW, I had horrible results with "receiveNoWait". I prefer "receive(smallTimeout)", to avoid buffer underruns or such.
This sounds like a race condition to me. Declaration of objects without instantiation will always result in null values. You may believe there are Messages waiting for you in the first case, but I bet there aren't. Before the conditional loop, print out the number of objects there are and verify the resulting behavior. If you are in a multi-threaded situation, synchronize on the Message queue if necessary to facilitate this. I am betting it works exactly as expected.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With