Skip navigation.
Downloads | Product Documentation | Support

Programming WebLogic JMS

# Developing a Basic JMS Application

The following sections provide information on the steps required to develop a basic JMS application:

1. Importing Required Packages
2. Setting Up a JMS Application
3. Sending Messages
4. Receiving Messages
5. Acknowledging Received Messages
6. Releasing Object Resources

In addition to the application development steps defined in the previous figure, you can also optionally perform any of the following steps during your design development:

- Manage connection and session processing
- Create destinations dynamically
- Create durable subscriptions
- Manage message processing by setting and browsing message header and property fields, filtering messages, and/or processing messages concurrently
- Use JMS within transactions (described in Using Transactions with WebLogic JMS)

Note: For more information about the JMS classes described in this section, access the JMS Javadoc supplied on the Sun Microsystems' Java Website.

# Importing Required Packages

The following table lists the packages that are commonly used by WebLogic JMS applications.

Table 4-1 WebLogic JMS Packages

Package | Description
--- | ---
javax.jms | Sun Microsystems' JMS API. This package is always used by WebLogic JMS applications.
javax.naming weblogic.jndi | JNDI packages required for server and destination lookups.
javax.transaction.UserTransaction | JTA API required for JTA user transaction support.
weblogic.jms.extensions | WebLogic-specific JMS public API that provides additional classes and methods, as described in Value-Added Public JMS API Extensions.
weblogic.jms.extensions.ServerSessionPoolFactory | Deprecated in WebLogic Server 8.1.

# Setting Up a JMS Application

Before you can send and receive messages, you must set up a JMS application. The following figure illustrates the steps required to set up a JMS application.

Figure 4-1 Setting Up a JMS Application

The setup steps are described in the following sections. Detailed examples of setting up a Point-to-Point (PTP) and Publish/Subscribe (Pub/Sub) application are also provided. The examples are excerpted from the `examples.jms` package provided with WebLogic Server in the `WL_HOME``\samples\server\examples\src\examples\jms` directory, where `WL_HOME` is the top-level directory of your WebLogic Platform installation.

Before proceeding, ensure that the system administrator responsible for configuring WebLogic Server has configured the required JMS resources, including the connection factories, JMS servers, and destinations.

- For more information, see "Configure Messaging" in the Administration Console Online Help.
- For more information about the JMS classes and methods described in these sections, see Understanding the JMS API, or the javax.jms, or the weblogic.jms.extensions Javadoc.
- For information about setting up transacted applications and JTA user transactions, see Using Transactions with WebLogic JMS.

## Step 1: Look Up a Connection Factory in JNDI

Before you can look up a connection factory, it must be defined as part of the configuration information. WebLogic JMS provides two default connection factories that are included as part of the configuration. They can be looked up using the JNDI names, `weblogic.jms.ConnectionFactory` and `weblogic.jms.XAConnectionFactory`, which is configured to enable JTA transactions. The administrator can configure new connection factories during configuration; however, these factories must be uniquely named or the server will not boot. For information on configuring connection factories and the defaults that are available, see "Configure connection factories" in the Administration Console Online Help.

Once the connection factory has been defined, you can look it up by first establishing a JNDI context (`context`) using the InitialContext() method. For any application other than a servlet application, you must pass an environment used to create the initial context.

Once the context is defined, to look up a connection factory in JNDI, execute one of the following commands, for PTP or Pub/Sub messaging, respectively:

>     QueueConnectionFactory queueConnectionFactory =
>      (QueueConnectionFactory) context.lookup(CF_name);

>     TopicConnectionFactory topicConnectionFactory =
>      (TopicConnectionFactory) context.lookup(CF_name);

The `CF_name` argument specifies the connection factory name defined during configuration.

For more information about the `ConnectionFactory` class, see ConnectionFactory or the javax.jms.ConnectionFactory Javadoc.

## Step 2: Create a Connection Using the Connection Factory

You can create a connection for accessing the messaging system by using the `ConnectionFactory` methods described in the following sections.

For more information about the `Connection` class, see Connection or the javax.jms.Connection Javadoc.

### Create a Queue Connection

The `QueueConnectionFactory` provides the following two methods for creating a queue connection:

>     public QueueConnection createQueueConnection(
>     ) throws JMSException

>     public QueueConnection createQueueConnection(
>      String userName,
>      String password
>     ) throws JMSException

The first method creates a `QueueConnection`; the second method creates a `QueueConnection` using a specified user identity. In each case, a connection is created in stopped mode and must be started in order to accept messages, as described in Step 7: Start the Connection.

For more information about the `QueueConnectionFactory` class methods, see the javax.jms.QueueConnectionFactory Javadoc. For more information about the `QueueConnection` class, see the javax.jms.QueueConnection Javadoc.

### Create a Topic Connection

The `TopicConnectionFactory` provides the following two methods for creating a topic connection:

>     public TopicConnection createTopicConnection(
>     ) throws JMSException

>     public TopicConnection createTopicConnection(
>      String userName,
>      String password
>     ) throws JMSException

The first method creates a `TopicConnection`; the second method creates a `TopicConnection` using a specified user identity. In each case, a connection is created in stopped mode and must be started in order to accept messages, as described in Step 7: Start the Connection.

For more information about the `TopicConnectionFactory` class methods, see the javax.jms.TopicConnectionFactory Javadoc. For more information about the `TopicConnection` class, see the javax.jms.TopicConnection Javadoc.

## Step 3: Create a Session Using the Connection

You can create one or more sessions for accessing a queue or topic using the `Connection` methods described in the following sections.

Notes: A session and its message producers and consumers can only be accessed by one thread at a time. Their behavior is undefined if multiple threads access them simultaneously.

