5 Developing a Basic JMS Application
Importing Required Packages
Import the Java packages that define all required classes and interfaces to create, send, receive, and read messages for the WebLogic application.
Table 5-1 lists the packages that are commonly used by WebLogic JMS applications.
Table 5-1 WebLogic JMS Packages
| Package | Description |
|---|---|
jakarta.jms |
JMS API. This package is always used by WebLogic JMS applications. See |
javax.naming weblogic.jndi |
JNDI packages required for server and destination lookups. See |
jakarta.transaction.UserTransaction |
JTA API required for JTA user transaction support. See |
weblogic.jms.extensions |
WebLogic-specific JMS public API that provides additional classes and methods, as described in Value-Added Public JMS API Extensions. |
Setting Up a JMS Application
Before you can send and receive messages, you must set up a JMS application.
The following sections describe the procedure to set up a basic WebLogic JMS application:
You must ensure that the system administrator responsible for configuring WebLogic Server has configured the required JMS resources, including the connection factories, JMS servers, and destinations.
-
For information about JMS resource definitions, see Configuring Basic JMS System Resources in Administering JMS Resources for Oracle WebLogic Server.
-
For information about configuring other JMS resources, see Messaging in the Oracle WebLogic Remote Console Online Help.
-
For more information about the JMS interfaces and methods described in these sections, see Understanding the JMS API, or the
jakarta.jms, atjakarta.jms package, or the weblogic.jms.extensions Javadoc in Java API Reference for Oracle WebLogic Server. -
For information about setting up transacted applications and JTA user transactions, see Using Transactions with WebLogic JMS.
Using a Simplified API to Set Up a JMS Application
Oracle WebLogic Server 12.2.1 supports the JMS 2.0 simplified API for sending and receiving messages. For more information about the simplified API, see Understanding the Simplified API Programming Model.
Figure 5-1 shows the steps required to set up a JMS application using the JMS 2.0 Simplified API.
Figure 5-1 Setting Up a JMS Application Using the Simplified API

Description of "Figure 5-1 Setting Up a JMS Application Using the Simplified API"
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.
Use a unique configured name for each connection factory within a JMS module, and configure the JNDI name that clients use to look it up. You can also use the default connection factories defined by the Jakarta EE specification and WebLogic Server. For information, see Connection Factory Configuration in Administering JMS Resources for Oracle WebLogic Server.
After the connection factory is defined, establish the JNDI context used below with the InitialContext constructor. Code running in WebLogic Server, including servlets and EJBs, can use new InitialContext() for the local naming service. For a remote lookup, configure the appropriate JNDI environment properties, including the initial context factory and provider URL; you can pass them in a Hashtable to new InitialContext(environment). For constructor details, see InitialContext.
After the JNDI context is defined, to look up a connection factory in JNDI, execute the following command:
ConnectionFactory connectionFactory = (ConnectionFactory) namingContext.lookup(CF_name);
The CF_name argument specifies the connection factory's JNDI lookup name. It need not equal the connection factory's configured Name.
For more information about the ConnectionFactory interface, see ConnectionFactory, or the jakarta.jms.ConnectionFactory Javadoc, at ConnectionFactory.
Look Up a Queue or Topic
Before you can look up a queue or a topic, it must be configured by the WebLogic JMS system administrator, as described in Create a JMS System Module and Configure Resources for JMS System Modules in the Oracle WebLogic Remote Console Online Help. For more information, see Destination or the Javadocs at Queue and Topic.
After the destination is configured, you can look up a queue or topic destination using one of the following procedures:
You can look up a queue or topic destination by establishing a JNDI context (namingContext), which has already been accomplished in Look Up a Connection Factory in JNDI, and executing one of the following commands, for Point-to-Point or Publish/Subscribe messaging, respectively:
Queue queue = (Queue) namingContext.lookup(Queue_name); Topic topic = (Topic) namingContext.lookup(Topic_name);
The Queue_name and Topic_name arguments specify the JNDI names of the queue and topic destinations defined during the configuration.
Create a JMSContext Object
A JMSContext object replaces the Connection and Session objects in the classic API. For more information, see New Interfaces in the Simplified JMS API.
The JMSContext object can be created by calling one of the several createContext methods on a ConnectionFactory object. For example:
JMSContext context = connectionFactory.createContext(sessionMode);
In this case, a connection and a session with the specified mode are created for use by the new JMSContext object context. For more information, see connectionFactory interface definition in ConnectionFactory.
Alternatively, you can inject JMSContext in the Jakarta EE web and EJB containers using the @Inject annotation as described in Declaring a JMSContext Object Using @Inject Annotation. This is the recommended way for creating JMSContext in Jakarta EE applications. For example:
@Inject @JMSConnectionFactory("myJMSCF") JMSContext context;
For more information about using the JMSContext interface, see JMSContext.
Create JMSProducer and JMSConsumer Objects
Use the JMSProducer and JMSConsumer objects to send and receive messages respectively.
You can create a JMSProducer object by calling the createProducer method on a JMSContext object as follows:
JMSProducer producer = context.createProducer();
Note:
You do not need to save the JMSProducer object in a variable. Instead, create the object while calling the send method as follows:
context.createProducer().send(queue, message);
For more information, see JMSProducer.
You can create a JMSConsumer object by passing a queue or topic object to one of the createConsumer methods on a JMSContext object as follows:
JMSContext context = connectionFactory.createContext(); JMSConsumer consumer = context.createConsumer(queue);
For more information, see JMSConsumer.
Using the Classic API to Set Up a JMS Application
The following figure shows the steps required to set up a JMS application using JMS 1.1 classic API.
Figure 5-2 Setting Up a JMS Application using Classic API

