Oracle Message Broker Adminstration Guide
Release 2.0.1.0

Part Number A65435-01

Library

Product

Contents

Index

Go to previous page Go to next page

3
JMS Programming

This chapter covers information about programming using the Oracle Message Broker and the JMS API. The following sections describe basic JMS programming using both JMS messaging domains, point-to-point (PTP), and publish/subscribe (Publish/Subscribe). Most client applications use only one of these JMS messaging domains.

This chapter covers the following:

Deployment Options for an Oracle Message Broker Application

There are four deployment options for an application, including:

  1. Using the LDAP Directory with a Local Mode Oracle Message Broker

  2. Using the LDAP Directory with a Remote Mode Oracle Message Broker

  3. Using Lightweight Configuration with a Local Mode Oracle Message Broker

  4. Using Lightweight Configuration with a Remote Mode Oracle Message Broker

Using each of these configuration and deployment options, an Oracle Message Broker application must perform the following tasks:

  1. Obtain a connection factory instance.

  2. Obtain a destination instance for a topic or a queue.

  3. Cleanup and shutdown.

This chapter covers the methods you need to use to perform these tasks using an LDAP Directory and either Local Mode or Remote Mode (Non-Local Mode). Chapter 13, "Lightweight Configuration" covers the details for the application programming tasks using Lightweight Configuration.


Note:

Using Local Mode or Remote (Non-Local Mode), the commands you use to start and stop the Oracle Message Broker differ. Refer to "Starting and Stopping the Oracle Message Broker" for information on starting and stopping the Oracle Message Broker. 


Programming Roadmap (Using an LDAP Directory)

This section describes JMS programming using the Oracle Message Broker. Figure 3-1 shows the standard JMS client programming steps when using the LDAP Directory configuration option in Remote Mode. This section explains JMS programming for both Local Mode and Remote Mode.

The steps a JMS client program executes to access and use the Oracle Message Broker are as follows:

  1. Use JNDI to lookup and create a Connection Factory. Refer to "Accessing Objects in the Directory" for more information.

  2. Use JNDI to lookup a Destination. Refer to "Accessing Objects in the Directory" for more information.

  3. Create and start a Connection using the connection factory. Refer to "Creating and Starting a Queue Connection" for PTP messaging or "Creating and Starting a Topic Connection" for Publish/Subscribe messaging.

  4. Use the new connection to create a Session. Refer to "Getting a Queue Session" for PTP messaging or "Getting a Topic Session" for Publish/Subscribe messaging.

  5. (Optional) When JNDI is not used to lookup a destination, you can use the session to create a Destination. Refer to "Working with Queue Destinations - QueueSender and QueueReceiver" for PTP messaging or "Working with Topic Destinations - TopicPublisher and TopicSubscriber" for Publish/Subscribe messaging.

  6. Create and handle messages. This step differs depending on the needs of the client. Clients may need to create messages or to consume them, or both. In a PTP messaging system, this step involves sending and receiving messages along with any other required conversions or processing. In a Publish/Subscribe messaging system, this step involves publishing messages, receiving messages, and subscribing to topics. Refer to "Sending and Receiving Messages" for PTP messaging or "Publishing and Subscribing" for Publish/Subscribe messaging.

  7. Finally, when clients finish, they need to cleanup and shutdown.

    Refer to "Shutting Down" for PTP messaging or "Shutting Down (Publish/Subscribe)" for Publish/Subscribe messaging.

    Figure 3-1 JMS Client Programming Steps (using an LDAP Directory)


Accessing Objects in the Directory

JMS clients obtain Oracle Message Broker administrative information from an LDAP Directory. Using JMS, clients find administrative objects by looking them up using JNDI. Oracle Message Broker clients follow this convention when the configuration mode uses the LDAP Directory. In this mode, the Oracle Message Broker uses the LDAP Directory to store administrative information, including the administrative objects for both PTP and Publish/Subscribe messaging.

