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 |
---|---|
javax.jms |
JMS API. This package is always used by WebLogic JMS applications. See |
weblogic.jndi |
JNDI packages required for server and destination lookups. See |
javax.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 Configure Messaging in the Oracle WebLogic Server Administration Console Online Help.
-
For more information about the JMS classes and methods described in these sections, see Understanding the JMS API, or the
javax.jms
, athttp://docs.oracle.com/javaee/7/api/javax/jms/package-summary.html
, 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.
The administrator can configure new connection factories during configuration; however, these factories must be uniquely named or the server will not boot. You can also use the default connection factories defined by the Java 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, you can look it up by establishing a JNDI context (namingContext
) using the InitialContext()
constructor, at http://docs.oracle.com/javase/7/docs/api/javax/naming/InitialContext.html#InitialContext()
. For any application other than a servlet application, you must provide a Hashtable
defining the environment when calling the InitialContext
constructor.
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 name defined during the configuration.
For more information about the ConnectionFactory
class, see ConnectionFactory, or the javax.jms.ConnectionFactory
Javadoc, at http://docs.oracle.com/javaee/7/api/javax/jms/ConnectionFactory.html
.
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 Configure topics and Configure queues in the Oracle WebLogic Server Administration
Console Online Help. For more information, see Destination or the Javadocs at http://docs.oracle.com/javaee/7/api/javax/jms/Queue.html
and http://docs.oracle.com/javaee/7/api/javax/jms/Topic.html
.
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 http://docs.oracle.com/javaee/7/api/javax/jms/ConnectionFactory.html
.
Alternatively, you can inject JMSContext
in the Java 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 Java EE applications. For example:
@Inject @JMSConnectionFactory("myJMSCF") JMSContext context;
For more information about using the JMSContext
interface, see http://docs.oracle.com/javaee/7/api/javax/jms/JMSContext.html
.
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 http://docs.oracle.com/javaee/7/api/javax/jms/JMSProducer.html
.
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 http://docs.oracle.com/javaee/7/api/javax/jms/JMSConsumer.html
.
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.
The administrator can configure new connection factories during configuration; however, these factories must be uniquely named or the server will not boot. You can also use the default connection factories defined by the Java 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, you can look it up by establishing a JNDI context (context
) using the InitialContext()
method, at http://docs.oracle.com/javase/8/docs/api/javax/naming/InitialContext.html#InitialContext()
. For any application other than a servlet application, you must pass an environment used to create the initial context.
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 name defined during configuration.
For more information about the ConnectionFactory
class, see ConnectionFactory, or the javax.jms.ConnectionFactory
Javadoc, at http://docs.oracle.com/javaee/7/api/javax/jms/ConnectionFactory.html
.
Step 2: Create a Connection Using the Connection Factory
You can create a connection for accessing the messaging system by using the ConnectionFactory
methods described in the following sections.
For more information about the Connection
class, see Connection, or the javax.jms.Connection
Javadoc, at http://docs.oracle.com/javaee/7/api/javax/jms/Connection.html
.
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, at http://docs.oracle.com/javaee/7/api/javax/jms/QueueConnectionFactory.html
. For more information about the QueueConnection
class, see the javax.jms.QueueConnection
Javadoc, at http://docs.oracle.com/javaee/7/api/javax/jms/QueueConnection.html
.
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
class methods, see the javax.jms.TopicConnectionFactory
Javadoc., at http://docs.oracle.com/javaee/7/api/javax/jms/TopicConnectionFactory.html
. For more information about the TopicConnection
class, see the javax.jms.TopicConnection
Javadoc, at http://docs.oracle.com/javaee/7/api/javax/jms/TopicConnection.html
.
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.
WebLogic JMS does not support having both types of MessageConsumer (QueueConsumer and TopicSubscriber) for a single Session. However, it does support a single session with both a QueueSender and a TopicSubscriber (and vice-versa: QueueConsumer and TopicPublisher), or with multiple MessageProducers of any type.
For more information about the Session
class, see Session or the javax.jms.Session
Javadoc, at http://docs.oracle.com/javaee/7/api/javax/jms/Session.html
.
Create a Session Using the createSession Method
Use the createSession
method in javax.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
class methods, see the javax.jms.QueueConnection
Javadoc, at http://docs.oracle.com/javaee/7/api/javax/jms/QueueConnection.html
. For more information about the QueueSession
class, see the javax.jms.QueueSession
Javadoc, at http://docs.oracle.com/javaee/7/api/javax/jms/QueueSession.html
.
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
class methods, see the javax.jms.TopicConnection
Javadoc, at http://docs.oracle.com/javaee/7/api/javax/jms/TopicConnection.html
. For more information about the TopicSession
class, see the javax.jms.TopicSession
Javadoc, at http://docs.oracle.com/javaee/7/api/javax/jms/TopicSession.html
.
Step 4: Look Up a Destination (Queue or Topic)
Before you can look up a destination, the destination must be configured by the WebLogic JMS system administrator, as described in Configure topics and Configure queues in the Oracle WebLogic Server Administration
Console Online Help. For more information about the Destination
class, see Destination or the javax.jms.Destination
Javadoc, at http://docs.oracle.com/javaee/7/api/javax/jms/Destination.html
.
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/Subscibe 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
classes, see MessageProducer and MessageConsumer, or the javax.jms.MessageProducer
, at http://docs.oracle.com/javaee/7/api/javax/jms/MessageProducer.html
, and javax.jms.MessageConsumer
Javadocs, at http://docs.oracle.com/javaee/7/api/javax/jms/MessageConsumer.html
.
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 the 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.
After the queue sender or receiver is 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, at http://docs.oracle.com/javaee/7/api/javax/jms/QueueSession.html
. For more information about the QueueSender
and QueueReceiver
classes, see the javax.jms.QueueSender
, at http://docs.oracle.com/javaee/7/api/javax/jms/QueueSender.html
, and javax.jms.QueueReceiver
Javadocs, at http://docs.oracle.com/javaee/7/api/javax/jms/QueueReceiver.html
.
Create TopicPublishers and TopicSubscribers
The TopicSession
object defines the following methods for creating topic publishers and topic subscribers:
public TopicPublisher createPublisher( Topic topic ) throws JMSException public TopicSubscriber createSubscriber( Topic topic ) throws JMSException public TopicSubscriber createSubscriber( Topic topic, String messageSelector, boolean noLocal ) throws JMSException
Note:
The methods described in this section create non-durable subscribers. Non-durable topic subscribers only receive messages sent while they are active. For information about the methods used to create durable subscriptions enabling messages to be retained until all messages are delivered to a durable subscriber, see Creating Subscribers for a Durable Subscription. In this case, durable subscribers only receive messages that are published after the subscriber has subscribed.
You must specify the topic object for the publisher or subscriber being created. You 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 a value of null to the createPublisher()
method, then 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 JMS connections 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
.
After the topic publisher or subscriber is 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, at http://docs.oracle.com/javaee/7/api/javax/jms/TopicSession.html
. For more information about the TopicPublisher
and TopicSubscriber
classes, see the javax.jms.TopicPublisher
, at http://docs.oracle.com/javaee/7/api/javax/jms/TopicPublisher.html
, and the javax.jms.TopicSubscriber
Javadocs, at http://docs.oracle.com/javaee/7/api/javax/jms/TopicSubscriber.html
.
Step 6a: Create the Message Object (Message Producers)
Note:
This step applies to message producers only.
To create the message object, use one of the following Session
or WLSession
class methods:
-
Session
MethodsNote:
These methods are inherited by both the
QueueSession
andTopicSession
subclasses.public BytesMessage createBytesMessage( ) throws JMSException public MapMessage createMapMessage( ) throws JMSException public Message createMessage( ) throws JMSException public ObjectMessage createObjectMessage( ) throws JMSException public ObjectMessage createObjectMessage( Serializable object ) throws JMSException public StreamMessage createStreamMessage( ) throws JMSException public TextMessage createTextMessage( ) throws JMSException public TextMessage createTextMessage( String text ) throws JMSException
-
WLSession
Methodpublic XMLMessage createXMLMessage( String text ) throws JMSException
For more information about the Session
and WLSession
class methods, see the javax.jms.Session
, at http://docs.oracle.com/javaee/7/api/javax/jms/Session.html
, and weblogic.jms.extensions.WLSession
Javadocs, respectively. For more information about the Message
class and its methods, see Messages, or the javax.jms.Message
Javadoc, at http://docs.oracle.com/javaee/7/api/javax/jms/Message.html
.
Step 6b: Optionally Register an Asynchronous Message Listener
Note:
This step applies to message consumers only.
To receive messages asynchronously, you must register an asynchronous message listener by performing the following steps:
You can unset a message listener by calling the MessageListener()
method with the value of null.
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
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, at http://docs.oracle.com/javaee/7/api/javax/jms/MessageConsumer.html
.
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, at http://docs.oracle.com/javaee/7/api/javax/jms/Connection.html
.
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 in the EXAMPLES_HOME
\wlserver\samples\server\examples\src\examples\jms\classicapi\queue
directory where EXAMPLES_HOME
represents the directory in which the WebLogic Server code examples are configured. 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 session, it is passed to the examples.jms.QueueReceive.onMessage()
method. The following code example 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 the onMessage()
method receives a different message type, then it uses the message's toString()
method to display the message contents.
Note:
It is good practice to verify that the received message is the type expected by the handler method.
For more information about the JMS classes used in this example, see Understanding the JMS API or the javax.jms
Javadoc, 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 in the EXAMPLES_HOME
\wlserver\samples\server\examples\src\examples\jms\classicapi\topic
directory, where EXAMPLES_HOME
represents the directory in which the WebLogic Server code examples are configured. 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 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 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 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 Point-to-Point JMS Application Using the Classic API.
For more information about the JMS classes used in this example, see Understanding the JMS API or the javax.jms
Javadoc, at http://www.oracle.com/technetwork/java/jms/index.html
.
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,
context.createProducer().send(destination,"Hello");
This code creates a TextMessage
object and sets its body to "Hello", and then sends it to the specified destination
.
You can also use the following JMSProducer
methods, which create a message automatically for of the appropriate message type and set the payload to the specified 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:
http://docs.oracle.com/javaee/7/api/javax/jms/JMSProducer.html
WebLogic JMS provides proprietary attributes that you can use while sending messages. You can specify the delivery mode (DeliveryMode.PERSISTENT
or DeliveryMode.NON_PERSISTENT
), priority (0-9
), delivery delay, and time-to-live (in milliseconds) by casting the JMSProducer
instance to weblogic.jms.extensions.WLJMSProducer
. See the Javadoc for WLSJMSProducer
in Java API Reference for Oracle
WebLogic Server.
For example,
context.createProducer().setDeliveryMode(DeliveryMode.NON_PERSISTENT).send(destination,message);
If not specified, the delivery mode, priority, and time-to-live attributes are set to one of the following:
-
Connection factory or destination override configuration attributes defined for the producer, as described Configure default delivery parameters in the Oracle WebLogic Server Administration Console Online Help.
-
Values specified using the JMSProducer object's set methods, as described in Setting JMSProducer and MessageProducer Attributes.
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 classes for sending messages and the message types, see the javax.jms.Message
Javadoc, at http://docs.oracle.com/javaee/7/api/javax/jms/Message.html
. 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 a value was specified and you do not want to change it, you can go to step 3.
If a value was specified or if you want 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 methods used to define messages, see the javax.jms.Session
Javadoc, at http://docs.oracle.com/javaee/7/api/javax/jms/Session.html
.
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:
If multiple topic subscribers are defined for the same topic, each subscriber will receive its own local copy of a message. 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 the write permission.
For more information about the MessageProducer
class, see MessageProducer and MessageConsumer or the javax.jms.MessageProducer
Javadoc, at http://docs.oracle.com/javaee/7/api/javax/jms/MessageProducer.html
.
You must specify a message. You can also specify the queue name (for anonymous message producers), delivery mode (DeliveryMode.PERSISTENT
or DeliveryMode.NON_PERSISTENT
), priority (0-9
), delivery delay, and time-to-live (in milliseconds). If not specified, the delivery mode, priority, and time-to-live attributes are set to one of the following:
-
Connection factory or destination override configuration attributes defined for the producer, as described in Configure default delivery parameters in the Oracle WebLogic Server Administration Console Online Help.
-
Values specified using the message producer's set methods, as described in Setting JMSProducer and MessageProducer Attributes.
If you define the delivery mode as PERSISTENT
, you should configure a backing store for the destination, as described in Configure persistent stores in the Oracle WebLogic Server Administration
Console Online Help.
Note:
If no backing store is configured, then the delivery mode is changed to NON_PERSISTENT
and messages are not written to the persistent store.
For more information about using the QueueSender
and TopicPublisher
methods for sending messages, see the WebLogic Server documentation at:
https://docs.oracle.com/middleware/1213/wls/JMSPG/implement.htm#JMSPG228
For additional information about the QueueSender
class methods, see the javax.jms.QueueSender
Javadoc, at http://docs.oracle.com/javaee/7/api/javax/jms/QueueSender.html
.
For more information about the TopicPublisher
class methods, see the javax.jms.TopicPublisher
Javadoc, at http://docs.oracle.com/javaee/7/api/javax/jms/TopicPublisher.html
.
Sending a Message Asynchronously
In asynchronous mode, the JMS client sends a message and returns control to the application without waiting for an acknowledgement from the JMS server.
To send messages asynchronously, your application should define a CompletionListener
object. When an acknowledgement is received from the JMS server to indicate that the message was received, the JMS provider notifies the application by invoking the callback method onCompletion
on the CompletionListener
object defined by the application. For more information about the CompletionListener
interface, see http://docs.oracle.com/javaee/7/api/javax/jms/CompletionListener.html
.
After defining the javax.jms.CompletionListener
object, send messages asynchronously using the JMSProducer
or MessageProducer
objects as described.
-
If you are using
JMSProducer
objects to send messages, call the methodsetAsync(CompletionListener listener)
with a non-nullCompletionListener
on theJMSProducer
object before calling thesend
method 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
MessageProducer
to 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
As described in the previous section, when sending a message, you can optionally specify the delivery mode, priority, delivery delay, and time-to-live values. If not specified, these attributes are set to the connection factory configuration attributes, as described in Configure connection factories in the Oracle WebLogic Server Administration Console Online Help.
Alternatively, you can set the delivery mode, priority, time-to-deliver, time-to-live, and redelivery delay (timeout), and redelivery limit values dynamically using the message producer's set methods. Table 5-2 lists the message producer set and get methods for each dynamically configurable attribute.
Note:
The delivery mode, priority, time-to-live, time-to-deliver, redelivery delay (timeout), and redelivery limit attribute settings can be overridden by the destination using the Delivery Mode Override, Priority Override, Time To Live Override, Time To Deliver Override, Redelivery Delay Override, and Redelivery Limit configuration attributes, as described in Configure message delivery overrides and Configure topic message delivery overrides in the Oracle WebLogic Server Administration Console Online Help.
Table 5-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 |
Redelivery limit |
public void setRedeliveryLimit(
int redeliveryLimit
) throws JMSException |
public int getredeliveryLimit(
) throws JMSException |
Send timeout |
public void setsendTimeout(
long sendTimeout
) throws JMSException |
public long getsendTimeout(
) throws JMSException |
Note:
JMS defines optional MessageProducer
methods for disabling the message ID and timestamp information. However, these methods are ignored by WebLogic JMS.
For more information about the MessageProducer
class methods, see the javax.jms.MessageProducer
Javadoc, at http://docs.oracle.com/javaee/7/api/javax/jms/MessageProducer.html
, or the weblogic.jms.extensions.WLMessageProducer
Javadoc.
Example: Sending Messages Within a Point-toPoint Application
The following example is excerpted from the examples.jms.queue.QueueSend
example, provided with WebLogic Server in the EXAMPLES_HOME
\wl_server\examples\src\examples\jms\queue
directory, where EXAMPLES_HOME
represents the directory in which the WebLogic Server code examples are configured. 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, at http://docs.oracle.com/javaee/7/api/javax/jms/QueueSender.html
.
Example: Sending Messages Within a Publish/Subscribe Application
The following example is excerpted from the examples.jms.topic.TopicSend
example, provided with WebLogic Server in the EXAMPLES_HOME
\wl_server\examples\src\examples\jms\topic
directory, where EXAMPLES_HOME
represents the directory in which the WebLogic Server code examples are configured. 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, at http://docs.oracle.com/javaee/7/api/javax/jms/TopicPublisher.html
.
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 destination keys in the Oracle WebLogic Server Administration Console Online Help.
After the message 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, at http://docs.oracle.com/javaee/7/api/javax/jms/Message.html
. For information about sending messages, see Sending Messages.
Receive Messages Asynchronously Using the Simplified API
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. Message delivery is started automatically.
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
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 are accumulated on an asynchronous consumer, but that are not been passed to a message listener.
Configuring a Message Pipeline
You can control a client's maximum pipeline size by configuring the Messages Maximum per Session attribute on the client's connection factory, which is defined as the "maximum number of messages that can exist for an asynchronous consumer and that have not yet been passed to the message listener". The default setting is 10. For more information about configuring a JMS connection factory, see Configure connection factories in the Oracle WebLogic Server Administration 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 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 theMaxT3MessageSize
attribute. This means that if ten 2 megabyte messages are in the pipelinet3
limit may be exceeded.
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 = session.createConsumer(queue); body = consumer.receiveBody(String.class); } catch (JMSRuntimeException ex) { // handle exception } return body; }
For additional information about the JMSConsumer
class methods, see the javax.jms.JMSConsumer
Javadoc, at http://docs.oracle.com/javaee/7/api/javax/jms/JMSConsumer.html
.
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
In each case, the application receives the next message produced. If you call the receive()
method with no arguments, then 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, then 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, at http://docs.oracle.com/javaee/7/api/javax/jms/MessageConsumer.html
.
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 EXAMPLES_HOME
\wl_server\examples\src\examples\jms\queue
directory, where EXAMPLES_HOME
represents the directory in which the WebLogic Server code examples are configured. 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 EXAMPLES_HOME
\wl_server\examples\src\examples\jms\topic
directory, where EXAMPLES_HOME
represents the directory in which the WebLogic Server code examples are configured. 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
In releases prior to WebLogic Server 9.1, synchronous consumers required making a two-way network calls for each message, which was an inefficient model because the synchronous consumer could not retrieve multiple messages, and could also increase network traffic resources, since synchronous consumers would continually poll the server for available messages. In WebLogic 9.1 or later, your synchronous consumers can also use the same efficient behavior as asynchronous consumers by enabling the Prefetch Mode for Synchronous Consumers option on JMS connection factories, either using the WebLogic Server Administration Console or the JMSClientParamsBean
MBean.
Similar to the asynchronous message pipeline, when the Prefetch Mode is enabled on a JMS client's connection factory, the connection factory's targeted JMS servers will proactively push batches of unconsumed messages to synchronous message consumers, using the connection factory's Messages Maximum per Session parameter to define the maximum number of messages per batch. This may improve performance because messages are ready and waiting for synchronous consumers when the consumers are ready to process more messages, and it may also reduce network traffic by reducing synchronous calls from consumers that must otherwise continually poll for messages.
Synchronous message prefetching does not support user (XA) transactions for synchronous message receives or multiple synchronous consumers per session (regardless of queue or topic). In most such cases, WebLogic JMS will silently and safely ignore the Prefetch Mode for Synchronous Consumer flag; however, otherwise WebLogic will fail the application's synchronous receive calls.
For more information on the behavior of pipelined messages, see Asynchronous Message Pipeline. For more information on configuring a JMS connection factory, see Configure connection factories in the Oracle WebLogic Server Administration Console Online Help.
Recovering Received Messages
Note:
This section applies only to non-transacted sessions for which the acknowledge mode is set to CLIENT_ACKNOWLEDGE
. Synchronously received AUTO_ACKNOWLEDGE
messages may not be recovered; they have already been acknowledged.
An application can request that JMS redeliver messages (unacknowledge them) using the following method:
public void recover( ) throws JMSException
The recover()
method performs the following steps:
-
Stops message delivery for the session
-
Tags all messages that have not been acknowledged (but may have been delivered) as redelivered
-
Resumes sending messages starting from the first unacknowledged message for that session
Note:
Messages in queues are not necessarily 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
When you finish using the connection, session, message producer or consumer, connection consumer, or queue browser created on behalf of a JMS application, you should explicitly close them to release the resources.
Enter the close()
method to close JMS objects, as follows:
public void close( ) throws JMSException
When closing an object:
-
The call blocks until the method call completes or until any outstanding asynchronous receiver
onMessage()
calls complete. -
All associated sub objects are also closed. For example, when closing a session, all associated message producers and consumers are also closed. When closing a connection, all associated sessions are also closed.
For more information about the effects of the close()
method for each object, see the appropriate javax.jms
Javadoc, at http://www.oracle.com/technetwork/java/jms/index.html
. 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.QueueSend
example, provided with WebLogic Server in the EXAMPLES_HOME
\wl_server\examples\src\examples\jms\queue
directory. EXAMPLES_HOME
represents the directory in which the WebLogic Server code examples are configured. 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.