Description of "Figure 5-2 Setting Up a JMS Application using Classic API"
Note:
Oracle WebLogic Server 12.2.1 supports JMS 2.0 simplified API for sending and receiving messages. See Understanding the Simplified API Programming Model.
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.
Use a unique configured name for each connection factory within a JMS module, and configure the JNDI name that clients use to look it up. You can also use the default connection factories defined by the Jakarta EE specification and WebLogic Server. For information, see "Connection Factory Configuration" in Administering JMS Resources for Oracle WebLogic Server.
After the connection factory is defined, establish the JNDI context used below with the InitialContext constructor. Code running in WebLogic Server, including servlets and EJBs, can use new InitialContext() for the local naming service. For a remote lookup, configure the appropriate JNDI environment properties, including the initial context factory and provider URL; you can pass them in a Hashtable to new InitialContext(environment). For constructor details, see InitialContext.
After the context is defined, to look up a connection factory in JNDI, execute one of the following commands, for PTP or Publish/Subscribe messaging, respectively:
QueueConnectionFactory queueConnectionFactory = (QueueConnectionFactory) context.lookup(CF_name); TopicConnectionFactory topicConnectionFactory = (TopicConnectionFactory) context.lookup(CF_name);
The CF_name argument specifies the connection factory's JNDI lookup name. It need not equal the connection factory's configured Name.
For more information about the ConnectionFactory interface, see ConnectionFactory, or the jakarta.jms.ConnectionFactory Javadoc, at ConnectionFactory.
Step 2: Create a Connection Using the Connection Factory
You can create a connection for accessing the messaging system by using the ConnectionFactory methods described in the following sections.
For more information about the Connection interface, see Connection, or the jakarta.jms.Connection Javadoc, at Connection.
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 interface methods, see the jakarta.jms.QueueConnectionFactory Javadoc, at QueueConnectionFactory. For more information about the QueueConnection interface, see the jakarta.jms.QueueConnection Javadoc, at QueueConnection.
Create a Topic Connection
The TopicConnectionFactory provides the following two methods to create 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 interface methods, see the jakarta.jms.TopicConnectionFactory Javadoc., at TopicConnectionFactory. For more information about the TopicConnection interface, see the jakarta.jms.TopicConnection Javadoc, at TopicConnection.
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 generic Session can create producers and consumers for both queues and topics, subject to the restrictions of the destination and acknowledgement mode. The domain-specific QueueSession and TopicSession interfaces retain their queue-only and topic-only restrictions.
Use a separate session for each thread that performs messaging concurrently. Once the connection is started, a session with registered message listeners and its producers and consumers must not be used by other application threads; this restriction also applies between callbacks. The permitted concurrent Session.close() and MessageConsumer.close() operations are exceptions. See the jakarta.jms.Session API documentation for the complete threading rules.
For more information about the Session interface, see Session or the jakarta.jms.Session Javadoc, at Session.
Create a Session Using the createSession Method
Use the createSession method in jakarta.jms.Connection to create a session. This method accepts a single parameter, sessionMode, or no parameter as follows:
Session createSession(int sessionMode) throws JMSException or Session createSession() throws JMSException
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. 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 interface methods, see the jakarta.jms.QueueConnection Javadoc, at QueueConnection. For more information about the QueueSession interface, see the jakarta.jms.QueueSession Javadoc, at QueueSession.
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. 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 interface methods, see the jakarta.jms.TopicConnection Javadoc, at TopicConnection. For more information about the TopicSession interface, see the jakarta.jms.TopicSession Javadoc, at TopicSession.
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 Create a JMS System Module and Configure Resources for JMS System Modules in the Oracle WebLogic Remote Console Online Help. For more information about the Destination interface, see Destination or the jakarta.jms.Destination Javadoc, at Destination.
After the destination is configured, you can look up a destination using a JNDI name or a reference:
Using a JNDI Name
You can look up a destination by establishing a JNDI context (context), which has already been accomplished in Look Up a Connection Factory in JNDI, and executing one of the following commands, for PTP or Publish/Subscribe messaging, respectively:
Queue queue = (Queue) context.lookup(Dest_name); Topic topic = (Topic) context.lookup(Dest_name);
The Dest_name argument specifies the JNDI name of the destination defined during configuration.
Use a Reference
If you do not use a JNDI namespace, you can use the following QueueSession or TopicSession method to reference a queue or topic, respectively:
Note:
The createQueue() and createTopic() methods do not create destinations dynamically; they create only references to destinations that already exist. For information about creating destinations dynamically, see Using JMS Module Helper to Manage Applications.
public Queue createQueue( String queueName ) throws JMSException public Topic createTopic( String topicName ) throws JMSException
For the syntax of JNDI name, createQueue(), and createTopic(), see How to Look Up a Destination.
Step 5: Create Message Producers and Message Consumers
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. After a message is 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 the write permission.
For more information about the MessageProducer and MessageConsumer interfaces, see MessageProducer and MessageConsumer, or the jakarta.jms.MessageProducer, at MessageProducer, and jakarta.jms.MessageConsumer Javadocs, at MessageConsumer.
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 null to createSender(), you create an anonymous producer. Specify a Queue object when sending each message, as described in Sending Messages.
Use getQueue() to obtain the Queue object associated with a QueueSender or QueueReceiver. An anonymous QueueSender returns null:
public Queue getQueue( ) throws JMSException
For more information about the QueueSession interface methods, see the jakarta.jms.QueueSession Javadoc, at QueueSession. For more information about the QueueSender and QueueReceiver interfaces, see the jakarta.jms.QueueSender, at QueueSender, and jakarta.jms.QueueReceiver Javadocs, at QueueReceiver.
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 createSubscriber methods shown here create non-durable subscribers, whose subscriptions last only while those subscribers exist. A durable subscription can retain eligible messages while it has no active consumer. Those messages remain available until acknowledged or removed, for example by expiration. A consumer that reconnects to the same durable subscription can receive its retained messages; creating a new subscription does not retrieve earlier publications. See Creating Subscribers for a Durable Subscription.
You must specify the topic object for the publisher or subscriber being created. You can 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 null to createPublisher(), you create an anonymous producer. Specify a Topic object when publishing each message, as described in Sending Messages.
An application can publish and subscribe using the same connection and can receive its own publications. To exclude messages published by that connection, set noLocal to true when creating the topic subscriber.
Use getTopic() to obtain the Topic object associated with a TopicPublisher or TopicSubscriber. An anonymous TopicPublisher returns null:
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 interface methods, see the jakarta.jms.TopicSession Javadoc, at TopicSession. For more information about the TopicPublisher and TopicSubscriber interfaces, see the jakarta.jms.TopicPublisher, at TopicPublisher, and the jakarta.jms.TopicSubscriber Javadocs, at TopicSubscriber.
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:
-
SessionMethodsNote:
These methods are inherited by both the
QueueSessionandTopicSessionsubclasses.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
-
WLSessionMethodpublic XMLMessage createXMLMessage( String text ) throws JMSException
For more information about the Session and WLSession interface methods, see the jakarta.jms.Session, at Session, and weblogic.jms.extensions.WLSession Javadocs, respectively. For more information about the Message interface and its methods, see Messages, or the jakarta.jms.Message Javadoc, at Message.
Step 6b: Optionally Register an Asynchronous Message Listener
Note:
This step applies to message consumers in Java SE applications and the Jakarta EE application client container. Web and EJB applications must use message-driven beans for asynchronous message receipt; they must not register a MessageListener on a consumer. See Jakarta EE Compliance.
To receive messages asynchronously, you must register an asynchronous message listener by performing the following steps:
To remove the message listener, call setMessageListener(null) on the MessageConsumer.
After a message listener is 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, then a ConsumerClosedException is delivered to the session exception listener, if one was defined. In this way, a new message consumer can be created, if necessary. For information about defining a session exception listener, see Defining a Connection Exception Listener.
The MessageConsumer interface methods are inherited by the QueueReceiver and TopicSubscriber interfaces. For additional information about the MessageConsumer interface methods, see MessageProducer and MessageConsumer or the jakarta.jms.MessageConsumer Javadoc, at MessageConsumer.
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 jakarta.jms.Connection Javadoc, at Connection.
Example: Setting Up a Point-to-Point JMS Application Using the Classic API
The following example is excerpted from the examples.jms.queue.QueueSend example, provided with WebLogic Server. When the WebLogic Server examples are installed, its source is in WL_HOME/samples/server/examples/src/examples/jms/classicapi/queue, where WL_HOME is the WebLogic Server installation directory. The init() method shows you 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 receiver, the provider calls examples.jms.queue.QueueReceive.onMessage(). The following code shows that callback method:
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 ("quit".equalsIgnoreCase(msgText)) {
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. For a TextMessage, it prints the text body. For another message type, it prints a diagnostic string representation. The null-safe comparison treats a text body equal to quit, ignoring case, as the request to stop the example.
Note:
It is good practice to verify that the received message is the type expected by the handler method.
For more information about the JMS classes used in this example, see Understanding the JMS API or the jakarta.jms Javadoc, at http://www.oracle.com/technetwork/java/jms/index.html.
Example: Setting Up a Publish-Subscribe JMS Application Using the Classic API
The following example is an excerpt from the examples.jms.topic.TopicSend example, provided with WebLogic Server. When the WebLogic Server examples are installed, its source is in WL_HOME/samples/server/examples/src/examples/jms/classicapi/topic, where WL_HOME is the WebLogic Server installation directory. The init() method shows you 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 topic. 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 one 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 subscriber, the provider calls examples.jms.topic.TopicReceive.onMessage(). This callback uses the same message-processing logic as QueueReceive.onMessage(), described in Example: Setting Up a Point-to-Point JMS Application Using the Classic API.
For more information about the JMS interfaces used in this example, see Understanding the JMS API or the jakarta.jms Javadoc, at jakarta.jms package.
Sending Messages
To send a message, you can use either the simplified API or the classic API.
You can start sending messages after you set up the JMS application as described in Setting Up a JMS Application.
Sending Messages Using the Simplified JMS API
In the simplified API, messages are sent by creating a JMSProducer object on behalf of JMSContext. For more information, see Create JMSProducer and JMSConsumer Objects.
To send a message to a specified destination, you can use the following JMSProducer method which is analogous to the send method of MessageProducer in the classic API:
JMSProducer send(Destination destination, Message message)
For example, to send an existing Message object:
context.createProducer().send(destination, message);
Alternatively, use the String overload to create and send a TextMessage:
context.createProducer().send(destination, "Hello");
The second call creates a TextMessage with the body Hello and sends it to the specified destination.
The following JMSProducer.send overloads create a message of the appropriate type and initialize its body from the supplied parameter:
JMSProducer send(Destination destination,byte[] body) JMSProducer send(Destination destination, Map<String,Object> body) JMSProducer send(Destination destination, Serializable body) JMSProducer send(Destination destination, String body)
For more information about the JMSProducer interface and send methods, see the Javadoc at:
Use the standard JMSProducer methods setDeliveryMode, setPriority, setDeliveryDelay, and setTimeToLive to configure message delivery. These methods do not require a WebLogic-specific cast. To use WebLogic extensions such as redelivery limits and send timeouts, cast a WebLogic JMS producer to weblogic.jms.extensions.WLJMSProducer. See WLJMSProducer in Java API Reference for Oracle WebLogic Server.
For example,
context.createProducer().setDeliveryMode(DeliveryMode.NON_PERSISTENT).send(destination,message);
A new JMSProducer uses DeliveryMode.PERSISTENT, priority 4, and a time-to-live of 0 (no expiration). Use its setter methods to change these producer settings. Configured destination delivery overrides take precedence over the corresponding values supplied by the producer. See Setting JMSProducer and MessageProducer Attributes and Configure Resources for JMS System Modules in the Oracle WebLogic Remote Console Online Help.
Sending Messages Using the Classic JMS API
Once you have set up the JMS application as described in Using the Classic API to Set Up a JMS Application, you can send messages. To send a message, you must, in order, perform the steps described in the following sections:
For more information about the JMS interfaces for sending messages and the message types, see the jakarta.jms.Message Javadoc, at Message. For information about receiving messages, see Receiving Messages.
Create a Message Object
This step has already been completed as part of the client setup procedure, as described in Step 6a: Create the Message Object (Message Producers).
Define a Message
This step may have been completed when you set up an application, as described in Step 6a: Create the Message Object (Message Producers). Whether or not this step has already been completed 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 the body already has the required value, continue to Send the Message to a Destination Using MessageProducer.
If no body value was specified, or if you want to change an existing value, use the appropriate setter method. For example, TextMessage provides the following method:
public void setText( String string ) throws JMSException
Note:
A TextMessage or ObjectMessage can have a null body. A Message object passed to a send method must not be null.
Subsequently, you can clear the message body using the following method:
public void clearBody( ) throws JMSException
For more information about methods used to define messages, see the jakarta.jms.Session Javadoc, at Session.
Send the Message to a Destination Using MessageProducer
The Destination and MessageProducer objects were created when you set up the application, as described in Using the Classic API to Set Up a JMS Application.
Note:
Each eligible topic subscription receives its own copy of a message. Consumers on the same shared subscription share that subscription's messages; each message is delivered to one consumer at a time. A received message's body and properties are read-only. Call clearBody() to clear the body and make it writable. Call clearProperties() separately to clear the properties and make them writable. Header fields are separate from the message body and properties.
For more information about the MessageProducer interface, see MessageProducer and MessageConsumer or the jakarta.jms.MessageProducer Javadoc, at MessageProducer.
Pass a Message object to send. For a producer created with a destination, use a send method without a destination argument. For an anonymous producer, created without a destination, supply a Destination object identifying the queue or topic.
The send overloads can specify delivery mode, priority, and time-to-live for an individual message. When those arguments are omitted, the producer's current values are used. Set delivery delay with MessageProducer.setDeliveryDelay; it is not a send-method argument.
WebLogic JMS initializes a classic MessageProducer's delivery mode, priority, and time-to-live from the connection factory. Producer setter methods change those values for subsequent sends, while explicit send arguments apply to that send. Configured destination delivery overrides take precedence over the corresponding message values. See Setting JMSProducer and MessageProducer Attributes and Configure Resources for JMS System Modules in the Oracle WebLogic Remote Console Online Help.
Persistent messages use the persistent store associated with the hosting JMS server. Depending on the JMS server's targeting and configuration, it uses a configured custom store or the hosting WebLogic Server instance's default store. For custom-store configuration, see Create a File Store and Create a JDBC Store in the Oracle WebLogic Remote Console Online Help.
Note:
If StoreEnabled is false for the JMS server, persistent sends are rejected unless AllowsPersistentDowngrade is true. When that option is enabled, persistent messages are downgraded to NON_PERSISTENT. Omitting a custom store does not by itself disable persistence.
The domain-specific QueueSender.send and TopicPublisher.publish methods provide the corresponding queue and topic operations.
For additional information about the QueueSender interface methods, see the jakarta.jms.QueueSender Javadoc, at QueueSender.
For more information about the TopicPublisher interface methods, see the jakarta.jms.TopicPublisher Javadoc, at TopicPublisher.
Sending a Message Asynchronously
An asynchronous send can return control before the send has completed. The provider calls CompletionListener.onCompletion(Message) when the message has been successfully sent, with the same degree of confidence as a successful synchronous send. This callback does not mean that a consumer has received or acknowledged the message.
Implement both onCompletion(Message) and onException(Message, Exception). A failure may be reported directly by the send call; if it cannot be thrown there, the provider reports it through onException. An exception does not by itself establish whether the message was sent. For more information, see the CompletionListener API reference.
Asynchronous sending with CompletionListener is not permitted in a Jakarta EE web or Enterprise Beans container. Use these examples in a supported client environment, such as a Java SE client.
After defining the jakarta.jms.CompletionListener object, send messages asynchronously using the JMSProducer or MessageProducer objects as described.
-
If you are using
JMSProducerobjects to send messages, call the methodsetAsync(CompletionListener listener)with a non-nullCompletionListeneron theJMSProducerobject before calling thesendmethod as listed in the following example:// send a message asynchronously try (JMSContext context = connectionFactory.createContext()) { MyCompletionListener myCompletionListener = new MyCompletionListener(); //call normal send method context.createProducer().setAsync(myCompletionListener).send(queue, "Hello world"); ... }For more information, see Sending Messages Using the Simplified JMS API.
-
If you are using a
MessageProducerto send messages, use the following method to send messages asynchronously:messageProducer.send(message,completionListener);
For more information, see Sending Messages Using the Classic JMS API.
Setting JMSProducer and MessageProducer Attributes
WebLogic JMS initializes classic MessageProducer delivery settings from the connection factory. A new JMSProducer instead uses DeliveryMode.PERSISTENT, priority 4, and a time-to-live of 0. For WebLogic JMS, the delivery delay follows the connection factory's default time-to-deliver setting until the application sets a delivery delay on the producer. Producer setters change the values used for later sends. Configured destination delivery overrides take precedence over the corresponding message values. See Configure Resources for JMS System Modules in the Oracle WebLogic Remote Console Online Help.
The standard producer methods configure delivery mode, priority, time-to-live, and delivery delay. WebLogic producer extensions also configure redelivery limits and send timeouts. Redelivery delay is a separate session/context setting, available through WLSession or WLJMSContext; it is not a producer send timeout. Table 5-2 distinguishes the classic and simplified producer methods.
Each cell lists the setter followed by its getter. All methods in the classic API column declare throws JMSException. Simplified API setters return the producer for method chaining; their methods use unchecked JMS runtime exceptions. The first four rows use the standard interfaces. The last two rows require the WebLogic extension named in that column.
Table 5-2 Message Producer Set and Get Methods
| Attribute | Classic API | Simplified API |
|---|---|---|
|
Delivery mode |
|
|
|
Priority |
|
|
|
Time-to-live |
|
|
|
Delivery delay |
|
|
|
Redelivery limit |
|
|
|
Send timeout |
|
|
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 interface methods, see the jakarta.jms.MessageProducer Javadoc, at MessageProducer, or the weblogic.jms.extensions.WLMessageProducer Javadoc.
Example: Sending Messages Within a Point-to-Point Application
The following example is excerpted from the examples.jms.queue.QueueSend example, provided with WebLogic Server. When the WebLogic Server examples are installed, its source is in WL_HOME/samples/server/examples/src/examples/jms/classicapi/queue, where WL_HOME is the WebLogic Server installation directory. 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 interface and methods, see the jakarta.jms.QueueSender Javadoc, at QueueSender.
Example: Sending Messages Within a Publish/Subscribe Application
The following example is excerpted from the examples.jms.topic.TopicSend example, provided with WebLogic Server. When the WebLogic Server examples are installed, its source is in WL_HOME/samples/server/examples/src/examples/jms/classicapi/topic, where WL_HOME is the WebLogic Server installation directory. 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 interface and methods, see the jakarta.jms.TopicPublisher Javadoc, at TopicPublisher.
Receiving Messages
Learn how to receive messages using the JMSConsumer and MessageConsumer methods.
After you 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.
The order in which messages are received can be controlled by the following:
-
Message delivery attributes (delivery mode and sorting criteria) defined during configuration or as part of the
send()method, as described in Sending Messages. -
Destination sort order set using destination keys, as described in Configure Resources for JMS System Modules in the Oracle WebLogic Remote Console Online Help.
After the message is 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 interfaces for receiving messages and the message types, see the jakarta.jms.Message Javadoc, at Message. For information about sending messages, see Sending Messages.
Receive Messages Asynchronously Using the Simplified API
This procedure applies to Java SE applications and the Jakarta EE application client container. Web and EJB applications must use message-driven beans for asynchronous message receipt. See Jakarta EE Compliance.
To receive messages, you must first create a JMSConsumer object using one of the several createConsumer or createDurableConsumer methods on JMSContext object.
Create a JMSConsumer object and use the method setMessageListener to specify the object that implements the MessageListener interface. By default, creating the consumer starts message delivery automatically. If the application has called context.setAutoStart(false), call context.start() when it is ready to receive messages.
JMSConsumer consumer = context.createConsumer(queue); consumer.setMessageListener(messageListener);
Receiving Messages Asynchronously using the Classic API
Receiving Messages Asynchronously using the Classic API is described within the context of setting up the application. For more information, see Step 6b: Optionally Register an Asynchronous Message Listener.
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
For asynchronous consumption, WebLogic JMS can push messages to a consumer's client-side pipeline before its message listener is ready to process them. The message pipeline, or backlog, consists of messages accumulated for that consumer that have not yet been passed to its listener. The connection factory's Messages Maximum setting controls the pipeline size.
Configuring a Message Pipeline
You can control a client's maximum pipeline size by configuring the Messages Maximum per Session attribute on the client's connection factory, which is defined as the "maximum number of messages that can exist for an asynchronous consumer and that have not yet been passed to the message listener". The default setting is 10. For more information about configuring a JMS connection factory, see Configure Resources for JMS System Modules in the Oracle WebLogic Remote Console Online Help.
Behavior of Pipelined Messages
After 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.
Note:
The Messages Maximum per Session pipeline size setting on the connection factory is not related to the Messages Maximum quota settings on JMS servers and destinations.
Messages in a pipeline can be aggregated into a single transport message. The combined encoded size must fit the effective maximum message size of the receiving network channel. The server's MaxMessageSize default is 10,000,000 bytes; a custom channel can override it with NetworkAccessPointMBean.MaxMessageSize. MaxT3MessageSize is a deprecated protocol-specific override. Account for aggregation and encoding overhead when choosing the pipeline size and message-size limits.
Receive Messages Synchronously Using the Simplified API
The receive methods on a JMSConsumer object are used for synchronous delivery of messages.
public String receiveMessage(
ConnectionFactory connectionFactory,Queue queue){
String body=null;
try (JMSContext context = connectionFactory.createContext();){
JMSConsumer consumer = context.createConsumer(queue);
body = consumer.receiveBody(String.class);
} catch (JMSRuntimeException ex) {
// handle exception
}
return body;
}For additional information about the JMSConsumer interface methods, see the jakarta.jms.JMSConsumer Javadoc, at JMSConsumer.
Receiving Messages Synchronously Using the Classic API
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
receive() and receive(0) wait indefinitely for a message available to that consumer or until the consumer is closed. receive(timeout) waits up to the specified number of milliseconds and returns null if the timeout expires or the consumer is concurrently closed. receiveNoWait() returns an available message immediately, or null if none is available.
The MessageConsumer interface methods are inherited by the QueueReceiver and TopicSubscriber interfaces. For additional information about the MessageConsumer interface methods, see the jakarta.jms.MessageConsumer Javadoc, at MessageConsumer.
Example: Receiving Messages Synchronously Within a PTP Application
The following example is excerpted from the examples.jms.queue.QueueReceive example, provided with WebLogic Server. When the WebLogic Server examples are installed, its source is in WL_HOME/samples/server/examples/src/examples/jms/classicapi/queue, where WL_HOME is the WebLogic Server installation directory. 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. When the WebLogic Server examples are installed, its source is in WL_HOME/samples/server/examples/src/examples/jms/classicapi/topic, where WL_HOME is the WebLogic Server installation directory. 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.
Use Prefetch Mode to Create a Synchronous Message Pipeline
Configure synchronous prefetch through SynchronousPrefetchMode on the connection factory's ClientParamsBean. The values are disabled (the default), enabled for queue receivers and topic subscribers, and topicSubscriberOnly for topic subscribers.
With prefetch enabled, WebLogic JMS can push messages ahead of synchronous receive calls so that messages are already available in the consumer's pipeline. MessagesMaximum controls the number of outstanding prefetched messages; it does not promise that every network batch has that size. Prefetch can reduce the number of synchronous server calls, but its performance benefit depends on the workload.
Prefetch is not supported for receives in a user (JTA/XA) transaction or with multiple consumers on one session. WebLogic JMS can disable prefetch when it detects these conditions before prefetch starts. After prefetch has started, a receive in a user transaction or an attempt to start prefetch on a second consumer can fail. Use one consumer per session and avoid user transactions when relying on synchronous prefetch.
For more information on the behavior of pipelined messages, see Asynchronous Message Pipeline. For more information on configuring a JMS connection factory, see Configure Resources for JMS System Modules in the Oracle WebLogic Remote Console Online Help.
Recovering Received Messages
Note:
Session.recover() operates on a non-transacted session and is not limited to CLIENT_ACKNOWLEDGE. It requests redelivery of unacknowledged messages; it does not undo acknowledgments. A synchronously received AUTO_ACKNOWLEDGE message has already been acknowledged when receive returns.
Where this operation is permitted, call Session.recover() to restart delivery of the session's unacknowledged messages:
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 re delivered in the same order that they were originally delivered, nor to the same queue consumers. For information to guarantee the correct ordering of re delivered messages, see Ordered Redelivery of Messages.
Acknowledging Received Messages
Use the acknowledge() method to acknowledge a received message. This method depends on how the connection factory's Acknowledge Policy attribute is configured.
Note:
This section applies only to non-transacted sessions for which the acknowledge mode is set to CLIENT_ACKNOWLEDGE.
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 the acknowledge on a message acknowledges all unacknowledged messages received on the session.
-
The "Previous" policy specifies that calling the 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
Close application-managed JMS resources when they are no longer needed.
For the classic API, close Connection, Session, MessageProducer, MessageConsumer, ConnectionConsumer, and QueueBrowser objects when they are no longer needed. Their close methods have the following signature:
public void close( ) throws JMSException
For the simplified API, close an application-managed JMSContext, or create it in a try-with-resources statement. Closing the context closes its session and consumers, and closes its connection when no other open JMSContext uses it. A JMSConsumer can also be closed separately. JMSProducer has no close method. Do not close an injected JMSContext; the container manages its lifecycle.
When closing an object:
-
Outside message-listener and completion callbacks, closing a consumer, session, or connection waits for its pending receives and message listeners to finish. Closing a producer, session, or connection also waits for outstanding asynchronous sends and CompletionListener callbacks. Consult the API contract for restrictions on calling close from a callback.
-
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 effects of the close() method for each object, see the appropriate jakarta.jms Javadoc, at jakarta.jms package. 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 an excerpt from the examples.jms.queue.QueueReceive example, provided with WebLogic Server. When the WebLogic Server examples are installed, its source is in WL_HOME/samples/server/examples/src/examples/jms/classicapi/queue, where WL_HOME is the WebLogic Server installation directory. 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 QueueReceive example, the close() method is called at the end of main() to close objects and free resources.