The Oracle Message Broker also supports domain-specific methods for creating destinations dynamically. Dynamically created destinations do not use the LDAP Directory (see "Creating Destinations" for more details). Dynamic destinations are intended for use by advanced clients for specialized applications.

Using PTP messaging, client programs that send or receive messages need to obtain the following from the directory:

Similarly, using Publish/Subscribe messaging, client programs need to obtain the following from the directory:

Accessing Objects for Point-to-Point Messaging

Before you use JMS for PTP messaging, the administrator needs to create certain administrative objects (see Chapter 2 for information on creating administrative objects). After creating the administrative objects and starting the Oracle Message Broker, a client program obtains and uses the information stored in the directory to initialize a connection with the Oracle Message Broker.

Accessing the Connection Factory with JNDI (for Point-to-Point)

A JMS client that sends or receives messages needs to create a queue connection factory. The client uses the queue connection factory to create a connection with the Oracle Message Broker.

To access the connection factory, the administrator creates a directory entry for the queue connection factory. The client uses the JMS API, and the connection factory that it obtains from the directory lookup to establish a connection with an active Oracle Message Broker. The Oracle Message Broker also supports a JMS extension for a connection factory that supports creating topic and queue connections (see "Universal Connections and Universal Sessions" for more information).

The following code shows the JNDI lookup for accessing a connection factory:

  SimpleSession(DirContext initCtx, String cfDn)
  {
    QueueConnectionFactory queueConnectionFactory;
    try
    { 
      queueConnectionFactory = (QueueConnectionFactory)
        initCtx.lookup(cfDn);
      if (queueConnectionFactory == null)
        {
          System.out.println("Lookup object returned null");
          System.exit(-1);
        }
     }catch () { }
   }

As is the example above, to obtain a QueueConnectionFactory instance, the client program uses a JNDI lookup on a connection factory entry in the LDAP Directory.

Remote Mode Connection Factory Support

The Oracle Message Broker's JNDI support code obtains the IOR of a remote mode Oracle Message Broker process from an LDAP Server. The Oracle Message Broker client side runtime uses the IOR to communicate with the remote mode Oracle Message Broker using IIOP.

Note the following limitations when obtaining the QueueConnectionFactory instance:

Local Mode Connection Factory Support

Accessing the Queue with JNDI (for Point-to-Point)

You can obtain instances of javax.jms.Queue using JNDI lookups on destination directory entries. The administrator creates the queue entries and queues that a client JMS program uses to specify, and that the Oracle Message Broker uses to determine where to store messages. A client program that needs to send or receive messages uses JNDI to locate the queue entry. The JNDI lookup returns a reference to an object that implements javax.jms.Queue.

The following code shows a queue lookup that creates a javax.jms.Queue object:

queue = (Queue) initCtx.lookup(qDn);

Accessing Objects for Publish/Subscribe Messaging

Before you can use JMS for Publish/Subscribe messaging, the administrator needs to create certain administrative objects (see Chapter 2 for information on creating administrative objects). After creating the administrative objects and starting the Oracle Message Broker, a client program obtains and uses the information stored in the directory to initialize a connection with the Oracle Message Broker.

Accessing the Connection Factory with JNDI (for Publish/Subscribe)

A JMS client program that publishes messages to a topic, or that subscribes to a topic, needs to create a topic connection factory. The client uses the topic connection factory to create a connection with the Oracle Message Broker.

To access the connection factory, the administrator creates a directory entry for the topic connection factory. The client uses the JMS API, and the connection factory that it obtains from the directory lookup to establish a connection with an active Oracle Message Broker. The Oracle Message Broker also supports a JMS extension for a connection factory that creates topic connections and queue connections (see "Universal Connections and Universal Sessions" for more information).

The following code shows the JNDI lookup for accessing a topic connection factory:

    TopicConnectionFactory topicConnectionFactory;
    try
    {
      topicConnectionFactory = (TopicConnectionFactory)initCtx.lookup(cfDn);
      if (topicConnectionFactory == null)
      {
          System.out.println("Lookup object returned null");
          System.exit(-1);
      }
     }catch () { }
    }