WebLogic JMS does not support having both types of MessageConsumer (QueueConsumer and TopicSubscriber) for a single Session. However, it does support a single session with both a QueueSender and a TopicSubscriber (and vice-versa: QueueConsumer and TopicPublisher), or with multiple MessageProducers of any type.

For more information about the `Session` class, see Session or the javax.jms.Session Javadoc.

### Create a Queue Session

The `QueueConnection` class defines the following method for creating a queue session:

>     public QueueSession createQueueSession(
>      boolean transacted,
>      int acknowledgeMode
>     ) throws JMSException

You must specify a boolean argument indicating whether the session will be transacted (`true`) or non-transacted (`false`), and an integer that indicates the acknowledge mode for non-transacted sessions, as described in Table 2-7. The `acknowledgeMode` attribute is ignored for transacted sessions. In this case, messages are acknowledged when the transaction is committed using the `commit()` method.

For more information about the `QueueConnection` class methods, see the javax.jms.QueueConnection Javadoc. For more information about the `QueueSession` class, see the javax.jms.QueueSession Javadoc.

### Create a Topic Session

The `TopicConnection` class defines the following method for creating a topic session:

>     public TopicSession createTopicSession(
>      boolean transacted,
>      int acknowledgeMode
>     ) throws JMSException

You must specify a boolean argument indicating whether the session will be transacted (`true`) or non-transacted (`false`), and an integer that indicates the acknowledge mode for non-transacted sessions, as described in Acknowledge Modes Used for Non-Transacted Sessions. The `acknowledgeMode` attribute is ignored for transacted sessions. In this case, messages are acknowledged when the transaction is committed using the `commit()` method.

For more information about the `TopicConnection` class methods, see the javax.jms.TopicConnection Javadoc. For more information about the `TopicSession` class, see the javax.jms.TopicSession Javadoc.

## Step 4: Look Up a Destination (Queue or Topic)

Before you can look up a destination, the destination must be configured by the WebLogic JMS system administrator, as described in "Configure topics" and "Configure queues" in the Administration Console Online Help. For more information about the `Destination` class, see Destination or the javax.jms.Destination Javadoc.

Once the destination has been configured, you can look up a destination using one of the following procedures:

### Using a JNDI Name

You can look up a destination by establishing a JNDI context (`context`), which has already been accomplished in Step 1: Look Up a Connection Factory in JNDI, and executing one of the following commands, for PTP or Pub/Sub messaging, respectively:

>     Queue queue = (Queue) context.lookup(Dest_name);

>     Topic topic = (Topic) context.lookup(Dest_name);

The `Dest_name` argument specifies the destination's JNDI name defined during configuration.

### Use a Reference

If you do not use a JNDI namespace, you can use the following `QueueSession` or `TopicSession` method to reference a queue or topic, respectively:

Note: The `createQueue()` and `createTopic()` methods do not create destinations dynamically; they create only references to destinations that already exist. For information about creating destinations dynamically, see Using JMS Module Helper to Manage Applications.

>     public Queue createQueue(
>      String queueName
>     ) throws JMSException

>     public Topic createTopic(
>      String topicName
>     ) throws JMSException

The value of `queueName` and/or `topicName` string is defined by:

- The `CreateDestinationIdentifier` when configuring a destination, see JMS Queue: Configuration: General and JMS Topic: Configuration: General. For more information about these methods, see the javax.jms.QueueSession and javax.jms.TopicSession Javadoc, respectively.
- `A` string is defined by `JMS_Server_Name/Module_Name!Destination_Name` (for example, `myjmsserver/myModule-jms!mydestination`). When referencing a destination in an interop module, the string is defined by `JMS_Server_Name/interop-jms!Destination_Name` (for example, `myjmsserver/interop-jms!mydestination`).

Note: To reference destination in releases prior to WebLogic 9.0, use a string defined by `JMS_`Server_Name!Destination_Name (for example, `myjmsserver!mydestination`).

Once the destination has been defined, you can use the following Queue or Topic method to access the queue or topic name, respectively:

>     public String getQueueName(
>     ) throws JMSException

>     public String getTopicName(
>     ) throws JMSException

To ensure that the queue and topic names are returned in printable format, use the `toString()` method.

#### Server Affinity When Looking Up Destinations

The `createTopic()` and `createQueue()` methods also allow a "`./Destination_Name`" syntax to indicate server affinity when looking up destinations. This will locate destinations that are locally deployed in the same JVM as the JMS connection's connection factory host. If the name is not on the local JVM an exception is thrown, even though the same name might be deployed on a different JVM.

An application might use this convention to avoid hard-coding the server name when using the `createTopic()` and `createQueue()` methods so that the code can be reused on different JMS servers without requiring any changes.

## Step 5: Create Message Producers and Message Consumers Using the Session and Destinations

You can create message producers and message consumers by passing the destination reference to the `Session` methods described in the following sections.

Note: Each consumer receives its own local copy of a message. Once received, you can modify the header field values; however, the message properties and message body are read only. (Attempting to modify the message properties or body at this point will generate a `MessageNotWriteableException`.) You can modify the message body by executing the corresponding message type's `clearbody()` method to clear the existing contents and enable write permission.

For more information about the `MessageProducer` and `MessageConsumer` classes, see MessageProducer and MessageConsumer, or the javax.jms.MessageProducer and javax.jms.MessageConsumer Javadocs, respectively.

### Create QueueSenders and QueueReceivers

The `QueueSession` object defines the following methods for creating queue senders and receivers:

>     public QueueSender createSender(
>      Queue queue
>     ) throws JMSException

>     public QueueReceiver createReceiver(
>      Queue queue
>     ) throws JMSException

