Question

After reading some document of JMS, I totally puzzled by the phrase synchronous and asynchronouns.

See this page: http://docs.oracle.com/cd/E19798-01/821-1841/bncdq/index.html

Synchronous

You use the receive method to consume a message synchronously. You can use this method at any time after you call the start method:

connection.start();
Message m = consumer.receive();
connection.start();
Message m = consumer.receive(1000); // time out after a second

To consume a message asynchronously, you use a message listener, described in the next section.

Asynchronous

JMS Message Listeners A message listener is an object that acts as an asynchronous event handler for messages. This object implements the MessageListener interface, which contains one method, onMessage. In the onMessage method, you define the actions to be taken when a message arrives.

You register the message listener with a specific MessageConsumer by using the setMessageListener method. For example, if you define a class named Listener that implements the MessageListener interface, you can register the message listener as follows:

Listener myListener = new Listener();
consumer.setMessageListener(myListener);

I have two questions:

  1. As what I understood, the nature of JMS is asynchronous. Producer publishes messages to the queue/topic, it doesn't need to wait consumer. This is asynchronous behaviour. How can it be "synchronous"?

  2. If the "mesageListener" is asynchronous, but in my test with spring-jms, I found it always running in a thread. That means, if I write Thread.sleep(2000) in onMessage, it have to be wait 2 seconds before processing next message. Is it "asynchronous"?

Was it helpful?

Solution

If you understand it better like this, consumer.receive() uses a pull model: you read from a queue and are blocked waiting for this message until it comes, or some timeout has elapsed.

Using a listener uses a push model: you register a listener and, when a message comes in, the listener is called, in a separate thread.

Everything is done in a thread in Java, and the listener call is no exception. Whether the listener message handling prevents the processing of other messages in the queue depends on how many threads are dedicated to message processing. If you configure Spring to use a pool of 5 threads to process messages asynchronously, then 5 listeners will be able to process messages in parallel.

OTHER TIPS

Like I understand this:

asynchronous - MessageListener: Use this on a server that listens to a queue. When a message arrives, then deal with it immediately. The server keeps listening to this queue.

synchronous - consumer.receive(1000): Use this on a client applications that now and then needs to check if a message is intend for this client. Example: poll every 60 seconds. This only opens a connection to the server shortly. The 1000 milliseconds will keep this connection open. If a message arrives within these 1000 milliseconds, then the message is consumed and the connection is closed.

You are looking at it end-to-end: from publisher to the consumer. Yes, it is asynchronous delivery from publisher to consumer irrespective of Sync/Async consumer. However Sync/Async in your question is for consumer only, i.e from the JMS broker (eg: ApacheMQ) to the consumer. As others have pointed out, Sync consumers pull messages sequentially from the broker and are waiting for messages. Async consumers register a callback where messages pushed to them (onMessage). Async consumers can go about doing other things while these messages are delivered to them asynchronously from the JMS broker.

I understand synchronous/asynchronous differently.

Synchronous: Caller(Sender) has to wait till the response from consumer has been received(till the time-out) -- request/reply pattern

Asynchronous: Caller(Sender) just post message and continue with its work, while the consumer processes as soon as the message reaches it -- one way request

Any MOM(Message Oriented Middle ware) follows service activator pattern which promotes asynchronous communication. One of my project has implemented a framework around JMS to make communication really synchronous.

  1. Any message has 2 parts. a. Metadata attributes b. Payload
  2. Set attribute "reply-to-queue" to a randomly generated value
  3. Make sure the MOM framework creates temporary queue with name from #2
  4. Make sure the sender spawns thread, which listens to temporary queue created in #3
  5. Publish message and block sender till it receives message to temporary queue
  6. Make sure the consumer intercepts "reply-to-queue" header and publishes response to it

This is one of the ways to make MOM based communication acts like synchronous. You may find other implementations like request-reply mechanism.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top