bea.com | products | dev2dev | support | askBEA
 Download Docs   Site Map   Glossary 
Search

Programming WebLogic JMS

 Previous Next Contents Index View as PDF  

Developing a WebLogic JMS Application

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

Note: For more information about the JMS classes described in this section, access the JMS Javadoc supplied on the Sun Microsystems' Java web site at the following location: http://java.sun.com/products/jms/docs.html

 


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:

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.

java.util

Utility API, such as date and time facilities.

java.io

System input and output API.

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

WebLogic JMS public API for use with server session pools, an optional application server facility described in the JMS specification.

weblogic.jms.extensions

WebLogic-specific JMS public API that provides additional classes and methods, as described in WebLogic JMS Extensions.

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

import javax.jms.*;
import java.util.*;
import java.io.*;
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.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\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 "Managing JMS" in the Administration Guide.

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.ServerSessionPoolFactory, 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 one default connection factory, that is included as part of the configuration by default. The WebLogic JMS system administrator may add or update connection factories during configuration. For information on configuring connection factories and the defaults that are available, see "Managing JMS" in the Administration Guide.

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 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 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 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-5. 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 "Managing JMS" in the Administration Guide.

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 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, 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:

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

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

Note: This step applies to message consumers only.

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

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

    Note: For an example of the onMessage() method interface, see Example: Setting Up a PTP Application.

    If you wish to issue the close() method within an onMessage() method call, the system administrator must select the Allow Close In OnMessage check box when configuring the connection factory. For more information on configuring JMS, see "Managing JMS" in the Administration Guide.

  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 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\src\examples\jms\queue directory, where WL_HOME is the top-level directory of your WebLogic Platform installation. The init() method shows how to set up and start a QueueSession for a JMS application. The following shows the init() method, with comments describing each setup step.

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

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

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

Set up the JNDI initial context, as follows:

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

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

Context ctx = new InitialContext();

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

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

Step 1

Look up a connection factory in JNDI.

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

Step 2

Create a connection using the connection factory.

  qcon = qconFactory.createQueueConnection(); 

Step 3

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

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

Step 4

Look up a destination (queue) in JNDI.

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

Step 5

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

  qsender = qsession.createSender(queue);

Step 6

Create the message object.

  msg = qsession.createTextMessage();

Step 7

Start the connection.

  qcon.start();
}

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

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

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

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

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

public void onMessage(Message msg)
{
try {
String msgText;
if (msg instanceof TextMessage) {
msgText = ((TextMessage)msg).getText();
} else { // If it is not a TextMessage...
msgText = msg.toString();
}
	System.out.println("Message Received: "+ msgText );
	if (msgText.equalsIgnoreCase("quit")) {
synchronized(this) {
	   	quit = true;
this.notifyAll(); // Notify main thread to quit
}
}
} catch (JMSException jmse) {
jmse.printStackTrace();
}
}

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

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

For more information about the JMS classes used in this example, see 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\src\examples\jms\topic directory, where WL_HOME is the top-level directory of your WebLogic Platform installation. The init() method shows how to set up and start a topic session for a JMS application. The following shows the init() method, with comments describing each setup step.

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

public final static String JNDI_FACTORY=
"weblogic.jndi.WLInitialContextFactory";
public final static String JMS_FACTORY=
"weblogic.examples.jms.TopicConnectionFactory";
public final static String
TOPIC="weblogic.examples.jms.exampleTopic";
protected TopicConnectionFactory tconFactory;
protected TopicConnection tcon;
protected TopicSession tsession;
protected TopicPublisher tpublisher;
protected Topic topic;
protected TextMessage msg;

Set up the JNDI initial context, as follows:

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

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

Context ctx = new InitialContext();

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

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

Step 1

Look up a connection factory using JNDI.

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

Step 2

Create a connection using the connection factory.

    tcon = tconFactory.createTopicConnection();

Step 3

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

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

Step 4

Look up the destination (topic) using JNDI.

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

Step 5

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

    tpublisher = tsession.createPublisher(topic);

Step 6

Create the message object.

    msg = tsession.createTextMessage();

Step 7

Start the connection.

    tcon.start();
}

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

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

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

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

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

For more information about the JMS classes used in this example, see 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 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:

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

If you define the delivery mode as PERSISTENT, you should configure a backing store for the destination, as described in "Managing JMS"in the Administration Guide.

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:

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

If you define the delivery mode as PERSISTENT, you should configure a backing store, as described in "Managing JMS"in the Administration Guide.

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 "Managing JMS"in the Administration Guide.

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 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

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\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\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:

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).

You can control the maximum number of messages that may exist for an asynchronous session and that have not yet been passed to the message listener by setting the Messages Maximum attribute when configuring the JMS 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 "Managing JMS" in the Administration Guide.

Behavior of Pipelined Messages

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

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\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\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-5. 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:

Messages in queues are not necessarily redelivered in the same order that they were originally delivered, nor to the same queue consumers.

 


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-5.

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:

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:

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\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, or Expired Messages

The following sections describe how to manage rolled back or recovered 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 Factories" 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.

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 Destinations" in the Administration Console Online Help.

Setting a Redelivery Limit for Messages

You can specify a limit on the number of times that WebLogic JMS will attempt to redeliver a message to an application. Once WebLogic JMS fails to redeliver a message to a destination for a specific number of times, the message can be redirected to an error destination that is associated to the message destination. If the 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.

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

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 Destinations" in the Administration Console Online Help.

Configuring an Error Destination for Undelivered Messages

If an error destination is configured for undelivered messages, then when a message has been deemed undeliverable, the message will be redirected to a specified error destination. The error destination can be either a queue or a topic, and 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.

The ErrorDestination attribute is configured using the Administration Console. For more information, see "JMS Destinations" in the Administration Console Online Help.

If a message redelivery attempt has already reached its specified redelivery limit, but its error destination has also reached its maximum quota, then the message is deemed undeliverable and is dropped. Non-persistent messages are deleted, while persistent messages remain in the store and will reappear in their originating destination (not the error destination) when the server is restarted. In either case, a log message is generated. To prevent the log file from becoming clogged, the log message is only generated once per error destination every five minutes, until the error condition is resolved.

Passive Message Expiration Policy

WebLogic JMS has only a passive message expiration policy, in that it does not actively search for or remove expired messages from the system. As such, expired messages are only deleted from the system when:

You should be aware that since no active searches are made for expired messages, they can accumulate on the system and strain system resources.

 


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 the DeliveryTime 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 Destinations" 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.

Table 4-3 Example Time-to-Deliver Schedules 

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:

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

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:

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(