>     public QueueReceiver createReceiver(
>      Queue queue,
>      String messageSelector
>     ) throws JMSException

You must specify the queue object for the queue sender or receiver being created. You may also specify a message selector for filtering messages. Message selectors are described in more detail in Filtering Messages.

If you pass a value of null to the `createSender()` method, you create an anonymous producer. In this case, you must specify the queue name when sending messages, as described in Sending Messages.

Once the queue sender or receiver has been created, you can access the queue name associated with the queue sender or receiver using the following `QueueSender` or `QueueReceiver` method:

>     public Queue getQueue(
>     ) throws JMSException

For more information about the `QueueSession` class methods, see the javax.jms.QueueSession Javadoc. For more information about the `QueueSender` and `QueueReceiver` classes, see the javax.jms.QueueSender and javax.jms.QueueReceiver Javadocs, respectively.

### Create TopicPublishers and TopicSubscribers

The `TopicSession` object defines the following methods for creating topic publishers and topic subscribers:

>     public TopicPublisher createPublisher(
>      Topic topic
>     ) throws JMSException

>     public TopicSubscriber createSubscriber(
>      Topic topic
>     ) throws JMSException

>     public TopicSubscriber createSubscriber(
>      Topic topic,
>      String messageSelector,
>      boolean noLocal
>     ) throws JMSException

Note: The methods described in this section create non-durable subscribers. Non-durable topic subscribers only receive messages sent while they are active. For information about the methods used to create durable subscriptions enabling messages to be retained until all messages are delivered to a durable subscriber, see Creating Subscribers for a Durable Subscription. In this case, durable subscribers only receive messages that are published after the subscriber has subscribed.

You must specify the topic object for the publisher or subscriber being created. You may also specify a message selector for filtering messages and a `noLocal` flag (described later in this section). Message selectors are described in more detail in Filtering Messages.

If you pass a value of null to the `createPublisher()` method, you create an anonymous producer. In this case, you must specify the topic name when sending messages, as described in Sending Messages.

An application can have a JMS connection that it uses to both publish and subscribe to the same topic. Because topic messages are delivered to all subscribers, the application can receive messages it has published itself. To prevent this behavior, a JMS application can set a `noLocal` flag to `true`.

Once the topic publisher or subscriber has been created, you can access the topic name associated with the topic publisher or subscriber using the following `TopicPublisher` or `TopicSubscriber` method:

>     Topic getTopic(
>     ) throws JMSException

In addition, you can access the `noLocal` variable setting associated with the topic subscriber using the following `TopicSubscriber` method:

>     boolean getNoLocal(
>     ) throws JMSException

For more information about the `TopicSession` class methods, see the javax.jms.TopicSession Javadoc. For more information about the `TopicPublisher` and `TopicSubscriber` classes, see the javax.jms.TopicPublisher and javax.jms.TopicSubscriber Javadocs, respectively.

## Step 6a: Create the Message Object (Message Producers)

Note: This step applies to message producers only.

To create the message object, use one of the following `Session` or `WLSession` class methods:

- `Session` Methods

Note: These methods are inherited by both the `QueueSession` and `TopicSession` subclasses.

>     public BytesMessage createBytesMessage(
>     ) throws JMSException

>     public MapMessage createMapMessage(
>     ) throws JMSException

>     public Message createMessage(
>     ) throws JMSException

>     public ObjectMessage createObjectMessage(
>     ) throws JMSException

>     public ObjectMessage createObjectMessage(
>      Serializable object
>     ) throws JMSException

>     public StreamMessage createStreamMessage(
>     ) throws JMSException

>     public TextMessage createTextMessage(
>     ) throws JMSException

>     public TextMessage createTextMessage(
>      String text
>     ) throws JMSException

- `WLSession` Method

>     public XMLMessage createXMLMessage(
>      String text
>     ) throws JMSException

For more information about the `Session` and `WLSession` class methods, see the javax.jms.Session and weblogic.jms.extensions.WLSession Javadocs, respectively. For more information about the `Message` class and its methods, see Message, or the javax.jms.Message Javadoc.

## Step 6b: Optionally Register an Asynchronous Message Listener (Message Consumers)

Note: This step applies to message consumers only.

To receive messages asynchronously, you must register an asynchronous message listener by performing the following steps:

1. Implement the javax.jms.MessageListener interface, which includes an `onMessage()` method.

Note: For an example of the `onMessage()` method interface, see Example: Setting Up a PTP Application.
If you wish to issue the `close()` method within an `onMessage()` method call, the system administrator must select the Allow Close In OnMessage option when configuring the connection factory. For more information on configuring connection factory options, see Configuring JMS Resources in Configuring and Managing WebLogic JMS.

2. Set the message listener using the following `MessageConsumer` method, passing the listener information as an argument:

>     public void setMessageListener(
>      MessageListener listener
>     ) throws JMSException

3. Optionally, implement an exception listener on the session to catch exceptions, as described in Defining a Connection Exception Listener.

You can unset a message listener by calling the `MessageListener()` method with a value of null.

Once a message listener has been defined, you can access it by calling the following `MessageConsumer` method:

>     public MessageListener getMessageListener(
>     ) throws JMSException

Note: WebLogic JMS guarantees that multiple `onMessage()` calls for the same session will not be executed simultaneously.

If a message consumer is closed by an administrator or as the result of a server failure, a `ConsumerClosedException` is delivered to the session exception listener, if one has been defined. In this way, a new message consumer can be created, if necessary. For information about defining a session exception listener, see Defining a Connection Exception Listener.