As is the example above, to obtain a TopicConnectionFactory instance, the client program uses a JNDI lookup on a connection factory entry in the LDAP Directory.

Remote Mode Connection Factory Support

The Oracle Message Broker's JNDI support code obtains the IOR of an Oracle Message Broker process from an LDAP server. The client program uses the Oracle Message Broker client-side runtime to interact with an Oracle Message Broker process using IIOP.

Note the following limitations when obtaining the TopicConnectionFactory instance:

Local Mode Connection Factory Support

In Local Mode, the client program obtains a connection factory instance using a JNDI lookup on a connection factory entry in the LDAP Directory. Oracle Message Broker's JNDI support code either starts an Oracle Message Broker within the Oracle Message Broker client process or obtains a handle to a previously started Oracle Message Broker within the Oracle Message Broker client process in the process before the lookup returns.

Accessing Topics with JNDI (for Publish/Subscribe)

You can obtain instances of javax.jms.Topic are using JNDI lookups on destination directory entries. The administrator creates the topic entries and queues that a client JMS program uses to specify and the Oracle Message Broker uses to determine where to store messages. A client program that needs to publish or subscribe to messages uses JNDI to locate the topic entry. The JNDI lookup returns a reference to an object that implements javax.jms.Topic.

The following code shows a topic lookup that creates a topic object:

topic = (Topic) initCtx.lookup(topicDn);

Point-to-Point Messaging

This section describes the programming steps required to send and receive messages using the JMS PTP methods. The following steps assume that the administrator has created the queue connection factory and one or more queues, and that these Oracle Message Broker administrative objects were obtained as described in "Accessing Objects in the Directory".

This section covers the following:

Figure 3-2 shows the path of messages for a simple point to point communication using a single queue.

Figure 3-2 JMS Programming Using the Point to Point Model


Creating and Starting a Queue Connection

Once you obtain a queue connection factory, use it to create a QueueConnection and use the start method to establish communications with an active Oracle Message Broker. When you first create the QueueConnection, the connection is stopped.


Note:

When the QueueConnection is created, it is in the stopped mode. When a connection is stopped, consumers cannot receive messages and calls to receive do not return. 


The QueueConnection is an active connection to the JMS provider (Oracle Message Broker). A client uses the QueueConnection to create one or more QueueSessions for producing and consuming messages.

QueueConnection queueConnection = null;
queueConnection = queueConnectionFactory.createQueueConnection();
queueConnection.start();

The JMS specification contains information that client programs should follow on the preferred use of the start method. When the QueueConnection is created, it is in the stopped mode. In general, it is best to leave the connection in the stopped mode while its sessions are being created, and then use the start method to start the stopped connection (for more information on conventions for using a session, see section 4.4.6 of the JMS specification).

Getting a Queue Session

After creating the QueueConnection, the client program needs to create a QueueSession. A session is single threaded, therefore concurrent operations are not allowed on a session. The session is used to create destinations for sending or receiving messages. A single connection can support multiple sessions, each maintaining its own state. The Oracle Message Broker supports a feature called Universal Sessions. Universal Sessions support both topic and queue sessions within a single session. See "Universal Connections and Universal Sessions" for more information on Universal Connections.

The following example shows how to create a session using the createQueueSession method:

QueueSession queueSession = null;
queueSession = queueConnection.createQueueSession(false, 
                                         MercurySession.IMMEDIATE_ACKNOWLEDGE);

The first parameter to createQueueSession indicates if the session is transacted. The parameter's value is either true or false.

The second parameter to createQueueSession indicates the mode of acknowledging message receipt (for more information on message acknowledgment, see section 4.4.13 in the JMS specification and see "Message Listeners and Threads").

If the session is transacted, the first parameter to createQueueSession is true, and the acknowledge mode parameter is ignored. If the session is not transacted, the first parameter to createQueueSession is false, and the acknowledge mode parameter must be the following:

MercurySession.IMMEDIATE_ACKNOWLEDGE

