Dave Richardson
Dave Richardson

Reputation: 4985

javax.jms.MessageConsumer hangs on receive when consumer closed

According to the javadoc, if I call receive() on a javax.jms.MessageConsumer it will block indefinitely until a message is produced or until the message consumer is closed.

I have a thread in which a receive() is being called. As part of the thread shutdown I am calling close(), but the consumer still blocks in receive() and so the thread will not shutdown. The gist of my code is:

public String receiveMessage() {
...
...
   System.out.println("About to receive")
   TextMessage message = (TextMessage) consumer.receive();
   System.out.println("No longer receiving")
...
...
}

public void stop() {
    try {
        if (consumer != null) {
            consumer.close();
        }
    } catch (JMSException ex) {
        throw new IllegalStateException(ex);
    }
}

In the debugger I can see close() being called, but the receive still blocks. If I use the receive() method with a timeout it will block until the timeout expires.

Everything looks right to me, hopefully someone can tell me what I am doing wrong.

Upvotes: 8

Views: 21283

Answers (4)

John M
John M

Reputation: 13229

One further thought.

In JMS, Connection is multi-threaded. Session and below (Consumer, Producer, Message, etc) are not thread-safe. If you're accessing any of that non-thread-safe stuff from multiple threads, you're responsible for avoiding multi-threaded access.

The code you show below looks like you're calling methods on Consumer from a couple of threads. A violation of that rule.

It might be safer to just close the Connection object. No threading conflicts and any sensible implementation would do the right thing to clean up resources associated w/ the Connection.

Upvotes: 5

Shashi
Shashi

Reputation: 15263

But still, calling consumer.close() on another thread is not the right thing to do. You will need to do a connection.Close which will take care of closing all sessions, consumers, producers etc under that connection.

Upvotes: 3

Dave Richardson
Dave Richardson

Reputation: 4985

I've sorted the problem, I wasn't doing a connection.start() anywhere. Once I put this in, the MessageConsumer.receive() stopped blocking when I closed it and everything worked as I had expected.

Thanks for your suggestions.

Upvotes: 6

Andrey Nudko
Andrey Nudko

Reputation: 707

  1. Try receive(long timeout), and don't forget to to check that returned mesage is not null.
  2. In addition to consumer.close() you may also interrupt polling thread - if close() is implemented poorly and doesn't notify blocked receiver, this will wake it up.

Upvotes: 2

Related Questions