The `MessageConsumer` class methods are inherited by the `QueueReceiver` and `TopicSubscriber` classes. For additional information about the `MessageConsumer` class methods, see MessageProducer and MessageConsumer or the javax.jms.MessageConsumer Javadoc.

## Step 7: Start the Connection

You start the connection using the `Connection` class `start()` method.

For additional information about starting, stopping, and closing a connection, see Starting, Stopping, and Closing a Connection or the javax.jms.Connection Javadoc.

## Example: Setting Up a PTP Application

The following example is excerpted from the `examples.jms.queue.QueueSend` example, provided with WebLogic Server in the `WL_HOME``\samples\server\examples\src\examples\jms\queue` directory, where `WL_HOME` is the top-level directory of your WebLogic Platform installation. The `init()` method shows how to set up and start a `QueueSession` for a JMS application. The following shows the `init()` method, with comments describing each setup step.

Define the required variables, including the JNDI context, JMS connection factory, and queue static variables.

>     public final static String JNDI_FACTORY=
>     	"weblogic.jndi.WLInitialContextFactory";
>     public final static String JMS_FACTORY=
>     	"weblogic.examples.jms.QueueConnectionFactory";
>     public final static String
>      	QUEUE="weblogic.examples.jms.exampleQueue";

>     private QueueConnectionFactory qconFactory;
>     private QueueConnection qcon;
>     private QueueSession qsession;
>     private QueueSender qsender;
>     private Queue queue;
>     private TextMessage msg;

Set up the JNDI initial context, as follows:

>     InitialContext ic = getInitialContext(args[0]);
>     	.
>     	.
>     	.
>     private static InitialContext getInitialContext(
>      String url
>     ) throws NamingException
>     {
>      Hashtable env = new Hashtable();
>      env.put(Context.INITIAL_CONTEXT_FACTORY, JNDI_FACTORY);
>      env.put(Context.PROVIDER_URL, url);
>      return new InitialContext(env);
>     }

Note: When setting up the JNDI initial context for an EJB or servlet, use the following method:

>     Context ctx = new InitialContext();

Create all the necessary objects for sending messages to a JMS queue. The `ctx` object is the JNDI initial context passed in by the `main()` method.

>     public void init(
>      Context ctx,
>      String queueName
>     ) throws NamingException, JMSException
>     {

### Step 1

Look up a connection factory in JNDI.

>      qconFactory = (QueueConnectionFactory) ctx.lookup(JMS_FACTORY);

### Step 2

Create a connection using the connection factory.

>      qcon = qconFactory.createQueueConnection();

### Step 3

Create a session using the connection. The following code defines the session as non-transacted and specifies that messages will be acknowledged automatically. For more information about transacted sessions and acknowledge modes, see Session.

>      qsession = qcon.createQueueSession(false,
>      Session.AUTO_ACKNOWLEDGE);

### Step 4

Look up a destination (queue) in JNDI.

>      queue = (Queue) ctx.lookup(queueName);

### Step 5

Create a reference to a message producer (queue sender) using the session and destination (queue).

>      qsender = qsession.createSender(queue);

### Step 6

Create the message object.

>      msg = qsession.createTextMessage();

### Step 7

Start the connection.

>      qcon.start();
>     }

The `init()` method for the `examples.jms.queue.QueueReceive` example is similar to the `QueueSend` `init()` method shown previously, with the one exception. Steps 5 and 6 would be replaced by the following code, respectively:

>     qreceiver = qsession.createReceiver(queue);
>     qreceiver.setMessageListener(this);

In the first line, instead of calling the `createSender()` method to create a reference to the queue sender, the application calls the `createReceiver()` method to create the queue receiver.

In the second line, the message consumer registers an asynchronous message listener.

When a message is delivered to the queue session, it is passed to the `examples.jms.QueueReceive.onMessage()` method. The following code excerpt shows the `onMessage()` interface from the `QueueReceive` example:

>     public void onMessage(Message msg)
>     {
>      try {
>     	String msgText;
>     	if (msg instanceof TextMessage) {
>      	  msgText = ((TextMessage)msg).getText();
>     	} else { // If it is not a TextMessage...
>     	 msgText = msg.toString();
>     	}

>     	System.out.println("Message Received: "+ msgText );

>     	if (msgText.equalsIgnoreCase("quit")) {
>     	  synchronized(this) {

>     	  	quit = true;
>     		this.notifyAll(); // Notify main thread to quit
>     	  }
>     	}
>       } catch (JMSException jmse) {
>        jmse.printStackTrace();
>       }
>     }

The `onMessage()` method processes messages received through the queue receiver. The method verifies that the message is a `TextMessage` and, if it is, prints the text of the message. If `onMessage()` receives a different message type, it uses the message's `toString()` method to display the message contents.

Note: It is good practice to verify that the received message is the type expected by the handler method.

For more information about the JMS classes used in this example, see Understanding the JMS API or the javax.jms Javadoc.

## Example: Setting Up a Pub/Sub Application

The following example is excerpted from the `examples.jms.topic.TopicSend` example, provided with WebLogic Server in the `WL_HOME``\samples\server\examples\src\examples\jms\topic` directory, where `WL_HOME` is the top-level directory of your WebLogic Platform installation. The `init()` method shows how to set up and start a topic session for a JMS application. The following shows the `init()` method, with comments describing each setup step.

Define the required variables, including the JNDI context, JMS connection factory, and topic static variables.

>     public final static String JNDI_FACTORY=
>     	"weblogic.jndi.WLInitialContextFactory";
>     public final static String JMS_FACTORY=
>     	"weblogic.examples.jms.TopicConnectionFactory";
>     public final static String
>     	TOPIC="weblogic.examples.jms.exampleTopic";

