Skip navigation.
Downloads | Product Documentation | Support

Programming WebLogic JMS

# Developing a WebLogic JMS Application

The following sections describe how to develop a WebLogic JMS application:

- Application Development Flow
- Importing Required Packages
- Setting Up a JMS Application
- Sending Messages
- Receiving Messages
- Acknowledging Received Messages
- Releasing Object Resources
- Managing Rolled Back, Recovered, Redelivered, or Expired Messages
- Setting Message Delivery Times
- Managing Connections
- Managing Sessions
- Creating Destinations Dynamically
- Deleting Destinations Dynamically
- Using Temporary Destinations
- Setting Up Durable Subscriptions
- Setting and Browsing Message Header and Property Fields
- Filtering Messages
- Defining Server Session Pools
- Using Multicasting
- Using Distributed Destinations

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

# Application Development Flow

When developing a WebLogic JMS application, you must perform the steps identified in the following figure.

Figure 4-1 WebLogic JMS Application Development Flow—Required Steps

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 multicasting
- Use JMS within transactions (described in Using Transactions with WebLogic JMS)

Except where noted, all application development steps are described in the following sections.

# 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.ServerSessionPoolFactory | Deprecated in WebLogic Server 8.1. The ServerSessionPoolFactory class is now available in the webLogic.jms.extensions package. See weblogic.jms.extensions.ServerSessionPoolFactory.
weblogic.jms.extensions | WebLogic-specific JMS public API that provides additional classes and methods, as described in WebLogic JMS Public API Extensions.

Include the following package `import` statements at the beginning of your program:

>     import javax.jms.*;
>     import javax.naming.*;
>     import javax.transaction.*;

If you implement a server session pool application, also include the following class on your import list:

>     import weblogic.jms.extensions.ServerSessionPoolFactory;

If you want to utilize any of the WebLogic JMS extension classes described in the previous table, also include the following statement on your import list:

>     import weblogic.jms.extensions.*;

# 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-2 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 features, including the connection factories, JMS servers, and destinations. For more information, see "Configuring JMS" in the Administration Console Online Help.

For more information about the JMS classes and methods described in these sections, see WebLogic JMS Classes, 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 "JMS Connection Factory Tasks" 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 NamingManager.InitialContext() method. For any application other than a servlet application, you must pass an environment used to create the initial context. For more information, see the NamingManager.InitialContext() Javadoc.

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 Object or the javax.jms.ConnectionFactory Javadoc.

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

You can create a connection for accessing a queue or topic using the `ConnectionFactory` methods described in the following sections.

For more information about the `Connection` class, see Connection Object 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.

Note: 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.

For more information about the `Session` class, see Session Object 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-6. 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 "Configuring JMS" in the Administration Console Online Help.

Once the destination has been configured, 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.

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

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

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

The syntax for the `queueName` and/or `topicName` string is JMS_Server_Name/Destination_Name (for example, `myjmsserver/mydestination`). To view source code that uses this syntax, refer to the `findqueue()` example in Creating Destinations Dynamically.

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 Creating Destinations Dynamically.

For more information about these methods, see the javax.jms.QueueSession and javax.jms.TopicSession Javadoc, respectively.

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.

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

### 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 Objects, 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 Setting Up Durable Subscriptions. 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 Object, 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 check box when configuring the connection factory. For more information on configuring JMS, see "Configuring JMS" in the Administration Console Online Help.

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 Session 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 Session 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 Objects 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 Object.

>       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 WebLogic JMS Classes 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 Object.

>         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 WebLogic JMS Classes 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.

## Step 1: 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).

## Step 2: 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.

## Step 3: 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 Objects 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 "Configuring JMS" 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 "JMS Store Tasks" 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 "Configuring JMS" 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 "Configuring JMS" 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 "Configuring JMS" 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 "Configuring Destinations" 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, as described in "Configuring JMS" in the Administration Console Online Help, or as part of the `send()` method, as described in Sending Messages.
- Destination sort order set using destination keys, as described in "Configuring JMS" 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 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 "JMS Connection Factory Tasks" 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 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.

### 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-6. 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-6.

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.

# Managing Rolled Back, Recovered, Redelivered, or Expired Messages

The following sections describe how to manage rolled back or recovered messages:

- Setting a Redelivery Delay for Messages
- Setting a Redelivery Limit for Messages
- Ordered Redelivery of Messages
- Handling Expired Messages

## Setting a Redelivery Delay for Messages

You can delay the redelivery of messages when a temporary, external condition prevents an application from properly handling a message. This allows an application to temporarily inhibit the receipt of "poison" messages that it cannot currently handle. When a message is rolled back or recovered, the redelivery delay is the amount of time a message is put aside before an attempt is made to redeliver the message.

If JMS immediately redelivers the message, the error condition may not be resolved and the application may still not be able to handle the message. However, if an application is configured for a redelivery delay, then when it rolls back or recovers a message, the message is set aside until the redelivery delay has passed, at which point the messages are made available for redelivery.

All messages consumed and subsequently rolled back or recovered by a session receive the redelivery delay for that session at the time of rollback or recovery. Messages consumed by multiple sessions as part of a single user transaction will receive different redelivery delays as a function of the session that consumed the individual messages. Messages that are left unacknowledged or uncommitted by a client, either intentionally or as a result of a failure, are not assigned a redelivery delay.

### Setting a Redelivery Delay

A session inherits the redelivery delay from its connection factory when the session is created. The `RedeliveryDelay` attribute of a connection factory is configured using the Administration Console. For more information, see "JMS Connection Factory Tasks" in the Administration Console Online Help.

The application that creates the session can then override the connection factory setting using WebLogic-specific extensions to the `javax.jms.Session` interface. The session attribute is dynamic and can be changed at any time. Changing the session redelivery delay affects all messages consumed and rolled back (or recovered) by that session after the change except when the message is in a session using non-durable topics.

Note: When a session is using non-durable topics, the `setRedeliveryDelay` method does not apply. This may result in unexpected behavior if you are using a non-durable topic consumer to drive a workflow.

The method for setting the redelivery delay on a session is provided through the `weblogic.jms.extensions.WLSession` interface, which is an extension to the `javax.jms.Session` interface. To define a redelivery delay for a session, use the following methods:

>     public void setRedeliveryDelay(
>       long redeliveryDelay
>     ) throws JMSException;

>     public long getRedeliveryDelay(
>     ) throws JMSException;

For more information on the `WLSession` class, refer to the weblogic.jms.extensions.WLSession Javadoc.

### Overriding the Redelivery Delay on a Destination

Regardless of what redelivery delay is set on the session, the destination where a message is being rolled back or recovered can override the setting. The redelivery delay override applied to the redelivery of a message is the one in effect at the time a message is rolled back or recovered.

The `RedeliveryDelayOverride` attribute of a destination is configured using the Administration Console. For more information, see "JMS Destination Tasks" in the Administration Console Online Help.

## Setting a Redelivery Limit for Messages

To better manage your system resources, you can specify a limit on the number of times that WebLogic JMS will attempt to redeliver messages to an application. You can also determine whether undeliverable messages are then redirected to a specified error destination on the local JMS server. If a redelivery limit is configured, but no error destination is configured, then persistent or non-persistent messages are simply deleted when they reach their redelivery limit, and no exception is thrown.

Note: The redelivery limit with no error destination behavior also applies to transactional messages, which are not rolled back for future redelivery, and no exception is thrown.

Alternatively, you can set the redelivery limit value dynamically using the message producer's set method, as described in Setting Message Producer Attributes.

### Configuring a Message Redelivery Limit On a Destination

When a destination's attempts to redeliver a message to a consumer reaches a specified redelivery limit, then the destination deems the message undeliverable. The `RedeliveryLimit` attribute is set on a destination and is configurable using the Administration Console. This setting overrides the redelivery limit set on the message producer. For more information, see "JMS Destination Tasks" in the Administration Console Online Help.

### Configuring an Error Destination for Undelivered Messages

If an error destination is configured on a JMS server for undelivered messages, then when a message has been deemed to be undeliverable to a destination, the message is then redirected to the error destination. The error destination can be either a queue or a topic destination. It must be configured on the same JMS server as the destination for which it is defined. If no error destination is configured, then undeliverable messages are simply deleted.

Once an error destination is configured for the JMS server (for example, `exampleQueueError`) existing destinations can select the error destination using the `Error Destination` attribute on the Configuration —> Redelivery tab on the Administration Console. For more information, see "JMS Destination Tasks" in the Administration Console Online Help.

## Ordered Redelivery of Messages

As per the JMS Specification, all messages initially delivered to a consumer from a given producer are guaranteed to arrive at the consumer in the order in which they were produced. WebLogic JMS goes above and beyond this requirement by providing the "Ordered Redelivery of Messages" feature, which guarantees the correct ordering of redelivered messages as well.

In order to provide this guarantee, WebLogic JMS must impose certain constraints. They are:

- Single consumers — ordered redelivery is only guaranteed when there is a single consumer. If there are multiple consumers, then there are no guarantees about the order in which any individual consumer will receive messages.

Note: With respect to MDBs (message-driven beans), the number of consumers is a function of the number of MDB instances deployed for a given MDB. The initial and maximum values for the number of instances must be set to 1. Otherwise, no ordering guarantees can be made with respect to redelivered messages.

- Sort order — if a given destination is sorted, has JMS destination keys defined, and another message is produced such that the message would be placed at the top of the ordering, then no guarantee can be made between the redelivery of an existing message and the delivery of the incoming message.
- Message selection — if a consumer is using a selector, then ordering on redelivery is only guaranteed between the message being redelivered and other messages that match the criteria for that selector. There are no guarantees of order with respect to messages that do not match the selector.
- Redelivery delay — if a message has a redelivery delay period and is recovered or rolled back, then it is unavailable for the delay period. During that period, other messages can be delivered before the delayed message—even though these messages were sent after the delayed message.
- Messages pending recovery — ordered redelivery does not apply to redelivered messages that end up in a pending recovery state due to a server failure or a system reboot.
- Configure the message pipeline for asynchronous consumers — for ordered redelivery to occur for all asynchronous consumers, explicitly set the Messages Maximum = 1 on the connection factory used by the receiving application. For more information, see Required Connection Factory Configuration for Asynchronous Consumers (including the Messaging Bridge and MDBs).

### Required Connection Factory Configuration for Asynchronous Consumers (including the Messaging Bridge and MDBs)

In order for ordered redelivery to occur for asynchronous consumers, including JMS applications that use the WebLogic Messaging Bridge or MDBs, the size of the message pipeline must be set to 1. The message pipeline size is set using the Messages Maximum attribute on the JMS connection factory used by the receiving application. Any value higher than 1 means there may be additional in-flight messages that will appear ahead of a redelivered message. MDB applications must define an application-specific JMS connection factory and set the Messages Maximum attribute value to 1 on that connection factory, and then reference the connection factory in the EJB descriptor for their MDB application.

For more information about configuring a JMS connection factory, see "JMS Connection Factory Tasks" in the Administration Console Online Help.

For more information about configuring a Messaging Bridge, see "WebLogic Messaging Bridge" in the Administration Console Online Help.

For more information about programming EJBs, see "Designing Message-Driven Beans" in Programming WebLogic Enterprise JavaBeans.

### Performance Limitations

JMS applications that implement the Ordered Redelivery feature will incur performance degradation for asynchronous consumers using JTA transactions (specifically, MDBs and the WebLogic Messaging Bridge). This is caused by a mandatory reduction in the number of in-flight messages to exactly 1, so messages are not aggregated when they are sent to the client.

## Handling Expired Messages

WebLogic JMS has an active message Expiration Policy feature that allows you to control how the system searches for expired messages and how it handles them when they are encountered. This feature ensures that expired messages are cleaned up immediately, either by simply discarding expired messages, discarding expired messages and logging their removal, or redirecting expired messages to an error destination configured on the local JMS server.

For more information about the configuring an message Expiration Policy, see "Handling Expired Messages" in the Administration Console Online Help.

# Setting Message Delivery Times

You can schedule message deliveries to an application for specific times in the future. Message deliveries can be deferred for short periods of time (such as seconds or minutes) or for long stretches of time (for example, hours later for batch processing). Until that delivery time, the message is essentially invisible until it is delivered, allowing you to schedule work at a particular time in the future.