Working with Queue Destinations - QueueSender and QueueReceiver

Once a session is created, messages can be sent within the session by creating queue senders, and messages can be received by creating queue receivers. A destination must be specified when a queue receiver is created.

Creating a QueueSender

Use the QueueSession createSender method to create a QueueSender.

QueueSender sender;
sender = session.createSender(queue);

The createSender method creates an object that can be used to send messages to a queue. The queue administrative object is obtained as described in "Accessing Objects for Point-to-Point Messaging".

Creating a QueueReceiver

Use the QueueSession method createReceiver to create a QueueReceiver for receiving messages.

QueueReceiver receiver;
receiver = session.createReceiver(queue);

The queue parameter is the queue to receive messages from. The queue administrative object is obtained as described in "Accessing Objects for Point-to-Point Messaging".

Sending and Receiving Messages

Finally, the client program needs to create a message of the desired type and send it to a queue. The client program that is receiving messages also needs to create a message.

Creating and Sending Messages

This example shows how to create and send a text message. The Oracle Message Broker and JMS support several message types in addition to a text message.

TextMessage message_out;
message_out = session.createTextMessage();
message_out.setText("Data");
sender.send(message_out);

Creating and Receiving Messages

This example shows how to receive a text message.

A client can receive messages either synchronously or have the provider asynchronously deliver the messages as they arrive. For information on asynchronous delivery and the message listener interface, see the JMS specification, section 4.5.2.

The following code shows the use of the QueueReceiver.receive method for synchronous delivery:

TextMessage message_in;
message_in = session.createTextMessage();
message_in = receiver.receive();
String inData = message_in.getText();

Shutting Down

Client programs run in either Local Mode or Remote Mode (Non-Local Mode). A client program in either mode needs to shut down when it finishes. Refer to Chapter 5 for information on Local Mode and Remote Mode clients.

When a client is done with the Oracle Message Broker, it should call Mercury.shutdownClient(). This shuts down any Oracle Message Brokers running in Local Mode, and the ORB, if remote Oracle Message Brokers have been accessed, and performs certain cleanup operations. Clients call this method as follows:

oracle.oas.mercury.Mercury.shutdownClient()


Note:

The shutdown methods are not part of the JMS specification. They assist the Oracle Message Broker in cleanup, and allow clients to exit and cleanup. 


After the Oracle Message Broker is shut down, keep the following in mind:

Publish/Subscribe Messaging

This section describes the programming steps required to publish messages to a topic and subscribe to topics to receive messages using the JMS Publish/Subscribe methods. The following steps assume that the administrator has created the topic connection factory and one or more topics, and that these Oracle Message Broker administrative objects were obtained as described in "Accessing Objects in the Directory" .

This section covers the following:

Figure 3-3 shows the path of messages for a simple Publish/Subscribe model.

Figure 3-3 JMS Programming Using a Publisher and a Subscriber


Creating and Starting a Topic Connection

Once you obtain a topic connection factory, use it to create a TopicConnection and use the start method to establish communications with the Oracle Message Broker. When you first create the TopicConnection, the connection is stopped.


Note:

When the TopicConnection is created, it is in the stopped mode. When a connection is stopped, consumers cannot receive messages and calls to receive do not return. 


The TopicConnection is an active connection to the provider. A client uses the TopicConnection to create one or more TopicSessions for producing and consuming messages.

TopicConnection topicConnection = null;
topicConnection = topicConnectionFactory.createTopicConnection();
topicConnection.start();

The JMS specification contains information that client programs should follow on the preferred use of the start method. When the TopicConnection is created, it is in the stopped mode. When a connection is stopped, consumers cannot receive messages. In general, it is best to leave the connection in the stopped mode while its sessions are being created, and then use the start method to start the stopped connection (for more information on conventions for using a session, see section 4.4.6 of the JMS specification.)

Getting a Topic Session

After creating the TopicConnection, the client program needs to create a session. A session is single threaded, therefore concurrent operations are not allowed on a session. Subscribers and Publishers are created within the session. A single connection can support multiple sessions, each maintaining its own state (transactions, publishers, and subscribers).