>     protected TopicConnectionFactory tconFactory;
>     protected TopicConnection tcon;
>     protected TopicSession tsession;
>     protected TopicPublisher tpublisher;
>     protected Topic topic;
>     protected TextMessage msg;

Set up the JNDI initial context, as follows:

>     InitialContext ic = getInitialContext(args[0]);
>     	.
>     	.
>     	.
>     private static InitialContext getInitialContext(
>      String url
>     ) throws NamingException
>     {
>       Hashtable env = new Hashtable();
>       env.put(Context.INITIAL_CONTEXT_FACTORY, JNDI_FACTORY);
>       env.put(Context.PROVIDER_URL, url);
>       return new InitialContext(env);
>     }

Note: When setting up the JNDI initial context for a servlet, use the following method:

>     Context ctx = new InitialContext();

Create all the necessary objects for sending messages to a JMS queue. The `ctx` object is the JNDI initial context passed in by the `main()` method.

>     public void init(
>      Context ctx,
>      String topicName
>     ) throws NamingException, JMSException
>     {

### Step 1

Look up a connection factory using JNDI.

>       tconFactory =
>        (TopicConnectionFactory) ctx.lookup(JMS_FACTORY);

### Step 2

Create a connection using the connection factory.

>       tcon = tconFactory.createTopicConnection();

### Step 3

Create a session using the connection. The following defines the session as non-transacted and specifies that messages will be acknowledged automatically. For more information about setting session transaction and acknowledge modes, see Session.

>       tsession = tcon.createTopicSession(false,
>        Session.AUTO_ACKNOWLEDGE);

### Step 4

Look up the destination (topic) using JNDI.

>       topic = (Topic) ctx.lookup(topicName);

### Step 5

Create a reference to a message producer (topic publisher) using the session and destination (topic).

>       tpublisher = tsession.createPublisher(topic);

### Step 6

Create the message object.

>       msg = tsession.createTextMessage();

### Step 7

Start the connection.

>       tcon.start();
>      }

The `init()` method for the `examples.jms.topic.TopicReceive` example is similar to the `TopicSend` `init()` method shown previously with on exception. Steps 5 and 6 would be replaced by the following code, respectively:

>     tsubscriber = tsession.createSubscriber(topic);
>     tsubscriber.setMessageListener(this);

In the first line, instead of calling the `createPublisher()` method to create a reference to the topic publisher, the application calls the `createSubscriber()` method to create the topic subscriber.

In the second line, the message consumer registers an asynchronous message listener.

When a message is delivered to the topic session, it is passed to the `examples.jms.TopicSubscribe.onMessage()` method. The `onMessage()` interface for the `TopicReceive` example is the same as the QueueReceive `onMessage()` interface, as described in Example: Setting Up a PTP Application.

For more information about the JMS classes used in this example, see Understanding the JMS API or the javax.jms Javadoc.

# Sending Messages

Once you have set up the JMS application as described in Setting Up a JMS Application, you can send messages. To send a message, you must perform the following steps:

1. Create a Message Object.
2. Define a Message
3. Send the Message to a Destination

For more information about the JMS classes for sending messages and the message types, see the javax.jms.Message Javadoc. For information about receiving messages, see Receiving Messages.

## Create a Message Object

This step has already been accomplished as part of the client setup procedure, as described in Step 6a: Create the Message Object (Message Producers).

## Define a Message

This step may have been accomplished when setting up an application, as described in Step 6a: Create the Message Object (Message Producers). Whether or not this step has already been accomplished depends on the method that was called to create the message object. For example, for TextMessage and ObjectMessage types, when you create a message object, you have the option of defining the message when you create the message object.

If a value has been specified and you do not wish to change it, you can proceed to step 3.

If a value has not been specified or if you wish to change an existing value, you can define a value using the appropriate `set` method. For example, the method for defining the text of a `TextMessage` is as follows:

>     public void setText(
>      String string
>     ) throws JMSException

Note: Messages can be defined as null.

Subsequently, you can clear the message body using the following method:

>     public void clearBody(
>     ) throws JMSException

For more information about the methods used to define messages, see the javax.jms.Session Javadoc.

## Send the Message to a Destination

You can send a message to a destination using a message producer—queue sender (PTP) or topic publisher (Pub/Sub)—and the methods described in the following sections. The `Destination` and `MessageProducer` objects were created when you set up the application, as described in Setting Up a JMS Application.

Note: If multiple topic subscribers are defined for the same topic, each subscriber will receive its own local copy of a message. Once received, you can modify the header field values; however, the message properties and message body are read only. You can modify the message body by executing the corresponding message type's `clearbody()` method to clear the existing contents and enable write permission.

For more information about the `MessageProducer` class, see MessageProducer and MessageConsumer or the javax.jms.MessageProducer Javadoc.

### Send a Message Using Queue Sender

You can send messages using the following `QueueSender` methods:

>     public void send(
>      Message message
>     ) throws JMSException

>     public void send(
>      Message message,
>      int deliveryMode,
>      int priority,
>      long timeToLive
>     ) throws JMSException

>     public void send(
>      Queue queue,
>      Message message
>     ) throws JMSException

>     public void send(
>      Queue queue,
>      Message message,
>      int deliveryMode,
>      int priority,
>      long timeToLive
>     ) throws JMSException

You must specify a message. You may also specify the queue name (for anonymous message producers), delivery mode (`DeliveryMode.PERSISTENT` or `DeliveryMode.NON_PERSISTENT`), priority (`0-9`), and time-to-live (in milliseconds). If not specified, the delivery mode, priority, and time-to-live attributes are set to one of the following:

- Connection factory or destination override configuration attributes defined for the producer, as described "Configure default delivery parameters" in the Administration Console Online Help.
- Values specified using the message producer's set methods, as described in Setting Message Producer Attributes.

Notes: WebLogic JMS also provides the following proprietary attributes, as described in Setting Message Producer Attributes:

- `TimeToDeliver` (that is, birth time), which represents the delay before a sent message is made visible on its target destination.
- `RedeliveryLimit`, which determines the number of times a message is redelivered after a recover or rollback.
- `SendTimeout`, which is the maximum time the producer will wait for space when sending a message.

If you define the delivery mode as `PERSISTENT`, you should configure a backing store for the destination, as described in "Configure persistent stores" in the Administration Console Online Help.

Note: If no backing store is configured, then the delivery mode is changed to `NON_PERSISTENT` and messages are not written to the persistent store.

If the queue sender is an anonymous producer (that is, if when the queue was created, the name was set to null), then you must specify the queue name (using one of the last two methods) to indicate where to deliver messages. For more information about defining anonymous producers, see Create QueueSenders and QueueReceivers.

For example, the following code sends a persistent message with a priority of 4 and a time-to-live of one hour:

>     QueueSender.send(message, DeliveryMode.PERSISTENT, 4, 3600000);

For additional information about the `QueueSender` class methods, see the javax.jms.QueueSender Javadoc.

### Send a Message Using TopicPublisher

You can send messages using the following `TopicPublisher` methods:

>     public void publish(
>      Message message
>     ) throws JMSException

>     public void publish(
>      Message message,
>      int deliveryMode,
>      int priority,
>      long timeToLive
>     ) throws JMSException

>     public void publish(
>      Topic topic,
>      Message message
>     ) throws JMSException

>     public void publish(
>      Topic topic,
>      Message message,
>      int deliveryMode,
>      int priority,
>      long timeToLive
>     ) throws JMSException

You must provide a message. You may also specify the topic name, delivery mode (`DeliveryMode.PERSISTENT` or `DeliveryMode.NON_PERSISTENT`), priority (`0-9`), and time-to-live (in milliseconds). If not specified, the delivery mode, priority, and time-to-live attributes are set to one of the following:

- Connection factory or destination override configuration attributes defined for the producer, as described "Configure default delivery parameters" in the Administration Console Online Help.
- Values specified using the message producer's set methods, as described in Setting Message Producer Attributes.

Notes: WebLogic JMS also provides the following proprietary attributes, as described in Setting Message Producer Attributes:

- `TimeToDeliver` (that is, birth time), which represents the delay before a sent message is made visible on its target destination.
- `RedeliveryLimit`, which determines the number of times a message is redelivered after a recover or rollback.
- `SendTimeout`, which is the maximum time the producer will wait for space when sending a message.

If you define the delivery mode as `PERSISTENT`, you should configure a backing store, as described in "Configure persistent stores" in the Administration Console Online Help.

Note: If no backing store is configured, then the delivery mode is changed to `NON_PERSISTENT` and no messages are stored.

If the topic publisher is an anonymous producer (that is, if when the topic was created, the name was set to null), then you must specify the topic name (using either of the last two methods) to indicate where to deliver messages. For more information about defining anonymous producers, see Create TopicPublishers and TopicSubscribers.

For example, the following code sends a persistent message with a priority of 4 and a time-to-live of one hour:

>     TopicPublisher.publish(message, DeliveryMode.PERSISTENT,
>      4,3600000);

For more information about the `TopicPublisher` class methods, see the javax.jms.TopicPublisher Javadoc.

## Setting Message Producer Attributes

As described in the previous section, when sending a message, you can optionally specify the delivery mode, priority, and time-to-live values. If not specified, these attributes are set to the connection factory configuration attributes, as described in "Configure connection factories" in the Administration Console Online Help.

Alternatively, you can set the delivery mode, priority, time-to-deliver, time-to-live, and redelivery delay (timeout), and redelivery limit values dynamically using the message producer's set methods. The following table lists the message producer set and get methods for each dynamically configurable attribute.

Note: The delivery mode, priority, time-to-live, time-to-deliver, redelivery delay (timeout), and redelivery limit attribute settings can be overridden by the destination using the Delivery Mode Override, Priority Override, Time To Live Override, Time To Deliver Override, Redelivery Delay Override, and Redelivery Limit configuration attributes, as described in "Configure message delivery overrides: Queues" and "Configure message delivery overrides: Topics"in the Administration Console Online Help.

Table 4-2 Message Producer Set and Get Methods

Attribute | Set Method | Get Method
--- | --- | ---
Delivery Mode | `public void setDeliveryMode( int deliveryMode ) throws JMSException` | `public int getDeliveryMode( ) throws JMSException`
Priority | `public void setPriority( int defaultPriority ) throws JMSException` | `public int getPriority( ) throws JMSException`
Time-To-Live | `public void setTimeToLive( long timeToLive ) throws JMSException` | `public long getTimeToLive( ) throws JMSException`
Time-To-Deliver | `public void setTimeToDeliver( long timeToDeliver ) throws JMSException` | `public long getTimeToDeliver( ) throws JMSException`
Redelivery Limit | `public void setRedeliveryLimit( int redeliveryLimit ) throws JMSException` | `public int getredeliveryLimit( ) throws JMSException`
Send Timeout | `public void setsendTimeout( long sendTimeout ) throws JMSException` | `public long getsendTimeout( ) throws JMSException`

Note: JMS defines optional `MessageProducer` methods for disabling the message ID and timestamp information. However, these methods are ignored by WebLogic JMS.

For more information about the `MessageProducer` class methods, see Sun's javax.jms.MessageProducer Javadoc or the weblogic.jms.extensions.WLMessageProducer Javadoc.