Messages are not sent on a recurring basis; they are sent only once. In order to send messages on a recurring basis, a received scheduled message must be sent back to its original destination. Typically, the receive, the send, and any associated work should be under the same transaction to ensure exactly-once semantics.

## Setting a Delivery Time on Producers

Support for setting and getting a time-to-deliver on an individual producer is provided through the `weblogic.jms.extensions.WLMessageProducer` interface, which is an extension to the `javax.jms.MessageProducer` interface. To define a time-to-deliver on an individual producer, use the following methods:

>     public void setTimeToDeliver(
>       long timeToDeliver
>     ) throws JMSException;

>     public long getTimeToDeliver(
>     ) throws JMSException;

For more information on the `WLMessageProducer` class, refer to the weblogic.jms.extensions.WLMessageProducer Javadoc.

## Setting a Delivery Time on Messages

The `DeliveryTime` is a JMS message header field that defines the earliest absolute time at which the message can be delivered. That is, the message is held by the messaging system and is not given to any consumers until that time.

As a JMS header field, the `DeliveryTime` can be used to sort messages in a destination or to select messages. For purposes of data type conversion, the delivery time is stored as a long integer.

Note: Setting a delivery time value on a message has no effect on this field, because JMS will always override the value with the producer's value when the message is sent or published. The message delivery time methods described here are similar to other JMS message fields that are set through the producer, including the delivery mode, priority, time-to-deliver, time-to-live, redelivery delay, and redelivery limit fields. Specifically, the setting of these fields is reserved for JMS providers, including WebLogic JMS.

The support for setting and getting the delivery time on a message is provided through the `weblogic.jms.extensions.WLMessage` interface, which is an extension to the `javax.jms.Message` interface. To define a delivery time on a message, use the following methods:

>     public void setJMSDeliveryTime(
>       long deliveryTime
>     ) throws JMSException;

>     public long getJMSDeliveryTime(
>     ) throws JMSException;

For more information on the `WLMessage` class, refer to the weblogic.jms.extensions.WLMessage Javadoc.

## Overriding a Delivery Time

When a producer is created it inherits its `TimeToDeliver` attribute, expressed in milliseconds, from the connection factory used to create the connection that the producer is a part of. Regardless of what time-to-deliver is set on the producer, the destination to which a message is being sent or published can override the setting. An administrator can set the `TimeToDeliverOverride` attribute on a destination in either a relative or scheduled string format.

### Interaction With the Time-to-Live Value

If the specified time-to-live value (`JMSExpiration`) is less than or equal to the specified time-to-deliver value, then the message delivery succeeds. However, the message is then silently expired.

### Setting a Relative Time-to-Deliver Override

A relative `TimeToDeliverOverride` is a String specified as an integer, and is configurable using the Administration Console. For more information, see "JMS Destination Tasks" in the Administration Console Online Help.

### Setting a Scheduled Time-to-Deliver Override

A scheduled `TimeToDeliverOverride` can also be specified using the weblogic.jms.extensions.Schedule class, which provides methods that take a schedule and return the next scheduled time for delivering messages.

Example | Description
--- | ---
`0 0 0,30 * * * *` | Exact next nearest half-hour
`* * 0,30 4-5 * * *` | Anytime in the first minute of the half hours in the 4 A.M. and 5 A.M. hours
`* * * 9-16 * * *` | Between 9 A.M. and 5 P.M. (9:00.00 A.M. to 4:59.59 P.M.)
`* * * * 8-14 * 2` | The second Tuesday of the month
`* * * 13-16 * * 0` | Between 1 P.M. and 5 P.M. on Sunday
`* * * * * 31 *` | The last day of the month
`* * * * 15 4 1` | The next time April 15th occurs on a Sunday
`0 0 0 1 * * 2-6;0 0 0 2 * * 1,7` | 1 A.M. on weekdays; 2 A.M. on weekends

A cron-like string is used to define the schedule. The format is defined by the following BNF syntax:

>     schedule := millisecond second minute hour dayOfMonth month
>                 dayOfWeek

The BNF syntax for specifying the `second` field is as follows:

>     second      := * | secondList
>     secondList  := secondItem [, secondList]
>     secondItem  := secondValue | secondRange
>     SecondRange := secondValue - secondValue

Similar BNF statements for milliseconds, minute, hour, day-of-month, month, and day-of-week can be derived from the second syntax. The values for each field are defined as non-negative integers in the following ranges:

>     milliSecondValue := 0-999
>     milliSecondValue := 0-999
>     secondValue      := 0-59
>     minuteValue      := 0-59
>     hourValue        := 0-23
>     dayOfMonthValue  := 1-31
>     monthValue       := 1-12
>     dayOfWeekValue   := 1-7

Note: These values equate to the same ranges that the `java.util.Calendar` class uses, except for `monthValue`. The `java.util.Calendar` range for `monthValue` is 0-11, rather than 1-12.

Using this syntax, each field can be represented as a range of values indicating all times between the two times. For example, `2-6` in the `dayOfWeek` field indicates Monday through Friday, inclusive. Each field can also be specified as a comma-separated list. For instance, a minute field of `0,15,30,45` means every quarter hour on the quarter hour. Lastly, each field can be defined as both a set of individual values and ranges of values. For example, an hour field of `9-17,0` indicates between the hours of 9 A.M. and 5 P.M., and on the hour of midnight.

Additional semantics are as follows:

- If multiple schedules are supplied (using a semi-colon (;) as the separator), the next scheduled time for the set is determined using the schedule that returns the soonest value. One use for this is for specifying schedules that change based on the day of the week (see the final example below).
- A value of 1 (one) for the `dayOfWeek` equates to Sunday.
- A value of * means every time for that field. For instance, a * in the Month field means every month. A * in the Hour field means every hour.
- A value of `l` or `last` (not case sensitive) indicates the greatest possible value for a field.
- If a day-of-month is specified that exceeds the normal maximum for a month, then the normal maximum for that month will be specified. For example, if it is February during a leap year and 31 was specified, then the scheduler will schedule as if 29 was specified instead. This means that setting the month field to 31 always indicates the last day of the month.
- If milliseconds are specified, they are rounded down to the nearest 50th of a second. The values are 0, 19, 39, 59, ..., 979, and 999. Thus, 0-40 gets rounded to 0-39 and 50-999 gets rounded to 39-999.

Note: When a Calendar is not supplied as a method parameter to one of the static methods in this class, the calendar used is a `java.util.GregorianCalendar` with a default `java.util.TimeZone` and a default `java.util.Locale`.

### JMS Schedule Interface

The `weblogic.jms.extensions.schedule` class has methods that will return the next scheduled time that matches the recurring time expression. This expression uses the same syntax as the `TimeToDeliverOverride`. The time returned in milliseconds can be relative or absolute.

For more information on the `WLSession` class, refer to the weblogic.jms.extensions.Schedule Javadoc.

You can define the next scheduled time after the given time using the following method:

>     public static Calendar nextScheduledTime(
>         String schedule,
>         Calendar calendar
>       ) throws ParseException {

You can define the next scheduled time after the current time using the following method:

>     public static Calendar nextScheduledTime(
>         String schedule,
>           ) throws ParseException {

You can define the next scheduled time after the given time in absolute milliseconds using the following method:

>     public static long nextScheduledTimeInMillis(
>         String schedule,
>         long timeInMillis
>       ) throws ParseException

You can define the next scheduled time after the given time in relative milliseconds using the following method:

>     public static long nextScheduledTimeInMillisRelative(
>         String schedule,
>         long timeInMillis
>       ) throws ParseException {

You can define the next scheduled time after the current time in relative milliseconds using the following method:

>     public static long nextScheduledTimeInMillisRelative(
>         String schedule
>       ) throws ParseException {

# Managing Connections

The following sections describe how to manage connections:

- Defining a Connection Exception Listener
- Accessing Connection Metadata
- Starting, Stopping, and Closing a Connection

## Defining a Connection Exception Listener

An exception listener asynchronously notifies an application whenever a problem occurs with a connection. This mechanism is particularly useful for a connection waiting to consume messages that might not be notified otherwise.

Note: The purpose of an exception listener is not to monitor all exceptions thrown by a connection, but to deliver those exceptions that would not be otherwise be delivered.

You can define an exception listener for a connection using the following `Connection` method:

>     public void setExceptionListener(
>       ExceptionListener listener
>     ) throws JMSException

You must specify an `ExceptionListener` object for the connection.

The JMS Provider notifies an exception listener, if one has been defined, when it encounters a problem with a connection using the following `ExceptionListener` method:

>     public void onException(
>       JMSException exception
>     )

The JMS Provider specifies the exception that describes the problem when calling the method.

You can access the exception listener for a connection using the following Connection method:

>     public ExceptionListener getExceptionListener(
>     ) throws JMSException

## Accessing Connection Metadata

You can access the metadata associated with a specific connection using the following `Connection` method:

>     public ConnectionMetaData getMetaData(
>     ) throws JMSException

This method returns a `ConnectionMetaData` object that enables you to access JMS metadata. The following table lists the various type of JMS metadata and the get methods that you can use to access them.

JMS Metadata | Get Method
--- | ---
Version | `public String getJMSVersion( ) throws JMSException`
Major version | `public int getJMSMajorVersion( ) throws JMSException`
Minor version | `public int getJMSMinorVersion( ) throws JMSException`
Provider name | `public String getJMSProviderName( ) throws JMSException`
Provider version | `public String getProviderVersion( ) throws JMSException`
Provider major version | `public int getProviderMajorVersion( ) throws JMSException`
Provider minor version | `public int getProviderMinorVersion( ) throws JMSException`
JMSX property names | public Enumeration getJMSXPropertyNames( ) throws JMSException

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

## Starting, Stopping, and Closing a Connection

To control the flow of messages, you can start and stop a connection temporarily using the `start()` and `stop()` methods, respectively, as follows.

The `start()` and `stop()` method details are as follows:

>     public void start(
>     ) throws JMSException

>     public void stop(
>     ) throws JMSException

A newly created connection is stopped—no messages are received until the connection is started. Typically, other JMS objects are set up to handle messages before the connection is started, as described in Setting Up a JMS Application. Messages may be produced on a stopped connection, but cannot be delivered to a stopped connection.

Once started, you can stop a connection using the `stop()` method. This method performs the following steps:

- Pauses the delivery of all messages. No applications waiting to receive messages will return until the connection is restarted or the time-to-live value associated with the message is reached.
- Waits until all message listeners that are currently processing messages have completed.

Typically, a JMS Provider allocates a significant amount of resources when it creates a connection. When a connection is no longer being used, you should close it to free up resources. A connection can be closed using the following method:

>     public void close(
>     ) throws JMSException

This method performs the following steps to execute an orderly shutdown:

- Terminates the receipt of all pending messages. Applications may return a message or null if a message was not available at the time of the close.
- Waits until all message listeners that are currently processing messages have completed.
- Rolls back in-process transactions on its transacted sessions (unless such transactions are part of an external JTA user transaction). For more information about JTA user transactions, see Using JTA User Transactions.
- Does not force an acknowledge of client-acknowledged sessions. By not forcing an acknowledge, no messages are lost for queues and durable subscriptions that require reliable processing.

When you close a connection, all associated objects are also closed. You can continue to use the message objects created or received via the connection, except the received message's `acknowledge()` method. Closing a closed connection has no effect.

Note: Attempting to acknowledge a received message from a closed connection's session throws an `IllegalStateException`.

# Managing Sessions

The following sections describe how to manage sessions, including:

- Defining a Session Exception Listener
- Closing a Session

## Defining a Session Exception Listener

An exception listener asynchronously notifies a client in the event a problem occurs with a session. This is particularly useful for a session waiting to consume messages that might not be notified otherwise.

Note: The purpose of an exception listener is not to monitor all exceptions thrown by a session, only to deliver those exceptions that would otherwise be undelivered.

You can define an exception listener for a session using the following `WLSession` method:

>     public void setExceptionListener(
>       ExceptionListener listener
>     ) throws JMSException

You must specify an `ExceptionListener` object for the session.

The JMS Provider notifies an exception listener, if one has been defined, when it encounters a problem with a session using the following `ExceptionListener` method:

>     public void onException(
>       JMSException exception
>     )

The JMS Provider specifies the exception encountered that describes the problem when calling the method.

You can access the exception listener for a session using the following `WLSession` method:

>     public ExceptionListener getExceptionListener(
>     ) throws JMSException

Note: Because there can only be one thread per session, an exception listener and message listener (used for asynchronous message delivery) cannot execute simultaneously. Consequently, if a message listener is executing at the time a problem occurs, execution of the exception listener is blocked until the message listener completes its execution. For more information about message listeners, see Receiving Messages Asynchronously.

## Closing a Session

As with connections, a JMS Provider allocates a significant amount of resources when it creates a session. When a session is no longer being used, it is recommended that it be closed to free up resources. A session can be closed using the following `Session` method:

>     public void close(
>     ) throws JMSException

Note: The `close()` method is the only `Session` method that can be invoked from a thread that is separate from the session thread.

This method performs the following steps to execute an orderly shutdown:

- Terminates the receipt of all pending messages. Applications may return a message or null if a message was not available at the time of the close.
- Waits until all message listeners that are currently processing messages have completed.
- Rolls back in-process transactions (unless such transactions are part of external JTA user transaction). For more information about JTA user transactions, see Using JTA User Transactions.
- Does not force an acknowledge of client acknowledged sessions, ensuring that no messages are lost for queues and durable subscriptions that require reliable processing.

When you close a session, all associated producers and consumers are also closed.

Note: If you want to issue the `close()` method within an `onMessage()` method call, the system administrator must select the Allow Close In OnMessage check box when configuring the connection factory. For more information, see "JMS Connection Factory Tasks" in the Administration Console Online Help.

# Creating Destinations Dynamically

You can create destinations dynamically using:

- `weblogic.jms.extensions.JMSHelper` class methods. See Using JMS Helper to Manage Applications.
- Temporary destinations. See Using Temporary Destinations.

# Deleting Destinations Dynamically

You can dynamically delete JMS destinations (queue or topic) using any of the following methods:

- `weblogic.jms.extensions.JMSHelper` class method. See Using JMS Helper to Manage Applications.
- Administration console
- User-defined JMX application. See Using Temporary Destinations

The JMS server removes the deleted destination in real time, therefore, it's not necessary to redeploy the JMS server for the deletion to take effect. The associated procedures for dynamically deleting destinations are described in the following sections.

## Preconditions for Deleting Destinations

In order to successfully delete a destination, the following preconditions must be met:

- The destination must not be a member of a distributed destination. For more information, see Using Distributed Destinations.
- The destination must not be the error destination for some other destination. For more information, see Configuring an Error Destination for Undelivered Messages.

If either of these preconditions cannot be met, then the deletion will not be allowed.

## When a Destination is Deleted

When a destination is deleted, the following behaviors and semantics apply:

- Physical deletion of existing messages—all durable subscribers for the deleted destination are permanently deleted. All messages, persistent and non-persistent, stored in the deleted destination are permanently removed from the messaging system.
- No longer able to create producers, consumers, and browsers—Once a destination is deleted, applications will no longer be able to create producers, consumers, or browsers for the deleted destination. Any attempt to do so will result in the application receiving an `InvalidDestinationException` — as if the destination does not exist.
- Closing of consumers—All existing consumers for the deleted destination are closed. The closing of a consumer generates a `ConsumerClosedException`, which is delivered to the `ExceptionListener`, if any, of the parent session, and which will read "Destination was deleted".

When a consumer is closed, if it has an outstanding `receive()` operation, then that operation is cancelled and the caller receives a `null` indicating that no message is available. Attempts by an application to do anything but `close()` a closed consumer will result in an `IllegalStateException`.

- Closing of browsers—All browsers for the deleted destination are closed. Attempts by an application to do anything but `close()` a closed browser will result in an `IllegalStateException`. Closing of a browser implicitly closes all enumerations associated with the browser.
- Closing of enumerations—All enumerations for the deleted destination are closed. The behavior after an enumeration is closed depends on the last call before the enumeration was closed. If a call to `hasMoreElements()` returns a value of true, and no subsequent call to `nextElement()` has been made, then the enumeration guarantees that the next element can be enumerated. This produces the specifics. When the last call before the close was to `hasMoreElements()`, and the value returned was true, then the following behaviors apply:

- The first call to `nextElement()` will return a message.
- Subsequent calls to `nextElement()` will throw a `NoSuchElementException`.
- Calls to `hasMoreElements()` made before the first call to `nextElement()` will return true.
- Calls to `hasMoreElements()` made after the first call to `nextElement()` will return false.

If a given enumeration has never been called, or the last call before the close was to `nextElement()`, or the last call before the close was to `hasMoreElements()` and the value returned was false, then the following behaviors apply:

- Calls to `hasMoreElements()` will return false.
- Calls to `nextElement()` will throw a `NoSuchElementException`.

- Blocking send operations cancelled—All blocking send operations posted against the deleted destination are cancelled. Send operations waiting for quota will receive a `ResourceAllocationException`. For more information on using blocking send operations, see "Avoiding Quota Exceptions by Blocking Message Producers" in the Administration Console Online Help.
- Uncommitted transactions unaffected—The deletion of a destination does not affect existing uncommitted transactions. Any uncommitted work associated with a deleted destination is allowed to complete as part of the transaction. However, since the destination is deleted, the net result of all operations (rollback, commit, etc.) is the deletion of the associated messages.

### Message Timestamps for Troubleshooting Deleted Destinations

If a destination with persistent messages is deleted and then immediately recreated while the JMS server is not running, the JMS server will compare the version number of the destination (using the `CreationTime` field in the configuration `config.xml` file) and the version number of the destination in the persistent messages. In this case, the left over persistent messages for the older destination will have an older version number than the version number in the `config.xml` file for the recreated destination, and when the JMS server is rebooted, the left over persistent messages are simply discarded.

However, if a persistent message somehow has a version number that is newer than the version number in the `config.xml` for the recreated destination, then either the system clock was rolled back when the destination was deleted and recreated (while the JMS server was not running), or a different `config.xml` is being used. In this situation, the JMS server will fail to boot. To save the persistent message, you can set the version number (the `CreationTime` field) in the `config.xml` to match the version number in the persistent message. Otherwise, you can change the version number in the `config.xml` so that it is newer than the version number in the persistent message; this way, the JMS server can delete the message when it is rebooted.

### Deleted Destination Statistics

Statistics for the deleted destination and the hosting JMS server are updated as the messages are physically deleted. However, the deletion of some messages can be delayed pending the outcome of another operation. This includes messages sent and/or received in a transaction, as well as unacknowledged non-transactional messages received by a client.

# Using Temporary Destinations

Temporary destinations enable an application to create a destination, as required, without the system administration overhead associated with configuring and creating a server-defined destination.

JMS applications can use the `JMSReplyTo` header field to return a response to a request. The sender application may optionally set the `JMSReplyTo` header field of its messages to its temporary destination name to advertise the temporary destination that it is using to other applications.

Temporary destinations exist only for the duration of the current connection, unless they are removed using the `delete()` method, described in Deleting a Temporary Destination.

Because messages are never available if the server is restarted, all `PERSISTENT` messages are silently made `NON_PERSISTENT`. As a result, temporary destinations are not suitable for business logic that must survive a restart.

Note: Before creating a temporary destination (queue or topic), you must use the Administration Console to configure the JMS server to use temporary destinations. This is done by using the JMS server's `Temporary Template` attribute to select a JMS template that is configured in the same domain. For more information about configuring a JMS server, see "JMS Server Tasks" in the Administration Console Online Help.

The following sections describe how to create a temporary queue (PTP) or temporary topic (Pub/Sub).

## Creating a Temporary Queue

You can create a temporary queue using the following `QueueSession` method:

>     public TemporaryQueue createTemporaryQueue(
>     ) throws JMSException

For example, to create a reference to a `TemporaryQueue` that will exist only for the duration of the current connection, use the following method call:

`QueueSender = Session.createTemporaryQueue();`

## Creating a Temporary Topic

You can create a temporary topic using the following `TopicSession` method:

>     public TemporaryTopic createTemporaryTopic(
>     ) throws JMSException

For example, to create a reference to a temporary topic that will exist only for the duration of the current connection, use the following method call:

`TopicPublisher = Session.createTemporaryTopic();`

## Deleting a Temporary Destination

When you finish using a temporary destination, you can delete it (to release associated resources) using the following `TemporaryQueue` or `TemporaryTopic` method:

>     public void delete(
>     ) throws JMSException

# Setting Up Durable Subscriptions

WebLogic JMS supports durable and non-durable subscriptions.

For durable subscriptions, WebLogic JMS stores a message in a persistent file or database until the message has been delivered to the subscribers or has expired, even if those subscribers are not active at the time that the message is delivered. A subscriber is considered active if the Java object that represents it exists. Durable subscriptions are supported for Pub/Sub messaging only.

Note: Durable subscriptions cannot be created for distributed topics. However, you can still create a durable subscription on distributed topic member and the other topic members will forward the messages to the member that has the durable subscription. For more information on using distributed topics, see Using Distributed Destinations.

For non-durable subscriptions, WebLogic JMS delivers messages only to applications with an active session. Messages sent to a topic while an application is not listening are never delivered to that application. In other words, non-durable subscriptions last only as long as their subscriber objects. By default, subscribers are non-durable.

The following sections describe:

- Defining the Persistent Store
- Defining the Client ID
- Creating Subscribers for a Durable Subscription
- Deleting Durable Subscriptions
- Modifying Durable Subscriptions
- Managing Durable Subscriptions

## Defining the Persistent Store

You must configure a persistent file or database store and assign it to your JMS server so WebLogic JMS can store a message until it has been delivered to the subscribers or has expired.

- Create a JMS file store or JMS JDBC backing store using the Stores node.
- Target the configured store to your JMS server by selecting it from the Store field's drop-down list on the JMS Server —> Configuration —> General tab.

Note: No two JMS servers can use the same backing store.

For more information about configuring JMS stores, see "Configuring JMS" in the Administration Console Online Help.

## Defining the Client ID

To support durable subscriptions, a client identifier (client ID) must be defined for the connection.

Note: The JMS client ID is not necessarily equivalent to the WebLogic Server username, that is, a name used to authenticate a user in the WebLogic security realm. You can, of course, set the JMS client ID to the WebLogic Server username, if it is appropriate for your JMS application.

The client ID can be supplied in two ways:

- The first method is to configure the connection factory with the client ID. For WebLogic JMS, this means adding a separate connection factory definition during configuration for each client ID. Applications then look up their own topic connection factories in JNDI and use them to create connections containing their own client IDs. For more information about configuring a connection factory with a client ID, see "JMS Connection Factory Tasks" in the Administration Console Online Help.

In JNDI, every "`.`" is a subnode separator. The normal subnode prefix for `clientid` is `weblogic.jms.connection.clientid`. Once this has been created it is not removed. So, if your `clientId` name is `XYZ`, JNDI will create a new subnode called `XYZ` (`weblogic.jms.connection.clientid.XYZ`). When you close the connection and unbind `XYZ`, only the subnode `XYZ` is removed from the JNDI map. The prefix subnodes are left in place.

Note: Defining unique `clientId` names that include multiple "`.`" separators may result in memory growth resulting from the fact that when the `clientId` is removed, only the final subnode is removed from the map. So, it is recommend that you use a naming convention for `clientIds` that does not include "." separators in the name.

- Alternatively, the preferred method is for an application that can set its client ID in the connection after the connection is created by calling the following connection method:

>     public void setClientID(
>       String clientID
>     ) throws JMSException

You must specify a unique client ID. If you use this alternative approach, you can use the default connection factory (if it is acceptable for your application) and avoid the need to modify the configuration information. However, applications with durable subscriptions must ensure that they call `setClientID()` immediately after creating their topic connection. For information on the default connection factory, see "Configuring JMS" in the Administration Console Online Help.

If a client ID is already defined for the connection, an `IllegalStateException` is thrown. If the specified client ID is already defined for another connection, an `InvalidClientIDException` is thrown.

Note: When specifying the client ID using the `setClientID()` method, there is a risk that a duplicate client ID may be specified without throwing an exception. For example, if the client IDs for two separate connections are set simultaneously to the same value, a race condition may occur and the same value may be assigned to both connections. You can avoid this risk of duplication by specifying the client ID during configuration.

To display a client ID and test whether or not a client ID has already been defined, use the following Connection method:

>     public String getClientID(
>     ) throws JMSException

Note: Support for durable subscriptions is a feature unique to the Pub/Sub messaging model, so client IDs are used only with topic connections; queue connections also contain client IDs, but JMS does not use them.

Durable subscriptions should not be created for a temporary topic, because a temporary topic is designed to exist only for the duration of the current connection.

## Creating Subscribers for a Durable Subscription

You can create subscribers for a durable subscription using the following `TopicSession` methods:

>     public TopicSubscriber createDurableSubscriber(
>       Topic topic,
>       String name
>     ) throws JMSException

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

You must specify the name of the topic for which you are creating a subscriber, and the name of the durable subscription. 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 do not specify a `messageSelector`, by default all messages are searched.

An application can use a JMS connection to both publish and subscribe to the same topic. Because topic messages are delivered to all subscribers, an application can receive messages it has published itself. To prevent this, a JMS application can set a `noLocal` flag to `true`. The `noLocal` value defaults to `false`.

The durable subscription `name` must be unique per client ID. For information on defining the client ID for the connection, see Defining the Client ID.

Only one session can define a subscriber for a particular durable subscription at any given time. Multiple subscribers can access the durable subscription, but not at the same time. Durable subscriptions are stored within the file or database.

## Deleting Durable Subscriptions

To delete a durable subscription, you use the following `TopicSession` method:

>     public void unsubscribe(
>       String name
>     ) throws JMSException

You must specify the name of the durable subscription to be deleted.

You cannot delete a durable subscription if any of the following are true:

- A `TopicSubscriber` is still active on the session.
- A message received by the durable subscription is part of a transaction or has not yet been acknowledged in the session.

Note: You can also delete durable subscriptions from the Administration Console. For information on managing durable subscriptions, see Managing Durable Subscriptions.

## Modifying Durable Subscriptions

To modify a durable subscription, perform the following steps:

1. Optionally, delete the durable subscription, as described in Deleting Durable Subscriptions.

This step is optional. If not explicitly performed, the deletion will be executed implicitly when the durable subscription is recreated in the next step.

2. Use the methods described in Creating Subscribers for a Durable Subscription to recreate a durable subscription of the same name, but specifying a different topic name, message selector, or `noLocal` value.

The durable subscription is recreated based on the new values.

Note: When recreating a durable subscription, be careful to avoid creating a durable subscription with a duplicate name. For example, if you attempt to delete a durable subscription from a JMS server that is unavailable, the delete call fails. If you subsequently create a durable subscription with the same name on a different JMS server, you may experience unexpected results when the first JMS server becomes available. Because the original durable subscription has not been deleted, when the first JMS server again becomes available, there will be two durable subscriptions with duplicate names.

## Managing Durable Subscriptions

You can monitor and delete durable subscriptions from the Administration Console. For more information, see "Configuring JMS" in the Administration Console Online Help.

# Setting and Browsing Message Header and Property Fields

WebLogic JMS provides a set of standard header fields that you can define to identify and route messages. In addition, property fields enable you to include application-specific header fields within a message, extending the standard set. You can use the message header and property fields to convey information between communicating processes.

The primary reason for including data in a property field rather than in the message body is to support message filtering via message selectors. Except for XML message extensions, data in the message body cannot be accessed via message selectors. For example, suppose you use a property field to assign high priority to a message. You can then design a message consumer containing a message selector that accesses this property field and selects only messages of expedited priority. For more information about selectors, see Filtering Messages.

## Setting Message Header Fields

JMS messages contain a standard set of header fields that are always transmitted with the message. They are available to message consumers that receive messages, and some fields can be set by the message producers that send messages. Once a message is received, its header field values can be modified.

For a description of the standard messages header fields, see Message Header Fields.

The following table lists the Message class set and get methods for each of the supported data types.

Note: In some cases, the `send()` method overrides the header field value set using the `set()` method, as indicated in the following table.

Header Field | Set Method | Get Method
--- | --- | ---
`JMSCorrelationID` | `public void setJMSCorrelationID( String correlationID ) throws JMSException` | `public String getJMSCorrelationID( ) throws JMSException` `public byte[] getJMSCorrelationIDAsBytes( ) throws JMSException`
`JMSDestination` 1 | `public void setJMSDestination( Destination destination ) throws JMSException` | `public Destination getJMSDestination( ) throws JMSException`
`JMSDeliveryMode`1 | `public void setJMSDeliveryMode( int deliveryMode ) throws JMSException` | `public int getJMSDeliveryMode( ) throws JMSException`
`JMSDeliveryTime`1 | `public void setJMSDeliveryTime( long deliveryTime ) throws JMSException` | `public long getJMSDeliveryTime( ) throws JMSException`
`JMSDeliveryMode`1 | `public void setJMSDeliveryMode( int deliveryMode ) throws JMSException` | `public int getJMSDeliveryMode( ) throws JMSException`
`JMSMessageID`1 | `public void setJMSMessageID( String id ) throws JMSException` Note: In addition to the set method, the `weblogic.jms.extensions.JMSHelper` class provides the following methods to convert between pre-WebLogic JMS 6.0 and 6.1 `JMSMessageID` formats: `public void oldJMSMessageIDToNew( String id, long timeStamp ) throws JMSException public void newJMSMessageIDToOld( String id, long timeStamp ) throws JMSException` | `public String getJMSMessageID( ) throws JMSException`
`JMSPriority`1 | `public void setJMSPriority( int priority ) throws JMSException` | `public int getJMSPriority( ) throws JMSException`
`JMSRedelivered`1 | `public void setJMSRedelivered( boolean redelivered ) throws JMSException` | `public boolean getJMSRedelivered( ) throws JMSException`
`JMSRedeliveryLimit`1 | `public void setJMSRedeliveryLimit( int redelivered ) throws JMSException` | `public int getJMSRedeliveryLimit( ) throws JMSException`
`JMSReplyTo` | `public void setJMSReplyTo( Destination replyTo ) throws JMSException` | `public Destination getJMSReplyTo( ) throws JMSException`
`JMSTimeStamp`1 | `public void setJMSTimeStamp( long timestamp ) throws JMSException` | `public long getJMSTimeStamp( ) throws JMSException`
`JMSType` | `public void setJMSType( String type ) throws JMSException` | `public String getJMSType( ) throws JMSException`

1. The corresponding `set()` method has no impact on the message header field when the `send()` method is executed. If set, this header field value will be overridden during the `send()` operation.

The `examples.jms.sender.SenderServlet` example, provided with WebLogic Server in the `WL_HOME``\samples\server\examples\src\examples\jms\sender` directory, where `WL_HOME` is the top-level directory of your WebLogic Platform installation, shows how to set header fields in messages that you send and how to display message header fields after they are sent.

For example, the following code, which appears after the `send()` method, displays the message ID that was assigned to the message by WebLogic JMS:

>     System.out.println("Sent message " +
>     	msg.getJMSMessageID() + " to " +
>     	msg.getJMSDestination());

## Setting Message Property Fields

To set a property field, call the appropriate set method and specify the property name and value. To read a property field, call the appropriate get method and specify the property name.

The sending application can set properties in the message, and the receiving application can subsequently view them. The receiving application cannot change the properties without first clearing them using the following `clearProperties()` method:

>     public void clearProperties(
>     ) throws JMSException

This method does not clear the message header fields or body.

Note: The `JMSX` property name prefix is reserved for JMS. The connection metadata contains a list of JMSX properties, which can be accessed as an enumerated list using the `getJMSXPropertyNames(`) method. For more information, see Accessing Connection Metadata.

The `JMS_` property name prefix is reserved for provider-specific properties; it is not intended for use with standard JMS messaging.

The property field can be set to any of the following types: boolean, byte, double, float, int, long, short, or string. The following table lists the Message class set and get methods for each of the supported data types.

Table 4-3 Message Property Set and Get Methods for Data Types

Data Type | Set Method | Get Method
--- | --- | ---
boolean | `public void setBooleanProperty( String name, boolean value ) throws JMSException` | `public boolean getBooleanProperty( String name ) throws JMSException`
byte | `public void setByteProperty( String name, byte value ) throws JMSException` | `public byte getByteProperty( String name ) throws JMSException`
double | `public void setDoubleProperty( String name, double value ) throws JMSException` | `public double getDoubleProperty( String name ) throws JMSException`
float | `public void setFloatProperty( String name, float value ) throws JMSException` | `public float getFloatProperty( String name ) throws JMSException`
int | `public void setIntProperty( String name, int value ) throws JMSException` | `public int getIntProperty( String name ) throws JMSException`
long | `public void setLongProperty( String name, long value) throws JMSException` | `public long getLongProperty( String name ) throws JMSException`
short | `public void setShortProperty( String name, short value ) throws JMSException` | `public short getShortProperty( String name ) throws JMSException`
String | `public void setStringProperty( String name, String value ) throws JMSException` | `public String getStringProperty( String name ) throws JMSException`

In addition to the set and get methods described in the previous table, you can use the `setObjectProperty()` and `getObjectProperty()` methods to use the objectified primitive values of the property type. When the objectified value is used, the property type can be determined at execution time rather than during the compilation. The valid object types are boolean, byte, double, float, int, long, short, and string.

You can access all property field names using the following Message method:

>     public Enumeration getPropertyNames(
>     ) throws JMSException

This method returns all property field names as an enumeration. You can then retrieve the value of each property field by passing the property field name to the appropriate get method, as described in the previous table, based on the property field data type.

The following table is a conversion chart for message properties. It allows you to identify the type that can be read based on the type that has been written.

Table 4-4 Message Property Conversion Chart

Property Written As. . . | Can Be Read As. . .
--- | ---
boolean | byte | double | float | int | long | short | String
boolean | X |  |  |  |  |  |  | X
byte |  | X |  |  | X | X | X | X
double |  |  | X |  |  |  |  | X
float |  |  | X | X |  |  |  | X
int |  |  |  |  | X | X |  | X
long |  |  |  |  |  | X |  | X
Object | X | X | X | X | X | X | X | X
short |  |  |  |  | X | X | X | X
String | X | X | X | X | X | X | X | X

You can test whether or not a property value has been set using the following `Message` method:

>     public boolean propertyExists(
>       String name
>     ) throws JMSException

You specify a property name and the method returns a boolean value indicating whether or not the property exists.

For example, the following code sets two String properties and an int property:

>     msg.setStringProperty("User", user);
>     msg.setStringProperty("Category", category);
>     msg.setIntProperty("Rating", rating);

For more information about message property fields, see Message Property Fields or the javax.jms.Message Javadoc.

## Browsing Header and Property Fields

Note: Only queue message header and property fields can be browsed. You cannot browse topic message header and property fields.

You can browse the header and property fields of messages on a queue using the following `QueueSession` methods:

>     public QueueBrowser createBrowser(
>       Queue queue
>     ) throws JMSException

>     public QueueBrowser createBrowser(
>       Queue queue,
>       String messageSelector
>     ) throws JMSException

You must specify the queue that you wish to browse. You may also specify a message selector to filter messages that you are browsing. Message selectors are described in more detail in Filtering Messages.

Once you have defined a queue, you can access the queue name and message selector associated with a queue browser using the following `QueueBrowser` methods:

>     public Queue getQueue(
>     ) throws JMSException

>     public String getMessageSelector(
>     ) throws JMSException

In addition, you can access an enumeration for browsing the messages using the following `QueueBrowser` method:

>     public Enumeration getEnumeration(
>     ) throws JMSException

The `examples.jms.queue.QueueBrowser` 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, shows how to access the header fields of received messages.

For example, the following code line is an excerpt from the `QueueBrowser` example and creates the `QueueBrowser` object:

>     qbrowser = qsession.createBrowser(queue);

The following provides an excerpt from the `displayQueue()` method defined in the `QueueBrowser` example. In this example, the `QueueBrowser` object is used to obtain an enumeration that is subsequently used to scan the queue's messages.

>        public void displayQueue(
>        ) throws JMSException
>       {
>         Enumeration e = qbrowser.getEnumeration();
>         Message m = null;

>         if (! e.hasMoreElements()) {
>           System.out.println("There are no messages on this queue.");
>         } else {

>           System.out.println("Queued JMS Messages: ");
>           while (e.hasMoreElements()) {
>             m = (Message) e.nextElement();
>             System.out.println("Message ID " + m.getJMSMessageID() +
>                               " delivered " + new Date(m.getJMSTimestamp())
>                               " to " + m.getJMSDestination());
>           }
>         }

When a queue browser is no longer being used, you should close it to free up resources. For more information, see Releasing Object Resources.

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

# Filtering Messages

In many cases, an application does not need to be notified of every message that is delivered to it. Message selectors can be used to filter unwanted messages, and subsequently improve performance by minimizing their impact on network traffic.

Message selectors operate as follows:

- The sending application sets message header or property fields to describe or classify a message in a standardized way.
- The receiving applications specify a simple query string to filter the messages that they want to receive.

Because message selectors cannot reference the contents (body) of a message, some information may be duplicated in the message property fields (except in the case of XML messages).

You specify a selector when creating a queue receiver or topic subscriber, as an argument to the `QueueSession.createReceiver()` or `TopicSession.createSubscriber()` methods, respectively. For information about creating queue receivers and topic subscribers, see Step 5: Create Message Producers and Message Consumers Using the Session and Destinations.

The following sections describe how to define a message selector using SQL statements and XML selector methods, and how to update message selectors. For more information about setting header and property fields, see Setting and Browsing Message Header and Property Fields and Setting Message Property Fields, respectively.

## Defining Message Selectors Using SQL Statements

A message selector is a boolean expression. It consists of a String with a syntax similar to the `where` clause of an `SQL` `select` statement.

The following excerpts provide examples of selector expressions.

>     salary > 64000 and dept in ('eng','qa')

>     (product like 'WebLogic%' or product like '%T3')
>     	and version > 3.0

>     hireyear between 1990 and 1992
>     	or fireyear is not null

>     fireyear - hireyear > 4

The following example shows how to set a selector when creating a queue receiver that filters out messages with a priority lower than 6.

>     String selector = "JMSPriority >= 6";
>     qsession.createReceiver(queue, selector);

The following example shows how to set the same selector when creating a topic subscriber.

>     String selector = "JMSPriority >= 6";
>     qsession.createSubscriber(topic, selector);

For more information about the message selector syntax, see the javax.jms.Message Javadoc.

## Defining XML Message Selectors Using XML Selector Method

For XML message types, in addition to using the SQL selector expressions described in the previous section to define message selectors, you can use the following method:

>     String JMS_BEA_SELECT(String type, String expression)

JMS_BEA_SELECT is a built-in function in WebLogic JMS SQL syntax. You specify the syntax type, which must be set to `xpath` (XML Path Language) and an XPath expression. The XML path language is defined in the XML Path Language (XPath) document, which is available at the XML Path Language Web site at: http://www.w3.org/TR/xpath

Note: Pay careful attention to your XML message syntax, since malformed XML messages (for example, a missing end tag) will not match any XML selector.

The method returns a null value under the following circumstances:

- The message does not parse.
- The message parses, but the element is not present.
- If a message parses and the element is present, but the message contains no value (for example, `<order></order>`).

For example, consider the following XML excerpt:

>     <order>
>     	<item>
>     		<id>007</id>
>     		<name>Hand-held Power Drill</name>
>     		<description>Compact, assorted colors.</description>
>     		<price>$34.99</price>
>     	</item>
>     	<item>
>     		<id>123</id>
>     		<name>Mitre Saw</name>
>     		<description>Three blades sizes.</description>
>     		<price>$69.99</price>
>     	</item>
>     	<item>
>     		<id>66</id>
>     		<name>Socket Wrench Set</name>
>     		<description>Set of 10.</description>
>     		<price>$19.99</price>
>     	</item>
>     </order>

The following example shows how to retrieve the name of the second item in the previous example. This method call returns the string, `Mitre Saw`.

>     String sel = "JMS_BEA_SELECT(`xpath', `/order/item[2]/name/text()') = `Mitre Saw'";

Pay careful attention to the use of double and single quotes and spaces. Note the use of single quotes around `xpath`, the XML tab, and the string value.

The following example shows how to retrieve the ID of the third item in the previous example. This method call returns the string, `66`.

>     String sel = "JMS_BEA_SELECT(`xpath', `/order/item[3]/id/text()') = `66'";

## Displaying Message Selectors

You can use the following `MessageConsumer` method to display a message selector:

>     public String getMessageSelector(
>     ) throws JMSException

This method returns either the currently defined message selector or null if a message selector is not defined.

## Indexing Topic Subscriber Message Selectors To Optimize Performance

For a certain class of applications, WebLogic JMS can significantly optimize topic subscriber message selectors by indexing them. These applications typically have a large number of subscribers, each with a unique identifier (like a user name), and they need to be able to quickly send a message to a single subscriber, or to a list of subscribers. A typical example is an instant messaging application where each subscriber corresponds to a different user, and each message contains a list of one or more target users.

To activate optimized subscriber message selectors, subscribers must use the following syntax for their selectors:

`` "`identifier` `IS NOT NULL`"

where `identifier` is an arbitrary string that is not a predefined JMS message property (e.g., neither `JMSCorrelationID` nor `JMSType`). Multiple subscribers can share the same identifier.

WebLogic JMS uses this exact message selector syntax as a hint to build internal subscriber indexes. Message selectors that do not follow the syntax, or that include additional `OR` and `AND` clauses, are still honored, but do not activate the optimization.

Once subscribers have registered using this message selector syntax, a message published to the topic can target specific subscribers by including one or more identifiers in the message's user properties, as illustrated in the following example:

>     // Set up a named subscriber, where "wilma" is the name of
>     // the subscriber and subscriberSession is a JMS TopicSession.
>     // Note that the selector syntax used activates the optimization.

>     TopicSubscriber topicSubscriber =
>         subscriberSession.createSubscriber(
>            (Topic)context.lookup("IMTopic"),
>            "Wilma IS NOT NULL",
>            /* noLocal= */ true);

>     // Send a message to subscribers "Fred" and "Wilma",
>     // where publisherSession is a JMS TopicSession. Subscribers
>     // with message selector expressions "Wilma IS NOT NULL"
>     // or "Fred IS NOT NULL" will receive this message.

>     TopicPublisher topicPublisher =
>       publisherSession.createPublisher(
>         (Topic)context.lookup("IMTopic");

>     TextMessage msg =
>       publisherSession.createTextMessage("Hi there!");
>     msg.setBooleanProperty("Fred", true);
>     msg.setBooleanProperty("Wilma", true);

>     topicPublisher.publish(msg);

Notes:

The optimized message selector and message syntax is based on the standard JMS API; therefore, applications that use this syntax will also work on versions of WebLogic JMS that do not have optimized message selectors, as well as on non-WebLogic JMS products. However, these versions will not perform as well as versions that include this enhancement.

The message selector optimization will have no effect on applications that use the `MULTICAST_NO_ACKNOWLEDGE` acknowledge mode. These applications have no need no need for the enhancement anyway, since the message selection occurs on the client side rather than the server side.

# Defining Server Session Pools

Note: Session pools are now used rarely, as they are not a required part of the J2EE specification, do not support JTA user transactions, and are largely superseded by message-driven beans (MDBs), which are simpler, easier to manage, and more capable. For more information on designing MDBs, see "Designing and Developing Message-Driven Beans" in Programming WebLogic Enterprise JavaBeans.

WebLogic JMS implements an optional JMS facility for defining a server-managed pool of server sessions. This facility enables an application to process messages concurrently.

The server session pool:

- Receives messages from a destination and passes them to a server-side message listener that you provide to process messages. The message listener class provides an `onMessage()` method that processes a message.
- Processes messages in parallel by managing a pool of JMS sessions, each of which executes a single-threaded `onMessage()` method.

The following figure illustrates the server session pool facility, and the relationship between the application and the application server components.

Figure 4-3 Server Session Pool Facility

As illustrated in the figure, the application provides a single-threaded message listener. The connection consumer, implemented by JMS on the application server, performs the following tasks to process one or more messages:

1. Gets a server session from the server session pool.
2. Gets the server session's session.
3. Loads the session with one or more messages.
4. Starts the server session to consume messages.
5. Releases the server session back to pool when finished processing messages.

The following figure illustrates the steps required to prepare for concurrent message processing.

Figure 4-4 Preparing for Concurrent Message Processing

Applications can use other application server providers' session pool implementations within this flow. Server session pools can also be implemented using message-driven beans. For information on using message driven beans to implement server session pools, see "Designing Message-Driven Beans" in Programming WebLogic Enterprise JavaBeans.

If the session pool and connection consumer were defined during configuration, you can skip this section. For more information on configuring server session pools and connection consumers, see Configuring JMS in the Administration Console Online Help.

Currently, WebLogic JMS does not support the optional `TopicConnection.createDurableConnectionConsumer()` operation. For more information on this advanced JMS operation, refer to Sun Microsystems' JMS Specification.

## Step 1: Look Up Server Session Pool Factory in JNDI

You use a server session pool factory to create a server session pool.

WebLogic JMS defines one `ServerSessionPoolFactory` object, by default: `weblogic.jms.extensions.ServerSessionPoolFactory:<`name`>`, where <`name`> specifies the name of the JMS server to which the session pool is created.

Once it has been configured, you can look up a server session pool factory by first establishing a JNDI context (`context`) using the NamingManager.InitialContext() method. For any application other than a servlet application, you must pass an environment used to create the initial context. For more information, see the NamingManager.InitialContext() Javadoc.

Once the context is defined, to look up a server session pool factory in JNDI use the following code:

>     factory = (ServerSessionPoolFactory) context.lookup(<ssp_name>);

The `<ssp_name>` specifies a qualified or non-qualified server session pool factory name.

For more information about server session pool factories, see ServerSessionPoolFactory Object or the weblogic.jms.extensions.ServerSessionPoolFactory Javadoc.

## Step 2: Create a Server Session Pool Using the Server Session Pool Factory

You can create a server session pool for use by queue (PTP) or topic (Pub/Sub) connection consumers, using the `ServerSessionPoolFactory` methods described in the following sections.

For more information about server session pools, see ServerSessionPool Object or the javax.jms.ServerSessionPool Javadoc.

### Create a Server Session Pool for Queue Connection Consumers

The `ServerSessionPoolFactory` provides the following method for creating a server session pool for queue connection consumers:

>     public ServerSessionPool getServerSessionPool(
>       QueueConnection connection,
>       int maxSessions,
>       boolean transacted,
>       int ackMode,
>       String listenerClassName
>     ) throws JMSException

You must specify the queue connection associated with the server session pool, the maximum number of concurrent sessions that can be retrieved by the connection consumer (to be created in step 3), whether or not the sessions are transacted, the acknowledge mode (applicable for non-transacted sessions only), and the message listener class that is instantiated and used to receive and process messages concurrently.

For more information about the `ServerSessionPoolFactory` class methods, see the weblogic.jms.extensions.ServerSessionPoolFactory Javadoc. For more information about the `ConnectionConsumer` class, see the javax.jms.ConnectionConsumer Javadoc.

### Create a Server Session Pool for Topic Connection Consumers

The `ServerSessionPoolFactory` provides the following method for creating a server session pool for topic connection consumers:

>     public ServerSessionPool getServerSessionPool(
>       TopicConnection connection,
>       int maxSessions,
>       boolean transacted,
>       int ackMode,
>       String listenerClassName
>     ) throws JMSException

You must specify the topic connection associated with the server session pool, the maximum number of concurrent sessions that can be retrieved by the connection (to be created in step 3), whether or not the sessions are transacted, the acknowledge mode (applicable for non-transacted sessions only), and the message listener class that is instantiated and used to receive and process messages concurrently.

For more information about the `ServerSessionPoolFactory` class methods, see the weblogic.jms.extensions.ServerSessionPoolFactory Javadoc. For more information about the `ConnectionConsumer` class, see the javax.jms.ConnectionConsumer Javadoc.

## Step 3: Create a Connection Consumer

You can create a connection consumer for retrieving server sessions and processing messages concurrently using one of the following methods:

- Configuring the server session pool and connection consumer during the configuration, as described in the "Configuring JMS" in the Administration Console Online Help
- Including in your application the Connection methods described in the following sections

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

### Create a Connection Consumer for Queues

The `QueueConnection` provides the following method for creating connection consumers for queues:

>     public ConnectionConsumer createConnectionConsumer(
>       Queue queue,
>       String messageSelector,
>       ServerSessionPool sessionPool,
>       int maxMessages
>     ) throws JMSException

You must specify the name of the associated queue, the message selector for filtering messages, the associated server session pool for accessing server sessions, and the maximum number of messages that can be assigned to the server session simultaneously. For information about message selectors, see Filtering Messages.

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

### Create a Connection Consumer for Topics

The `TopicConnection` provides the following two methods for creating `ConnectionConsumers` for topics:

>     public ConnectionConsumer createConnectionConsumer(
>       Topic topic,
>       String messageSelector,
>       ServerSessionPool sessionPool,
>       int maxMessages
>     ) throws JMSException

>     public ConnectionConsumer createDurableConnectionConsumer(
>       Topic topic,
>       String messageSelector,
>       ServerSessionPool sessionPool,
>       int maxMessages
>     ) throws JMSException

For each method, you must specify the name of the associated topic, the message selector for filtering messages, the associated server session pool for accessing server sessions, and the maximum number of messages that can be assigned to the server session simultaneously. For information about message selectors, see Filtering Messages.

Each method creates a connection consumer; but, the second method also creates a durable connection consumer for use with durable subscribers. For more information about durable subscribers, see Setting Up Durable Subscriptions.

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

## Example: Setting Up a PTP Client Server Session Pool

The following example illustrates how to set up a server session pool for a JMS client. The `startup()` method is similar to the `init()` method in the `examples.jms.queue.QueueSend` example, as described in Example: Setting Up a PTP Application. This method also sets up the server session pool.

The following illustrates the `startup()` method, with comments highlighting each setup step.

Include the following package on the import list to implement a server session pool application:

>     import weblogic.jms.extensions.ServerSessionPoolFactory

Define the session pool factory static variable required for the creation of the session pool.

>     private final static String SESSION_POOL_FACTORY=
>     	"weblogic.jms.extensions.ServerSessionPoolFactory:examplesJMSServer";

>     private QueueConnectionFactory qconFactory;
>     private QueueConnection qcon;
>     private QueueSession qsession;
>     private QueueSender qsender;
>     private Queue queue;
>     private ServerSessionPoolFactory sessionPoolFactory;
>     private ServerSessionPool sessionPool;
>     private ConnectionConsumer consumer;

Create the required JMS objects.

>     public String startup(
>       String name,
>       Hashtable args
>     ) throws Exception

>     {
>       String connectionFactory = (String)args.get("connectionFactory");
>       String queueName = (String)args.get("queue");
>       if (connectionFactory == null || queueName == null) {
>      	throw new   IllegalArgumentException("connectionFactory="+connectionFactory+
>                                              ", queueName="+queueName);
>         }
>       Context ctx = new InitialContext();
>       qconFactory = (QueueConnectionFactory)
>     	ctx.lookup(connectionFactory);
>       qcon =qconFactory.createQueueConnection();
>       qsession = qcon.createQueueSession(false,
>     	Session.AUTO_ACKNOWLEDGE);
>       queue = (Queue) ctx.lookup(queueName);
>       qcon.start();

### Step 1

Look up the server session pool factory in JNDI.

>       sessionPoolFactory = (ServerSessionPoolFactory)
>      		   ctx.lookup(SESSION_POOL_FACTORY);

### Step 2

Create a server session pool using the server session pool factory, as follows:

>       sessionPool = sessionPoolFactory.getServerSessionPool(qcon, 5,
>        	false, Session.AUTO_ACKNOWLEDGE,
>        	examples.jms.startup.MsgListener);

The code defines the following:

- `qcon` as the queue connection associated with the server session pool
- `5` as the maximum number of concurrent sessions that can be retrieved by the connection consumer (to be created in step 3)
- Sessions will be non-transacted (`false`)
- `AUTO_ACKNOWLEDGE` as the acknowledge mode
- The `examples.jms.startup.MsgListener` will be used as the message listener that is instantiated and used to receive and process messages concurrently.

### Step 3

Create a connection consumer, as follows:

>       consumer = qcon.createConnectionConsumer(queue, "TRUE",
>     	sessionPool, 10);

The code defines the following:

- `queue` as the associated queue
- `TRUE` as the message selector for filtering messages
- `sessionPool` as the associated server session pool for accessing server sessions
- `10` as the maximum number of messages that can be assigned to the server session simultaneously

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

## Example: Setting Up a Pub/Sub Client Server Session Pool

The following example illustrates how to set up a server session pool for a JMS client. The `startup()` method is similar to the `init()` method in the `examples.jms.topic.TopicSend` example, as described in Example: Setting Up a Pub/Sub Application. It also sets up the server session pool.

The following illustrates `startup()` method, with comments highlighting each setup step.

Include the following package on the import list to implement a server session pool application:

>     import weblogic.jms.extensions.ServerSessionPoolFactory

Define the session pool factory static variable required for the creation of the session pool.

>     private final static String SESSION_POOL_FACTORY=
>     	"weblogic.jms.extensions.ServerSessionPoolFactory:examplesJMSServer";

>     private TopicConnectionFactory tconFactory;
>     private TopicConnection tcon;
>     private TopicSession tsession;
>     private TopicSender tsender;
>     private Topic topic;
>     private ServerSessionPoolFactory sessionPoolFactory;
>     private ServerSessionPool sessionPool;
>     private ConnectionConsumer consumer;

Create the required JMS objects.

>     public String startup(
>       String name,
>       Hashtable args
>     ) throws Exception

>     {
>       String connectionFactory = (String)args.get("connectionFactory");
>       String topicName = (String)args.get("topic");
>       if (connectionFactory == null || topicName == null) {
>      	throw new   IllegalArgumentException("connectionFactory="+connectionFactory+
>                                              ", topicName="+topicName);
>         }
>       Context ctx = new InitialContext();
>       tconFactory = (TopicConnectionFactory)
>     	ctx.lookup(connectionFactory);
>       tcon = tconFactory.createTopicConnection();
>       tsession = tcon.createTopicSession(false,
>     	Session.AUTO_ACKNOWLEDGE);
>       topic = (Topic) ctx.lookup(topicName);
>       tcon.start();

### Step 1

Look up the server session pool factory in JNDI.

>       sessionPoolFactory = (ServerSessionPoolFactory)
>      		   ctx.lookup(SESSION_POOL_FACTORY);

### Step 2

Create a server session pool using the server session pool factory, as follows:

>       sessionPool = sessionPoolFactory.getServerSessionPool(tcon, 5,
>        	false, Session.AUTO_ACKNOWLEDGE,
>        	examples.jms.startup.MsgListener);

The code defines the following:

- `tcon` as the topic connection associated with the server session pool
- `5` as the maximum number of concurrent sessions that can be retrieved by the connection consumer (to be created in step 3)
- Sessions will be non-transacted (`false`)
- `AUTO_ACKNOWLEDGE` as the acknowledge mode
- The `examples.jms.startup.MsgListener` will be used as the message listener that is instantiated and used to receive and process messages concurrently.

### Step 3

Create a connection consumer, as follows:

>       consumer = tcon.createConnectionConsumer(topic, "TRUE",
>     	sessionPool, 10);

The code defines the following:

- `topic` as the associated topic
- `TRUE` as the message selector for filtering messages
- `sessionPool` as the associated server session pool for accessing server sessions
- `10` as the maximum number of messages that can be assigned to the server session simultaneously

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

# Using Multicasting

Multicasting enables the delivery of messages to a select group of hosts that subsequently forward the messages to subscribers.

The benefits of multicasting include:

- Near real-time delivery of messages to host group.
- High scalability due to the reduction in the amount of resources required by the JMS server to deliver messages to subscribers.

The limitations of multicasting include:

- Multicast messages are not guaranteed to be delivered to all members of the host group. For messages requiring reliable delivery and recovery, you should not use multicasting.
- For interoperability with different versions of WebLogic Server, clients cannot have an earlier release of WebLogic Server installed than the host. They must all have at least the same version or higher.

For an example of when multicasting might be useful, consider a stock ticker. When accessing stock quotes, timely delivery is more important than reliability. When accessing the stock information in real-time, if all or a portion of the contents is not delivered, the client can simply request the information to be resent. Clients would not want to have the information recovered, in this case, as by the time it is redelivered, it would be out-of-date.

The following figure illustrates the steps required to set up multicasting.

Figure 4-5 Setting Up Multicasting

Note: Multicasting is only supported for the Pub/Sub messaging model, and only for non-durable subscribers.

Monitoring statistics are not provided for multicast sessions or consumers.

Before setting up multicasting, the JMS connection factory and destination must be configured to support multicasting, as follows:

- For each connection factory, the system administrator configures the maximum number of outstanding messages that can exist on a multicast session and whether the most recent or oldest messages are discarded in the event the maximum is reached. If the message maximum is reached, a `DataOverrunException` is thrown, and messages are automatically discarded. These attributes are also dynamically configurable, as described in Dynamically Configuring Multicasting Configuration Attributes.
- For each destination, the Multicast Address (IP), Port, and TTL (Time-To-Live) attributes are specified. To better understand the TTL attribute setting, see Example: Multicast TTL.

Note: For JMS multicast sessions, a JMS server uses IP multicast to send messages to consumers, which, in turn, use IP multicast to receive messages from the JMS server. When sending multicast messages, a JMS server will open a UPD port of 0, which can then be shared by all JMS servers hosted by a server instance.

Therefore, it is strongly recommended that you seek the advice of your network administrator when configuring the multicast IP address, port, and time-to-live attributes to ensure that the appropriate values are set.

For more information on how WebLogic Server utilizes IP multicast, see "Communications In a Cluster" in Using WebLogic Server Clusters. For more information on the JMS multicasting configuration attributes, see "JMS Topic --> Configuration --> Multicast" in the Administration Console Online Help.

## Step 1: Set Up the JMS Application, Creating Multicast Session and Topic Subscriber

Set up the JMS application as described in Setting Up a JMS Application. However, when creating sessions, as described in Step 3: Create a Session Using the Connection, specify that the session would like to receive multicast messages by setting the `acknowledgeMode` value to `MULTICAST_NO_ACKNOWLEDGE`.

Note: Multicasting is only supported for the Pub/Sub messaging model for non-durable subscribers. An attempt to create a durable subscriber on a multicast session will cause a `JMSException` to be thrown.

For example, the following method illustrates how to create a multicast session for the Pub/Sub messaging model.

>     tsession = tcon.createTopicSession(
>       false,
>       WLSession.MULTICAST_NO_ACKNOWLEDGE
>     );

Note: On the client side, each multicasting session requires one dedicated thread to retrieve messages off the socket. Therefore, you should increase the JMS client-side thread pool size to adjust for this. For more information on adjusting the thread pool size, see the "Tuning Thread Pools and EJB Pools" section in the "WebLogic JMS Performance Guide" white paper, , which discusses tuning JMS client-side thread pools.

In addition, create a topic subscriber, as described in Create TopicPublishers and TopicSubscribers.

For example, the following code illustrates how to create a topic subscriber:

`tsubscriber = tsession.createSubscriber(myTopic);`

Note: The `createSubscriber()` method fails if the specified destination is not configured to support multicasting.

## Step 2: Set Up the Message Listener

Multicast topic subscribers can only receive messages asynchronously. If you attempt to receive synchronous messages on a multicast session, a `JMSException` is thrown.

Set up the message listener for the topic subscriber, as described in Receiving Messages Asynchronously.

For example, the following code illustrates how to establish a message listener:

>     tsubscriber.setMessageListener(this);

When receiving messages, WebLogic JMS tracks the order in which messages are sent by the destinations. If a multicast subscriber's message listener receives the messages out of sequence, resulting in one or more messages being skipped, a `SequenceGapException` will be delivered to the `ExceptionListener` for the session(s) present. If a skipped message is subsequently delivered, it will be discarded. For example, in the following figure, the subscriber is receiving messages from two destinations simultaneously.

Figure 4-6 Multicasting Sequence Gap

Upon receiving the "4" message from Destination 1, a `SequenceGapException` is thrown to notify the application that a message was received out of sequence. If subsequently received, the "3" message will be discarded.

Note: The larger the messages being exchanged, the greater the risk of encountering a SequenceGapException.

## Dynamically Configuring Multicasting Configuration Attributes

During configuration, for each connection factory the system administrator configures the following information to support multicasting:

- Messages maximum specifying the maximum number of outstanding messages that can exist on a multicast session.
- Overrun policy specifying whether recent or older messages are discarded in the event the messages maximum is reached.

If the messages maximum is reached, a `DataOverrunException` is thrown and messages are automatically discarded based on the overrun policy. Alternatively, you can set the messages maximum and overrun policy using the `Session` set methods.

The following table lists the `Session` set and get methods for each dynamically configurable attribute.

Table 4-5 Message Producer Set and Get Methods

Attribute | Set Method | Get Method
--- | --- | ---
Messages Maximum | `public void setMessagesMaximum( int messagesMaximum ) throws JMSException` | `public int getMessagesMaximum( ) throws JMSException`
Overrun Policy | `public void setOverrunPolicy ( int overrunPolicy ) throws JMSException` | `public int getOverrunPolicy( ) throws JMSException`

Note: The values set using the set methods take precedence over the configured values.

For more information about these `Session` class methods, see the weblogic.jms.extensions.WLSession Javadoc. For more information on these multicast configuration attributes, see "JMS Topic --> Configuration --> Multicast" in the Administration Console Online Help.

## Example: Multicast TTL

Note: The following example is a very simplified illustration of how the Multicast TTL (time-to-live) destination configuration attribute impacts the delivery of messages across routers. It is strongly advised that you seek the assistance of your network administrator when configuring the multicast TTL attribute to ensure that the appropriate value is set.

The Multicast TTL is independent of the message time-to-live.

The following example illustrates how the Multicast TTL destination configuration attribute impacts the delivery of messages across routers. For more information on the multicast configuration attributes, see JMS Topic --> Configuration --> Multicast" in the Administration Console Online Help.

Consider the following network diagram.

Figure 4-7 Multicast TTL Example

In the figure, the network consists of three subnets: Subnet A containing the multicast publisher, and Subnets B and C each containing one multicast subscriber.

If the Multicast TTL attribute is set to 0 (indicating that the messages cannot traverse any routers and are delivered on the current subnet only), when the multicast publisher on Subnet A publishes a message, the message will not be delivered to any of the multicast subscribers.

If the Multicast TTL attribute is set to 1 (indicating that messages can traverse one router), when the multicast publisher on Subnet A publishes a message, the multicast subscriber on Subnet B will receive the message.

Similarly, if the Multicast TTL attribute is set to 2 (indicating that messages can traverse two routers), when the multicast publisher on Subnet A publishes a message, the multicast subscribers on Subnets B and C will receive the message.

# Using Distributed Destinations

A distributed destination is a set of physical destinations (queues or topics) that are called under a single JNDI name so they appear to be a single, logical destination to a client, when the members of the set are actually distributed across multiple servers within a cluster, with each destination member belonging to a separate JMS server.

By enabling you to configure multiple physical queues and topics as members of a distributed destination, WebLogic JMS supports high availability and load balancing of physical destinations within a cluster. Once properly configured, your producers and consumers are able to send and receive messages through the distributed destination. WebLogic JMS then balances the messaging load across all available members of the distributed destination. When one member becomes unavailable due a server failure, traffic is then redirected toward other available destination members in the set.

To facilitate the configuration process, the Administration Console has an "Auto Deploy" feature that allows you to easily configure distributed destinations, as follows:

- Create a Distributed Destination and Automatically Create Members — for new implementations of WebLogic JMS with no physical destinations or existing configurations of WebLogic JMS that do not require previously configured destinations to be part of a distributed destination.
- Create a Distributed Destination and Manually Add Existing Physical Destinations as Members — for existing implementations of WebLogic JMS that require previously configured destinations to be members of a distributed destination.

For instructions on configuring distributed destinations using the Administration Console, see "Distributed Destination Tasks" in the Administration Console Online Help.

The following sections explain how to use distributed destinations with your JMS applications:

- Accessing Distributed Destinations
- Accessing Distributed Destination Members
- Load Balancing Messages Across a Distributed Destination
- Distributed Destination Migration

## Accessing Distributed Destinations

A distributed destination is actually a set of physical JMS destination members (queues or topics) that is accessed through a single JNDI name. As such, a distributed destination can be looked up using JNDI. It implements the javax.jms.Destination interface, and can be used to create producers, consumers, and browsers.

Because a distributed destination can be served by multiple WebLogic Servers within a cluster, when creating a reference to a distributed destination by using one of the `createQueue()` or `createTopic()` methods, the name supplied is simply the name of the `JMSDistributedQueueMBean` or `JMSDistributedTopicMBean` configuration MBean name. No JMS server name or separating forward slash (`/`) is required.

For example, the following code illustrates how to look up a distributed destination topic member:

`topic = myTopicSession.createTopic("myDistributedTopic");`

Note: When calling the `createQueue()` or `createTopic()` methods, any string containing a forward slash (`/`), is assumed to be the name of a distributed destination member—not a physical destination. If no such destination member exists, then the call will fail with an `InvalidDestinationException`.

### Looking Up Distributed Queues

A distributed queue is a set of physical JMS queue members. As such, a distributed queue can be used to create a `QueueSender`, `QueueReceiver`, and a `QueueBrowser`. The fact that a distributed queue represents multiple physical queues is mostly transparent to your application.

The queue members can be located anywhere, but must all be served by JMS servers in a single server cluster. When a message is sent to a distributed queue, it is sent to exactly one of the physical queues in the set of members for the distributed queue. Once the message arrives at the queue member, it is available for receipt by consumers of that queue member only.

Note: Queue members can forward messages to other queue members by configuring the Forward Delay attribute in the Administration Console, which is disabled by default. This attribute defines the amount of time, in seconds, that a distributed queue member with messages, but which has no consumers, will wait before forwarding its messages to other queue members that do have consumers.

#### QueueSenders

After creating a queue sender, if the queue supplied at creation time was a distributed queue, then each time a message is produced using the sender a decision is made as to which queue member will receive the message. Each message is sent to a single physical queue member.

The message is not replicated in any way. As such, the message is only available from the queue member where it was sent. If that physical queue becomes unavailable before a given message is received, then the message is unavailable until that queue member comes back online.

It is not enough to send a message to a distributed queue and expect the message to be received by a queue receiver of that distributed queue. Since the message is sent to only one physical queue member, there must be a queue receiver receiving or listening on that queue member.

Note: For information on the load-balancing heuristics for distributed queues with zero consumers, see Load Balancing Heuristics.

#### QueueReceivers

When creating a queue receiver, if the supplied queue is a distributed queue, then a single physical queue member is chosen for the receiver at creation time. The created `QueueReceiver` is pinned to that queue member until the queue receiver loses its access to the queue member. At that point, the consumer will receive a `JMSException`, as follows:

- If the queue receiver is synchronous, then the exception is returned to the user directly.
- If the queue receiver is asynchronous, then the exception is delivered inside of a `ConsumerClosedException` that is delivered to the `ExceptionListener` defined for the consumer session, if any.

Upon receiving such an exception, an application can close its queue receiver and recreate it. If any other queue members are available within the distributed queue, then the creation will succeed and the new queue receiver will be pinned to one of those queue members. If no other queue member is available, then the application won't be able to recreate the queue receiver and will have to try again later.

Note: For information on the load-balancing heuristics for distributed queues with zero consumers, see Load Balancing Heuristics.

#### QueueBrowsers

When creating a queue browser, if the supplied queue is a distributed queue, then a single physical queue member is chosen for the browser at creation time. The created queue browser is pinned to that queue member until the receiver loses its access to the queue member. At that point, any calls to the queue browser will receive a `JMSException`. Any calls to the enumeration will return a `NoSuchElementException`.

Note: The queue browser can only browse the queue member that it is pinned to. Even though a distributed queue was specified at creation time, the queue browser cannot see or browse messages for the other queue members in the distributed destination.

### Looking Up Distributed Topics

A distributed topic is a set of physical JMS topic members. As such, a distributed topic can be used to create a `TopicPublisher` and `TopicSubscriber`. The fact that a distributed topic represents multiple physical topics is mostly transparent to the application.

Note: Durable subscribers (`DurableTopicSubscriber`) cannot be created for distributed topics. However, you can still create a durable subscription on distributed topic member and the other topic members will forward the messages to the topic member that has the durable subscription.

The topic members can be located anywhere but must all be served either by a single WebLogic Server or any number of servers in a cluster. When a message is sent to a distributed topic, it is sent to all of the topic members in the distributed topic set. This allows all subscribers to the distributed topic to receive messages published for the distributed topic.

A message published directly to a topic member of a distributed destination (that is, the publisher did not specify the distributed destination) is also forwarded to all the members of that distributed topic. This includes subscribers that originally subscribed to the distributed topic, and which happened to be assigned to that particular topic member. In other words, publishing a message to a specific distributed topic member automatically forwards it to all the other distributed topic members, just as publishing a message to a distributed topic automatically forwards it to all of its distributed topic members. For more information about looking up specific distributed destination members, see Accessing Distributed Destination Members.

#### Deploying Message-Driven Beans on a Distributed Topic

When an MDB is deployed on a distributed topic and is targeted to a WebLogic Server instance in a cluster that is hosting two members of the distributed topic on a JMS server, the MDB gets deployed on both the members of the distributed topic. This occurs because MDBs are pinned to a distributed topic member's destination name.

Therefore, you will receive [number of messages sent] * [number of distributed topic members] more messages per MDB, depending on how may distributed topic members are deployed on a WebLogic Server instance. For example, if a JMS server contains two distributed topic members, then two MDBs are deployed, one for each member, so you will receive twice as many messages.

#### TopicPublishers

When creating a topic publisher, if the supplied destination is a distributed destination, then any messages sent to that distributed destination are sent to all available topic members for that distributed topic, as follows:

- If one or more of the distributed topic members is not reachable, and the message being sent is non-persistent, then the message is sent only to the available topic members.
- If one or more of the distributed topic members is not reachable, and the message being sent is persistent, then the message is stored and forwarded to the other topic members when they become reachable. However, the message can only be persistently stored if the topic member has a JMS store configured.

Note: Every effort is made to first forward the message to distributed members that utilize a persistent store. However, if none of the distributed members utilize a store, then the message is still sent to one of the members according to the selected load-balancing algorithm, as described in Load Balancing Messages Across a Distributed Destination.

- If all of the distributed topic members are unreachable (regardless of whether the message is persistent or non-persistent), then the publisher receives a `JMSException` when it tries to send a message.

#### TopicSubscribers

When creating a topic subscriber, if the supplied topic is a distributed topic, then the topic subscriber receives messages published to that distributed topic. If one or more of the topic members for the distributed topic are not reachable by a topic subscriber, then depending on whether the messages are persistent or non-persistent the following occurs:

- Any persistent messages published to one or more unreachable distributed topic members are eventually received by topic subscribers of those topic members once they become reachable. However, the messages can only be persistently stored if the topic member has a JMS store configured.
- Any non-persistent messages published to those unreachable distributed topic members will not be received by that topic subscriber.

Note: If a JMS store is configured for a JMS server that is hosting a distributed topic member, then all the Distributed Topic System Subscribers associated with that member destination are treated as durable subscriptions, even when a topic member does not have a JMS store explicitly configured. As such, the saving of all the messages sent to these distributed topic subscribers in memory can result in unexpected memory and disk consumption. Therefore, a recommended best design practice when deploying distributed destination is to consistently configure all member destinations: either with a JMS store for durable messages, or without a JMS store for non-durable messages. For example, if you want all of your distributed topic subscribers to be non-durable, but some member destinations implicitly have a JMS store configured because their associated JMS server uses a JMS store, then you need to explicitly set the StoreEnabled attribute to False for each member destination to override the JMS server setting.

Ultimately, a topic subscriber is pinned to a physical topic member. If that topic member becomes unavailable, then the topic subscriber will receive a `JMSException`, as follows:

- If the topic subscriber is synchronous, then the exception is returned to the user directly.
- If the topic subscriber is asynchronous, then the exception is delivered inside of a `ConsumerClosedException` that is delivered to the `ExceptionListener` defined for the consumer session, if any.

Upon receiving such an exception, an application can close its topic subscriber and recreate it. If any other topic member is available within the distributed topic, then the creation should be successful and the new topic subscriber will be pinned to one of those topic members. If no other topic member is available, then the application will not be able to recreate the topic subscriber and will have to try again later.

## Accessing Distributed Destination Members

In order to access a destination member within a distributed destination, you must look up the destination member using the configured JNDI name, or supply the JMS server name and the `JMSQueueMBean` or `JMSTopicMBean` configuration MBean name, separated by a forward slash (`/`), to one of the `createQueue()` or `createTopic()` methods.

For example, the following code illustrates how to look up a particular member of a distributed queue (`myQueue`), on a JMS server (`myServer`):

`queue = myQueueSession.createQueue("myServer/myQueue");`

Note: When calling the `createQueue()` or `createTopic()` methods, any string containing a forward slash (`/`), is assumed to be the name of a distributed destination member—not a destination. If no such destination member exists, then the call will fail with an `InvalidDestinationException`.

## Load Balancing Messages Across a Distributed Destination

By using distributed destinations, WebLogic JMS can spread or balance the messaging load across multiple physical destinations, which can result in better use of resources and improved response times. The WebLogic JMS load-balancing algorithm determines the physical destinations that messages are sent to, as well as the physical destinations that consumers are assigned to.

For more information about configuring load balancing for a distributed destination, see "Configuring Message Load Balancing" in the Administration Console Online Help.

### Load Balancing Options

WebLogic JMS supports two different algorithms for balancing the message load across multiple physical destinations within a given distributed destination set. You select one of these load balancing options when configuring a distributed topic or queue on the Administration Console.

- Round-Robin Distribution
- Random Distribution

#### Round-Robin Distribution

In the round-robin algorithm, WebLogic JMS maintains an ordering of physical destinations within the distributed destination. The messaging load is distributed across the physical destinations one at a time in the order that they are defined in the WebLogic Server configuration (`config.xml`) file. Each WebLogic Server maintains an identical ordering, but may be at a different point within the ordering. Multiple threads of execution within a single server using a given distributed destination affect each other with respect to which physical destination a member is assigned to each time they produce a message. Round-robin is the default algorithm and doesn't need to be configured.

If weights are assigned to any of the physical destinations in the set for a given distributed destination, then those physical destinations appear multiple times in the ordering. For instance, if the weights of destinations A, B and C are 2, 5, and 3 respectively, then the ordering will be A, B, C, A, B, C, B, C, B, B. That is, a number of passes are made through the basic ordering (A, B, C). The number of passes is equal to the highest weight of the destinations within the set. On each pass, only those destinations with a weight that is greater than or equal to the ordinal value of the pass are included in the ordering. Following this logic, this example would produce the following results:

- A is dropped from the ordering after two passes.
- C is dropped after three passes.
- B is the only one remaining on the fourth and fifth passes.

#### Random Distribution

The random distribution algorithm uses the weight assigned to the physical destinations to compute a weighted distribution for the set of physical destinations. The messaging load is distributed across the physical destinations by pseudo-randomly accessing the distribution. In the short run, the load will not be directly proportional to the weight. In the long run, the distribution will approach the limit of the distribution. A pure random distribution can be achieved by setting all the weights to the same value, which is typically 1.

Adding or removing a member (either administratively or as a result of a WebLogic Server shutdown/restart event) requires a recomputation of the distribution. Such events should be infrequent however, and the computation is generally simple, running in O(n) time.

### Consumer Load Balancing

When an application creates a consumer, it must provide a destination. If that destination represents a distributed destination, then WebLogic JMS must find a physical destination that consumer will receive messages from. The choice of which destination member to use is made by using one of the load-balancing algorithms described in Load Balancing Options. The choice is made only once: when the consumer is created. From that point on, the consumer gets messages from that member only.

### Producer Load Balancing

When a producer sends a message, WebLogic JMS looks at the destination where the message is being sent. If the destination is a distributed destination, WebLogic JMS makes a decision as to where the message will be sent. That is, the producer will send to one of the destination members according to one of the load-balancing algorithms described in Load Balancing Options.

The producer makes such a decision each time it sends a message. However, there is no compromise of ordering guarantees between a consumer and producer, because consumers are load balanced once, and are then pinned to a single destination member.

Note: If a producer attempts to send a persistent message to a distributed destination, every effort is made to first forward the message to distributed members that utilize a persistent store. However, if none of the distributed members utilize a persistent store, then the message will still be sent to one of the members according to the selected load-balancing algorithm. bucolic

### Load Balancing Heuristics

In addition to the algorithms described in Load Balancing Options, WebLogic JMS uses the following heuristics when choosing an instance of a destination.

- Transaction Affinity
- Server Affinity
- Queues with Zero Consumers

#### Transaction Affinity

When producing multiple messages within a transacted session, an effort is made to send all messages produced to the same WebLogic Server. Specifically, if a session sends multiple messages to a single distributed destination, then all of the messages are routed to the same physical destination. If a session sends multiple messages to multiple different distributed destinations, an effort is made to choose a set of physical destinations served by the same WebLogic Server.

#### Server Affinity

When the Server Affinity option is enabled for distributed destinations, then before a WebLogic Server instance attempts to load balance consumers or producers across all the members of a distributed destination in a domain, it will first attempt to load balance across any local members that are running on the same WebLogic Server instance.

For more information about configuring server affinity for a distributed destination using the Server Affinity Enabled option on the JMS connection factory, see "Configuring Server Affinity" in the Administration Console Online Help.

Note: The Server Affinity Enabled attribute does not affect queue browsers. Therefore, a queue browser created on a distributed queue can be pinned to a remote distributed queue member even when Server Affinity is enabled.

#### Queues with Zero Consumers

When load balancing consumers across multiple remote physical queues, if one or more of the queues have zero consumers, then those queues alone are considered for balancing the load. Once all the physical queues in the set have at least one consumer, the standard algorithms apply.

In addition, when producers are sending messages, queues with zero consumers are not considered for message production, unless all instances of the given queue have zero consumers.

### Defeating Load Balancing

Applications can defeat load balancing by directly accessing the individual physical destinations. That is, if the physical destination has no JNDI name, it can still be referenced using the `createQueue()` or `createTopic()` methods.

- JNDI Lookup
- CreateQueue() and CreateTopic()
- Connection Factories

#### JNDI Lookup

If a physical destination has a JNDI name, then it can be looked up using JNDI. The returned destination can then be used to create a consumer or receiver.

#### CreateQueue() and CreateTopic()

An application can also obtain a reference to a topic or queue using the `createQueue()` and `createTopic()` methods. When using these methods, the application must supply a vendor-specific string identifying the destination that they want a reference to. The vendor-specific string for WebLogic JMS is of the form server/destination, where "server" is the name of a JMS server and "destination" is the name of a queue or topic on that JMS server.

#### Connection Factories

Applications that use distributed destinations to distribute or balance their producers and consumers across multiple physical destinations, but do not want to make a load balancing decision each time a message is produced, can use a connection factory with the Load Balancing Enabled attribute disabled (i.e., set to False).

For more information about configuring load balancing for a distributed destination, see "Enabling Message Load Balancing" in the Administration Console Online Help.

### How Distributed Destination Load Balancing Is Affected When Using the "Server Affinity Enabled" Attribute

The following table explains how the setting of the JMS connection factory's Server Affinity Enabled attribute affects the load balancing preferences for distributed destination members. The order of preference depends on the type of operation and whether or not durable subscriptions or persistent messages are involved.

The Server Affinity Enabled attribute for distributed destinations is different from the server affinity provided by the Default Load Algorithm attribute in the `ClusterMBean`, which is also used by the JMS connection factory to create initial context affinity for client connections. For more information, refer to the "Load Balancing for EJBs and RMI Objects" and "Initial Context Affinity and Server Affinity for Client Connections" sections in Using WebLogic Server Clusters.

Table 4-6 Server Affinity Load Balancing Preferences

When the operation is... | And Server Affinity Enabled is... | Then load balancing preference is given to a...
--- | --- | ---
`createReceiver()` for queues `createSubscriber()` for topics | True | 1. local member without a consumer 2. local member 3. remote member without a consumer 4. remote member
`createReceiver()` for queues | False | 1. member without a consumer 2. member
`createSubscriber()` for topics (Note: non-durable subscribers) | True or False | 1. local member without a consumer 2. local member 3. local proxy topic (see "Monitoring Distributed Destination System Subscriptions and Proxy Topic Members" in the Administration Console Online Help)
`createSender()` for queues `createPublisher()` for topics | True or False | There is no separate machinery for load balancing a JMS producer creation. JMS producers are created on the server on which your JMS connection is load balanced or pinned. For more information about load balancing JMS connections created via a connection factory, refer to the "Load Balancing for EJBs and RMI Objects" and "Initial Context Affinity and Server Affinity for Client Connections" sections in Using WebLogic Server Clusters.
For persistent messages using `QueueSender.send()` | True | 1. local member with a consumer and a store 2. remote member with a consumer and a store 3. local member with a store 4. remote member with a store 5. local member with a consumer 6. remote member with a consumer 7. local member 8. remote member
For persistent messages using `QueueSender.send()` | False | 1. member with a consumer and a store 2. member with a store 3. member with a consumer 4. member
For non-persistent messages using `QueueSender.send()` | True | 1. local member with a consumer 2. remote member with a consumer 3. local member 4. remote member
For non-persistent messages: `QueueSender.send()` `TopicPublish.publish()` | False | 1. member with a consumer 2. member
`createConnectionConsumer()` for session pool queues and topics | True or False | 1. local member only Note: Session pools are now used rarely, as they are not a required part of the J2EE specification, do not support JTA user transactions, and are largely superseded by message-driven beans (MDBs), which are simpler, easier to manage, and more capable.

## Distributed Destination Migration

For clustered JMS implementations that take advantage of the Service Migration feature, a JMS server and its distributed destination members can be manually migrated to another WebLogic Server instance within the cluster. Service migrations can take place due to scheduled system maintenance, as well as in response to a server failure within the cluster.

However, the target WebLogic Server may already be hosting a JMS server with all of its physical destinations. This can lead to situations where the same WebLogic Server instance hosts two physical destinations for a single distributed destination. This is permissible in the short term, since a WebLogic Server instance can host multiple physical destinations for that distributed destination. However, load balancing in this situation is less effective.

In such a situation, each JMS server on a target WebLogic Server instance operates independently. This is necessary to avoid merging of the two destination instances, and/or disabling of one instance, which can make some messages unavailable for a prolonged period of time. The long-term intent, however, is to eventually re-migrate the migrated JMS server to yet another WebLogic Server instance in the cluster.

For more information about the configuring JMS migratable targets, see Configuring Migratable Targets for JMS Servers.

### Distributed Destination Failover

If the server instance that is hosting the JMS connections for the JMS producers and JMS consumers should fail, then all the producers and consumers using these connections are closed and are not re-created on another server instance in the cluster. Furthermore, if a server instance that is hosting a JMS destination should fail, then all the JMS consumers for that destination are closed and not re-created on another server instance in the cluster.

If the distributed queue member on which a queue producer is created should fail, yet the WebLogic Server instance where the producer's JMS connection resides is still running, the producer remains alive and WebLogic JMS will fail it over to another distributed queue member, irrespective of whether the Load Balancing option is enabled.

For more information about procedures for recovering from a WebLogic Server failure, see Recovering from a WebLogic Server Failure.