The following example shows how to create a session using the TopicConnection's createTopicSession method:

TopicSession topicSession = null;
topicSession = topicConnection.createTopicSession(false, 
                                        MercurySession.IMMEDIATE_ACKNOWLEDGE);

The first parameter to createTopicSession indicates if the session is transacted. The parameter value is either true or false.

The second parameter to createTopicSession indicates the mode of acknowledging message receipt (for more information on message acknowledgment, see section 4.4.13 in the JMS specification and see "Message Listeners and Threads").

If the session is transacted, the first parameter to createTopicSession is true, and the acknowledge mode parameter is ignored. If the session is not transacted, the first parameter to createTopicSession is false, and the acknowledge mode parameter must be the following:

MercurySession.IMMEDIATE_ACKNOWLEDGE

Working with Topic Destinations - TopicPublisher and TopicSubscriber

To publish messages to a topic, create a publisher within a session. To receive messages from a topic, create a subscriber within a session.

Creating a TopicPublisher

Use the TopicSession method createPublisher to create a TopicPublisher.

TopicPublisher publisher;
publisher = session.createPublisher(topic);

The topic parameter is the topic to send messages to. The topic administrative object is obtained as described in "Accessing Objects for Point-to-Point Messaging".

Creating a TopicSubscriber

Use the TopicSession method createSubscriber to create a TopicSubscriber.

TopicSubscriber subscriber;
subscriber = session.createSubscriber(topic);

The topic parameter is the topic to subscribe to messages. The topic administrative object is obtained as described in "Accessing Objects for Point-to-Point Messaging".

Publishing and Subscribing

Finally, the client program needs to create a message of the appropriate type and send it to a topic.

Creating and Publishing Messages

This example shows how to create and send a text message.

TextMessage message_out;
message_out = session.createTextMessage();
message_out.setText("Data");
publisher.publish(message_out);

Subscribing to Topics

A client can receive messages either synchronously or have the provider asynchronously deliver the messages as they arrive. For information on asynchronous delivery and the message listener interface, see section 4.5.2 in the JMS specification.

The following code shows a synchronous delivery using the TopicSubscriber.receive method:

TextMessage message_in;
message_in = session.createTextMessage();
message_in = subscriber.receive();
String inData = message_in.getText();

Shutting Down (Publish/Subscribe)

Client programs run in either Local Mode or Remote Mode (Non-Local Mode). A client program in either mode needs to shut down when it finishes. Refer to Chapter 5 for information on Local Mode and Remote Mode clients.

When a client is done with the Oracle Message Broker, it needs to shut down. The procedure for shutting down is the same for PTP and Publish/Subscribe Messaging. See "Shutting Down" for more information.

Message Listeners and Threads

This section lists important points to keep in mind when you are using JMS with message listeners.

  1. When the Oracle Message Broker is running, the following methods can be called by any thread after a message listener has been registered:

    • Session.close() When message listeners have been registered within a session, no listeners will be executed when Session.close returns. The implication is that Session.close blocks if a listener is executing the onMessage method for that session.

    • MessageConsumer.setMessageListener() only if the connection is stopped.

  2. The MessageConsumer.close() method cannot be called after a listener has been registered within the session.

  3. All JMS methods, other than those mentioned above, can only be called by the thread executing the message listener. The client-side runtime enforces this restriction when a listener has been registered in that session.

    The following methods must be called by the thread executing the message listener if one has been registered (they cannot be called by any other thread after a message listener has been registered):

    • Session.rollack() (can only be called by the listener)

    • Session.commit() (can only be called by the listener)

    Session.close and MessageConsumer.setMessageListener are the only methods that can be called in a session, or in the consumers, producers, and message listeners within that session once a message listener has been registered, if the caller is not executing in the thread that executes the message listeners.

  4. As described in the JMS specification [JMS 4.5.2], the result of a MessageListener throwing a RuntimeException depends on the session's acknowledgment mode. In the Oracle Message Broker, the following rules apply for RuntimeExceptions.

    • MecurySession.IMMEDIATE_ACKNOWLEDGE: the message will not be redelivered. The message is lost. In this mode, message delivery is at-most-once delivery.

    • For a transactional session, the next message for the listener is delivered. The client can then either commit or rollback the Session. A RuntimeException does not automatically rollback the session. If the client fails, the Oracle Message Broker performs a rollback for the Session.

  5. For a durable subscriber with a message listener, note the following:

    • An unsubscribe cannot be performed when the subscriber is in use.

    • The subscriber is in use until the session is closed. The only way to close a message consumer once a listener has been registered is to close the session.

    • Since the session cannot be used after it has been closed, to unsubscribe, use another session to perform the unsubscribe.

    • The subscription created for a durable subscriber is only cancelled by calling Session.unsubscribe. Subscriptions for non-durable subscribers are cancelled when the consumer is closed.