## Example: Sending Messages Within a PTP Application

The following example is excerpted from the `examples.jms.queue.QueueSend` example, provided with WebLogic Server in the `WL_HOME``\samples\server\examples\src\examples\jms\queue` directory, where `WL_HOME` is the top-level directory of your WebLogic Platform installation. The example shows the code required to create a `TextMessage`, set the text of the message, and send the message to a queue.

>     msg = qsession.createTextMessage();
>     	.
>     	.
>     	.
>     public void send(
>      String message
>     ) throws JMSException
>     {
>      msg.setText(message);
>      qsender.send(msg);
>     }

For more information about the `QueueSender` class and methods, see the javax.jms.QueueSender Javadoc.

## Example: Sending Messages Within a Pub/Sub Application

The following example is excerpted from the `examples.jms.topic.TopicSend` example, provided with WebLogic Server in the `WL_HOME``\samples\server\examples\src\examples\jms\topic` directory, where `WL_HOME` is the top-level directory of your WebLogic Platform installation. It shows the code required to create a `TextMessage`, set the text of the message, and send the message to a topic.

>     msg = tsession.createTextMessage();
>     	.
>     	.
>     	.
>     public void send(
>      String message
>     ) throws JMSException
>     {
>      msg.setText(message);
>      tpublisher.publish(msg);
>     }

For more information about the `TopicPublisher` class and methods, see the javax.jms.TopicPublisher Javadoc.

# Receiving Messages

Once you have set up the JMS application as described in Setting Up a JMS Application, you can receive messages.

To receive a message, you must create the receiver object and specify whether you want to receive messages asynchronously or synchronously, as described in the following sections.

The order in which messages are received can be controlled by the following:

- Message delivery attributes (delivery mode and sorting criteria) defined during configuration or as part of the `send()` method, as described in Sending Messages.
- Destination sort order set using destination keys, as described in "Configure destination keys" in the Administration Console Online Help.

Once received, you can modify the header field values; however, the message properties and message body are read-only. You can modify the message body by executing the corresponding message type's `clearbody()` method to clear the existing contents and enable write permission.

For more information about the JMS classes for receiving messages and the message types, see the javax.jms.Message Javadoc. For information about sending messages, see Sending Messages.

## Receiving Messages Asynchronously

This procedure is described within the context of setting up the application. For more information, see Step 6b: Optionally Register an Asynchronous Message Listener (Message Consumers).

Note: You can control the maximum number of messages that may exist for an asynchronous consumer and that have not yet been passed to the message listener by setting the Messages Maximum attribute when configuring the connection factory.

### Asynchronous Message Pipeline

If messages are produced faster than asynchronous message listeners (consumers) can consume them, a JMS server will push multiple unconsumed messages in a batch to another session with available asynchronous message listeners. These in-flight messages are sometimes referred to as the message pipeline, or in some JMS vendors as the message backlog. The pipeline or backlog size is the number of messages that have accumulated on an asynchronous consumer, but which have not been passed to a message listener.

#### Configuring a Message Pipeline

You can control a client's maximum pipeline size by configuring the Messages Maximum per Session attribute on the client's connection factory, which is defined as the "maximum number of messages that can exist for an asynchronous consumer and that have not yet been passed to the message listener". The default setting is 10. For more information on configuring a JMS connection factory, see "Configure connection factories" in the Administration Console Online Help.

#### Behavior of Pipelined Messages

Once a message pipeline is configured, it will exhibit the following behavior:

- Statistics — JMS monitoring statistics reports backlogged messages in a message pipeline as pending (for queues and durable subscribers) until they are either committed or acknowledged.
- Performance — Increasing the Messages Maximum pipeline size may improve performance for high-throughput applications. Note that a larger pipeline will increase client memory usage, as the pending pipelined messages accumulate on the client JVM before the asynchronous consumer's listener is called.
- Sorting — Messages in an asynchronous consumer's pipeline are not sorted according to the consumer destination's configured sort order; instead, they remain in the order in which they are pushed from the JMS server. For example, if a destination is configured to sort by priority, high priority messages will not jump ahead of low priority messages that have already been pushed into an asynchronous consumer's pipeline.

Notes: The Messages Maximum per Session pipeline size setting on the connection factory is not related to the Messages Maximum quota settings on JMS servers and destinations.

Pipelined messages are sometimes aggregated into a single message on the network transport. If the messages are sufficiently large, the aggregate size of the data written may exceed the maximum value for the transport, which may cause undesirable behavior. For example, the `t3` protocol sets a default maximum message size of 10,000,000 bytes, and is configurable on the server with the `MaxT3MessageSize` attribute. This means that if ten 2 megabyte messages are pipelined, the `t3` limit may be exceeded.

## Receiving Messages Synchronously

To receive messages synchronously, use the following `MessageConsumer` methods:

>     public Message receive(
>     ) throws JMSException

>     public Message receive(
>      long timeout
>     ) throws JMSException

>     public Message receiveNoWait(
>     ) throws JMSException

In each case, the application receives the next message produced. If you call the `receive()` method with no arguments, the call blocks indefinitely until a message is produced or the application is closed. Alternatively, you can pass a timeout value to specify how long to wait for a message. If you call the `receive()` method with a value of 0, the call blocks indefinitely. The `receiveNoWait()` method receives the next message if one is available, or returns null; in this case, the call does not block.

The `MessageConsumer` class methods are inherited by the `QueueReceiver` and `TopicSubscriber` classes. For additional information about the `MessageConsumer` class methods, see the javax.jms.MessageConsumer Javadoc.

### Using the Prefetch Mode to Create a Synchronous Message Pipeline

