7.8.4. Producers and Consumers

The messages are sent by message producers and received by message consumers. The classic interfaces are MessageProducer and MessageConsumer, created by calling the appropriate session methods.

// Uses the classic API.

MessageProducer sender;
MessageConsumer recipient;

sender = session.createProducer (oQueue);
recipient = session.createConsumer (oQueue);

The simplified API interfaces to producers and consumers (JMS 2.0 and above) are JMSProducer and JMSConsumer, created by calling the appropriate context methods.

// Uses the simplified API.

// Configure sender with method chaining.
// Sender is not bound to destination here.
JMSProducer sender = context.createProducer ().
                     setDeliveryMode (PERSISTENT).
                     setDeliveryDelay (1000).
                     setTimeToLive (10000);

JMSConsumer recipient = context.createConsumer (oQueue);

The interfaces to send messages support various degrees of blocking, termed as synchronous and asynchronous (JMS 2.0 and above) message send. The standard does not define any interface that would guarantee non blocking operation.

// Uses the classic API.

TextMessage message;

message = session.createTextMessage ();
message.setText ("Hello");

// Always blocks until message is sent.
sender.send (message);
// Uses the simplified API.

// By default blocks until message is sent.
// Overloaded versions for all body types exist.
sender.send (oQueue, "Hello");

The interface to receive messages supports both blocking and nonblocking operation, termed as synchronous and asynchronous message receive in the standard.

Use of nonblocking communication is strongly related to the session threading model. As soon as a message listener is registered for a session of an active connection, that session becomes reserved for the internal thread implementing that listener, and neither the session nor the producers and consumers of the session can be called from other threads. It is safe to call the session or the associated objects from within the message listener using the listener thread. Registering a completion listener does not reserve the session, however, it is not safe to call the session from within the completion listener if it can be called from other code at the same time.

// Uses the classic API.

TextMessage oMessage;

oMessage = (TextMessage) recipient.receive ();
oMessage = (TextMessage) recipient.receive (1000);
// Uses the classic API.

public class SomeListener implements MessageListener
{
  public void onMessage (Message message)
  { ... }
}

SomeListener oListener = new SomeListener ();
recipient.setMessageListener (oListener);
// Uses the simplified API.

// Template versions for all body types exist.
String body = consumer.receiveBody (String.class);

Message filters can be associated with message consumers.

String selector;
MessageConsumer receiver;

selector = new String ("(SomeProperty = 1000)");
receiver = session.createConsumer (oQueue, selector);

To guarantee reliable delivery, messages need to be acknowledged. Each session provides a recover method that causes unacknowledged messages to be delivered again. The acknowledgment itself can be done either automatically upon message delivery or manually by calling the acknowledge method on the message. When transactions are used, acknowledgment is done as a part of commit and recovery as a part of rollback.

A durable subscription to a topic can be requested. The messaging service stores messages for durable subscriptions of temporarily disconnected recipients.

session.createDurableSubscriber (oTopic,"DurableSubscriberName");

A shared subscription to a topic can be requested (JMS 2.0 and above). The messaging service delivers messages for shared subscriptions to one of the connected recipients to provide load balancing.

MessageConsumer consumer;

consumer = session.createSharedConsumer (oQueue, "SharedSubscriberName");