Closing JMS Objects and Death Detection

The Oracle Message Broker has a mechanism to detect JMS connections and sessions that have been closed implicitly (this means the JMS connection is closed by the finalizer rather than by a call to connection.close or session.close). When a JMS connection is closed, either implicitly or by calling connection.close, there is no need to explicitly close the sessions, consumers, or producers that had been created within that JMS connection.

When message listeners have been registered within a session, no listeners will be executed when Session.close returns. The implication is that Session.close blocks if a listener is executing the onMessage method for that session.

Connection.close closes each session within that connection. Connection.close blocks if a listener is executing within one of the connection's sessions. When Connection.close returns, no message listeners will be executed for any listeners that had been set for the connection's sessions.

Oracle Message Broker objects other than JMS connections and sessions do not have a mechanism to detect consumers or producers that have been closed implicitly. When you are programming with Oracle Message Broker, it is important to explicitly close sessions, consumers, and producers using the corresponding close method when you are done with the object. When a session is closed, there is no need to explicitly close the consumers and producers that had been created within that session.

When a JMS connection is closed, explicitly or by the finalizer, Oracle Message Broker frees resources for the JMS connection, and the sessions, consumers, or producers within that JMS connection. Oracle Message Broker does not free resources for consumers or producers that have been garbage collected when the corresponding JMS connection or session has not been garbage collected. Oracle Message Broker detects client processes that have stopped running. If the Oracle Message Broker had allocated resource for the client it will cleanup the resources (rollback transactions, release Database Server connections). Note that the detection mechanism is not instantaneous, it takes some amount of time.

Leaked Resources and Death Detection

Several conditions may affect performance and available resources. For this section, use the following definitions:

The Oracle Message Broker uses a death detection thread that runs every 20 seconds to find leaked connections and leaked sessions. Leaked connections and leaked sessions will be detected within two intervals (40 seconds). Leaked connections and sessions, and the resources associated with them, are released when the leak is detected.

The death detection thread is run more frequently when any of the following occur:

  1. Low memory is detected in the Oracle Message Broker.

  2. The number of sessions in AQ Driver approaches maxPrivateSessions (this operation is AQ Driver specific).

  3. A consumer attempts to use a durable subscriber name that is in use. This is handled by pinging the current user of the durable subscriber name to detect when a client exits and then restarts and attempts to create a durable subscriber with the same name.

Setting the Message Priority

The Oracle Message Broker sets the message priority after a client invokes the send or publish method on a message. This overwrites any value set by the client using a call to Message.setJMSPriority() before the message is sent or published.

Oracle Message Broker sets the priority value for a message as follows:

  1. The value of the priority argument in the call to send or publish if there is a priority argument.

  2. The priority value set as the default for the message producer if there is not a priority argument in the call to send or publish. The priority for a message producer is set using a call to MessageProducer.setPriority().

Use a call to Message.setJMSPriority() to change the priority value for a message that has been received.


Go to previous page Go to next page
Oracle
Copyright © 1996-2000, Oracle Corporation.

All Rights Reserved.

Library

Product

Contents

Index