In releases prior to WebLogic Server 9.1, synchronous consumers required making a two-way network calls for each message, which was an inefficient model because the synchronous consumer could not retrieve multiple messages, and could also increase network traffic resources, since synchronous consumers would continually poll the server for available messages. In WebLogic 9.1 or later, your synchronous consumers can also use the same efficient behavior as asynchronous consumers by enabling the Prefetch Mode for Synchronous Consumers option on JMS connection factories, either using the Administration Console or the JMSClientParamsBean MBean.

Similar to the asynchronous message pipeline, when the Prefetch Mode is enabled on a JMS client's connection factory, the connection factory's targeted JMS servers will proactively push batches of unconsumed messages to synchronous message consumers, using the connection factory's Messages Maximum per Session parameter to define the maximum number of messages per batch. This may improve performance because messages are ready and waiting for synchronous consumers when the consumers are ready to process more messages, and it may also reduce network traffic by reducing synchronous calls from consumers that must otherwise continually poll for messages.

Synchronous message prefetching does not support user (XA) transactions for synchronous message receives or multiple synchronous consumers per session (regardless of queue or topic). In most such cases, WebLogic JMS will silently and safely ignore the Prefetch Mode for Synchronous Consumer flag; however, otherwise WebLogic will fail the application's synchronous receive calls.

For more information on the behavior of pipelined messages, see Asynchronous Message Pipeline. For more information on configuring a JMS connection factory, see "Configure connection factories" in the Administration Console Online Help.

### Example: Receiving Messages Synchronously Within a PTP Application

The following example is excerpted from the `examples.jms.queue.QueueReceive` example, provided with WebLogic Server in the `WL_HOME``\samples\server\examples\src\examples\jms\queue` directory, where `WL_HOME` is the top-level directory of your WebLogic Platform installation. Rather than set a message listener, you would call `qreceiver.receive()` for each message. For example:

>     qreceiver = qsession.createReceiver(queue);
>     qreceiver.receive();

The first line creates the queue receiver on the queue. The second line executes a `receive()` method. The `receive()` method blocks and waits for a message.

### Example: Receiving Messages Synchronously Within a Pub/Sub Application

The following example is excerpted from the `examples.jms.topic.TopicReceive` example, provided with WebLogic Server in the `WL_HOME``\samples\server\examples\src\examples\jms\topic` directory, where `WL_HOME` is the top-level directory of your WebLogic Platform installation. Rather than set a message listener, you would call `tsubscriber.receive()` for each message.

For example:

>     tsubscriber = tsession.createSubscriber(topic);
>     Message msg = tsubscriber.receive();
>     msg.acknowledge();

The first line creates the topic subscriber on the topic. The second line executes a `receive()` method. The `receive()` method blocks and waits for a message.

## Recovering Received Messages

Note: This section applies only to non-transacted sessions for which the acknowledge mode is set to `CLIENT_ACKNOWLEDGE`, as described in Table 2-7. Synchronously received AUTO_ACKNOWLEDGE messages may not be recovered; they have already been acknowledged.

An application can request that JMS redeliver messages (unacknowledge them) using the following method:

>     public void recover(
>     ) throws JMSException

The `recover()` method performs the following steps:

- Stops message delivery for the session
- Tags all messages that have not been acknowledged (but may have been delivered) as redelivered
- Resumes sending messages starting from the first unacknowledged message for that session

Note: Messages in queues are not necessarily redelivered in the same order that they were originally delivered, nor to the same queue consumers. For information to guarantee the correct ordering of redelivered messages, see Ordered Redelivery of Messages.

# Acknowledging Received Messages

Note: This section applies only to non-transacted sessions for which the acknowledge mode is set to `CLIENT_ACKNOWLEDGE`, as described in Table 2-7.

To acknowledge a received message, use the following `Message` method:

>     public void acknowledge(
>     ) throws JMSException

The `acknowledge()` method depends on how the connection factory's Acknowledge Policy attribute is configured, as follows:

- The default policy of "All" specifies that calling acknowledge on a message acknowledges all unacknowledged messages received on the session.
- The "Previous" policy specifies that calling acknowledge on a message acknowledges only unacknowledged messages up to, and including, the given message. Messages that are not acknowledged may be redelivered to the client.

This method is effective only when issued by a non-transacted session for which the acknowledge mode is set to `CLIENT_ACKNOWLEDGE`. Otherwise, the method is ignored.

# Releasing Object Resources

When you have finished using the connection, session, message producer or consumer, connection consumer, or queue browser created on behalf of a JMS application, you should explicitly close them to release the resources.

Enter the `close()` method to close JMS objects, as follows:

>     public void close(
>     ) throws JMSException

When closing an object:

- The call blocks until the method call completes or until any outstanding asynchronous receiver `onMessage()` calls complete.
- All associated sub-objects are also closed. For example, when closing a session, all associated message producers and consumers are also closed. When closing a connection, all associated sessions are also closed.

For more information about the impact of the `close()` method for each object, see the appropriate javax.jms Javadoc. In addition, for more information about the connection or Session `close()` method, see Starting, Stopping, and Closing a Connection or Closing a Session, respectively.

The following example is excerpted from the `examples.jms.queue.QueueSend` example, provided with WebLogic Server in the `WL_HOME``\samples\server\examples\src\examples\jms\queue` directory, where `WL_HOME` is the top-level directory of your WebLogic Platform installation. This example shows the code required to close the message consumer, session, and connection objects.

>     public void close(
>     ) throws JMSException
>     {
>      qreceiver.close();
>      qsession.close();
>      qcon.close();
>     }

In the `QueueSend` example, the `close()` method is called at the end of `main()` to close objects and free resources.