D Advanced Programming with Distributed Destinations Using the JMS Destination Availability Helper API

Learn how to design a distributed application or a container that offers high availability (HA), scalability, and flexibility when using JMS distributed destinations in a clustered environment.

Note:

This guide includes advanced information for experienced JMS developers. Oracle recommends that you use Message Driven Beans (MDBs) when interacting with Distributed Destinations. The MDB container automatically creates and closes internal consumers across all members of a Distributed Destination as needed. It also handles security, threading, pooling, application life cycle, automatic reconnect, and transaction enlistment. If you cannot use MDBs, then you can use simpler workarounds, such as periodically restarting consumers to rebalance consumers across a distributed destination, or if messaging ordering and performance are not a concern, then enabling the distributed queue forwarding option.

Introduction

A distributed destination (DD) is a group of JMS physical destinations (a group of queues or a group of topics) that is accessed as a single logical destination. Messages are load balanced across members, and clients can failover between member destinations.

Distributed destination users that don't leverage MDBs may encounter problems with consumer applications. These include:

  • Failing to ensure that all DD members are serviced by consumers.

  • Unprocessed messages accumulating on DD members that have no consumers.

  • DD Consumers not automatically rebalancing in the event of a JMS server migration, WebLogic Server restart, or any other event that results in DD member changes.

To address these use cases, WebLogic Server provides the JMS Destination Availability Helper APIs and advanced topic features in Developing Advanced Pub/Sub Applications.

Controlling DD Producer Load Balancing

Before discussing consumer load balancing, it is helpful to first explore producer load balancing basics and best practices.

Basic JMS

A JMS program sets up message sends in three stages:

  1. Clients create a JMS connection into WebLogic using a JMS connection factory.

  2. Clients use the connection to create JMS sessions and senders.

  3. Clients use the senders to send messages.

In WebLogic JMS, the WebLogic server that the client is connected to is called the client's connection host, and messages always route from the sender, through its connection host, and then on to a destination that's in the same cluster as the connection host. Connections stay pinned to their connection host for the life of the connection.

A WebLogic connection factory can be targeted at one or more WebLogic servers. If a client is running on the same WebLogic server where a connection factory is targeted, then the factory always returns a connection with a connection host that is the same server as the client (the connection is local). On the other hand, if a client is not running on a WebLogic server that is included in its connection factory targets, the factory automatically load balances among the targets and returns a connection to one of them.

When working with a distributed destination, senders should always send to the JNDI name of the DQ or PDT (its "logical name") instead of sending to the JNDI names of the individual members, as this enables automatic load balancing behavior.

Senders to Distributed Queues (DQs) and Partitioned Distributed Topics (PDTs)

The default behavior for a sender to a DQ or PDT is: If there are members that run on the sender's connection host, all sent messages go to one of these local members, otherwise messages move in a round-robin among all members.

To force messages from the same DQ or PDT sender to move in a round-robin among all active members even when local members reside on the sender's connection host, use a custom connection factory with Server Affinity set to false and Load Balance set to true.

Senders to Replicated Distributed Topics (RDTs)

Senders to RDTs always load balance once and then pin to a particular member for all messages - this member becomes the "sender host". After a message arrives on the sender host, the message is automatically replicated to every subscription on every RDT member.

If you want to control the initial load balance decision for the sender host so that it is not biased towards being the same as its connection host, then use a connection factory with Server Affinity configured to false (default is true), and Load Balance configured to true (the default).

Using the JMS Destination Availability Helper API

The following sections provide information on how to use the JMSDestinationAvailabilityHelper APIs:

Overview

When a consumer is created using the client javax.jms API and a DD logical JNDI name is specified, the consumer is load balanced to an active DD member and remains pinned to that member over its lifetime. If new members become active after all consumers were created, then the new members have no consumers.

The JMSDestinationAvailabilityHelper APIs provide a way to get notifications when destinations become available or unavailable. These notifications can help ensure that an application creates consumers on all DD members even when there are unavailable members at the time the application is initialized. The same mechanism can also be used to detect availability of other types of destinations (not just WebLogic distributed destinations, but also regular destinations and foreign vendor destinations).

Applications register a notification listener with the helper by specifying JNDI context parameters and the JNDI name of a destination. For DDs, the helper notifies listeners when members become available and unavailable, as they are undeployed, added as a new member, migrated, shut down, or restarted.

Note that MDBs in WebLogic Server internally use this same mechanism for both local MDBs (deployed in the same cluster as a DD) and remote MDBs (deployed in a cluster that is separate from the cluster that hosts the DD). MDBs provide an out-of-the-box solution that achieves the same dynamic adaptability to DD topology changes that the JMSDestinationAvailabilityHelper APIs provide.

General Flow

Applications that use the JMSDestinationAvailabilityHelper APIs should follow these general steps:

  1. Implement the weblogic.jms.extensions.DestinationAvailableListener interface to provide behavior as per step 3 below.

  2. Register interest with the helper by specifying JNDI context properties (typically just a URL and context factory), the JNDI name of the destination, and a listener instance. Do not specify a URL if the client is running in the same cluster as the DD.

    import java.util.Hashtable;
    import javax.naming.Context;
    import weblogic.jms.extensions.JMSDestinationAvailabilityHelper;
    
    Hashtable contextProps = new Hashtable();
    contextProps.put(javax.naming.Context.PROVIDER_URL, myURL);
    contextProps.put(Context.INITIAL_CONTEXT_FACTORY, "weblogic.jndi.WLInitialContextFactory");
    JMSDestinationAvailabilityHelper dah = JMSDestinationAvailabilityHelper.getInstance();
    
    RegistrationHandler rh = dah.register(
       contextProperties,
       destinationJNDIName,
       myDestinationAvailableListener
    )
    
  3. Handle listener callbacks. Callbacks are single-threaded for each listener instance, so no two callbacks occur concurrently.

    1. onDestinationsAvailable(): Typically the first notification. Implementations of this callback usually react by creating zero or more consumers on each given destination, and if this fails, periodically retrying.

    2. onDestinationsUnavailable(): This callback is usually used to destroy existing consumers on the destination.

    3. onFailure(): This callback is usually used simply to log a failure. The helper continues to retry internally and make subsequent callbacks, but administrators may need to see the failure. The helper makes a best effort to just call theonFailure()method once for the same repeated failures.

  4. When you are done, unregister interest in a destination by calling the rh.unregister()method.

Handling the weblogic.jms.extension.DestinationDetail

As described previously, an onDestinationsAvailable() notification indicates that a stand alone destination, foreign destination, or distributed destination member has become available. The notification consists of a list of DestinationDetail instances, where key information is obtained by calling thegetDestinationType(), getJNDIName(), isLocalWLSServer(), and isLocalCluster() on each Detail.

The destination detail helps determine the actions that the caller should take. If the destination is of type DD_QUEUE, REPLICATED_DT, or PARTITIONED_DT then the detail's getJNDIName() method returns the JNDI name of a specific DD member and the caller may or may not want to deploy instances of the application consumer on the member. If the destination is of type PHYSICAL or FOREIGN, then the application treats the destination as a regular destination.

Especially when working with DDs, it is highly recommended that you take advantage of the co-location flags in DestinationDetail. You can determine the co-location nature of a destination by calling isLocalWLSServer(), and isLocalCluster(). See Best Practice for Local Server Consumers.

For more information about APIs and their methods, see DestinationDetail in Java API Reference for Oracle WebLogic Server.

Best Practices for Consumer Containers

The following sections provide best practice guidelines for consumer containers:

When to Register and Unregister
  1. Register with JMSDestinationAvailabilityHelper at application deployment time. Do not fail the deployment if the helper calls the onFailure() callback on your listener (assume it could be an intermittent failure).

  2. Unregister with JMSDestinationAvailabilityHelper at application undeployment time.

URL Handling
  1. If the client is running on the same server or same cluster as the destination, then don't specify a URL when registering with the helper or creating a JNDI context. This ensures that the helper creates a local context.

  2. Consider logging a single warning if isLocalCluster() or isLocalServer() returns true, but a URL was specified (as no URL is needed in this case).

Failure Handling
  1. Log the errors reported by onFailure() notifications, so that the application developer can have a chance to correct possible configuration/application errors. Avoid repeatedly logging the same exception. The helper continues to retry internally and make subsequent callbacks on success or different types of failures, but administrators may need to see the failures. The error may be caused by an application or administrative error such as an incorrect URL, invalid security information, or non-existent destination. It might also be caused by temporary unavailability of the JNDI context host or the destination.

  2. When a JMS call throws an exception, or when a JMS connection exception listener reports a connection failure, close the connection. Once all resources have been cleaned up, then periodically attempt to re-initialize all resources. Re-initialization generally involves creating a context, performing JNDI lookups, and then creating a connection, session, and a consumer.

  3. Avoid immediately retrying after a failure. Instead periodically retry every few seconds to avoid overloading the server.

JNDI Context Handling
  1. In general, avoid creating multiple JNDI initial context instances to the same server or cluster.

    Note:

    It may be necessary to use additional context instances to work around some security problems, especially in inter-domain scenarios.

  2. Call close() on a context on undeploy to prevent a memory leak.

  3. Call close() on a context and re create on any failure (including a lookup failure).

JMS Connection Handling
  1. For JMS connections, always register a standard JMS connection "exception listener".

  2. On an onException(), close the connection and periodically retry JNDI lookups, recreating a JMS connection, and setting up consumers in another thread.

  3. Close connections on undeploy to prevent memory leaks.

  4. Instead of sharing a WebLogic Server connection among multiple sessions, consider creating one connection per session. With WebLogic Server, multiple connections allow for better load balancing. There is no performance penalty when working with WebLogic Server, but this might have unexpected overhead with foreign vendors, because some foreign vendors create a TCP/IP socket or a similarly expensive resource for each connection.

Interoperability Guidelines

The JMSDestinationAvailabilityHelper in Java API Reference for Oracle WebLogic Server includes details about usage and behavior of the various methods available, including details about interoperability guidelines discussed in the following sections:

API Availability

The public JMS Destination Availability Helper API is available on AS11gR1PS2 (WebLogic Server version 10.3.3) and later clients and servers.

Foreign Contexts

The context properties that are specified when registering a notification listener with the DA Helper can resolve to any valid JNDI context, including contexts from foreign vendors and older versions of WebLogic Server.

For foreign (non-WebLogic) contexts, the foreign JNDI vendor's classes must be in the current classpath and the Context.INITIAL_CONTEXT_FACTORY property must reference the foreign vendor JNDI context factory class name.

Destination Type Support

The JMSDestinationAvailabilityHelper API works with any type of destination that can be registered in a JNDI context, including non-distributed destinations and foreign vendor destinations. However, unavailable notifications are only generated for DD members and certain DestinationDetail fields apply only to DD members. Unavailable notifications do not apply to foreign destinations.

Unavailable Notifications

Unavailable notifications only apply to DD type destinations (DQ_QUEUE, PARTITIONED_DT, REPLICATED_DT).

Interoperating with WebLogic Server 9.0 and Earlier Distributed Queues

When interoperating with a WebLogic Server 9.0 or later DDs, the DA Helper generates notifications for each individual member of the DD, when working with versions prior to 9.0, the helper only generates a single DestinationDetail notification which contains the logical JNDI name for the DD destination and getDestinationType() returns PHYSICAL.

WebLogic Server 9.0 and earlier DDs are usually treated as a regular destination, and consequently have the same limitations as outlined in Application Design Limitations When Using Replicated Distributed Topics.

Interoperating with WebLogic Server 10.3.4.0 and Earlier Distributed Topics

In releases prior to WebLogic Server 10.3.4, there are no features that enable unrestricted (non-exclusive) client IDs or shared subscriptions.

Note:

For information about how to configure unrestricted client-ids and shared subscriptions, see Configure an Unrestricted ClientID and Configure Shared Subscriptions in Administering JMS Resources for Oracle WebLogic Server.

To determine if a destination is a WebLogic 10.3.4.0 topic or later, ensure that the destination type is PHYSICAL_TOPIC, REPLICATED_DT or PARTITIONED_DT and not FOREIGN_TOPIC and that isAdvancedTopicSupported() returns true. A topic prior to WebLogic Server 10.3.4.0:

  • Will never be a PARTITIONED_DT.

  • PHYSICAL_TOPICs are usually treated as regular topics and are limited to one consumer per subscription.

Automatic attempts to durably subscribe to individual members of WebLogic 10.3.4.0 and earlier DT when a logical DT name is specified are not recommended. Oracle recommends that your applications do not support this option and log an error informing users that need durable subscriptions on a of WebLogic 10.3.4.0 and earlier DT to directly specify the JNDI name of a member instead of specifying the logical DT name.

When subscribing non-durably to a distributed topic prior to WebLogic Server 10.3.4.0, Oracle recommends creating a consumer on any single member JNDI name, or on the logical DR name, and ignoring all other notifications (one subscriber gets all messages sent to the DT and there can be only one consumer thread on the subscription).

DestinationDetail Fields

The behavior of some destination detail fields changes based on the type of destination, the JMS vendor, and, when working WebLogic JMS, the WebLogic Server version. See JMSDestinationAvailabilityHelper in Java API Reference for Oracle WebLogic Server.

Security Considerations

The following sections provide information about implementing security using the Java EE and WebLogic Server security models:

WebLogic Server Security Model

WebLogic Server credential propagation is thread based in most cases. The current thread credentials are established by specifying them when creating a JNDI context or application descriptor. These credentials are automatically propagated along with any RMI-based calls between JVMs including WebLogic JMS calls.

Passing Credentials Between Threads

The subject associated with a JNDI context is lost if the context instance is passed to and used in a different thread, which can cause security problems in some multi domain application scenarios. The following sections provide methods on passing credentials:

Using the Same Thread

If possible, you can avoid the issue by using the same thread to create the context, perform all JMS and JNDI operations, and close the context.

Pass as Anonymous User

Use an anonymous subject if the JMS destination and JNDI resources are not secured. In particular, when interoperating among multiple WebLogic domains, it is usually simplest to force all calls to use an anonymous subject if the JMS destination and JNDI resources are not secured. Non-anonymous credentials are typically only valid for a particular domain, leading to security exceptions if an attempt is made to use them for a different domain.

Cache and Reuse a Subject from the Initial Context

The following code provides an example of how to cache a subject and associate it with another thread using an anonymous user.

import java.security.PrivilegedExceptionAction;
import java.security.PrivilegedActionException;

import javax.security.auth.Subject;
import weblogic.security.Security;

 class MyClass {

 // don't make the cached subject public
  private Subject subject;

  MyClass() {
    subject = Security.getCurrentSubject();
  }

   void doSomething() {

 // run some operation as the subject on the original thread
     try {
       Security.runAs(subject,new PrivilegedExceptionAction() {
           public Object run()  throws Exception {
             //  do something;
             return null; // or return some Object
       }});
     } catch (PrivilegedActionException e) {
         // handle exception
     }
  }
}
When to Use Cross-Domain Security

Cross-Domain Security is a feature introduced in WebLogic Server 10.0 for establishing security across two or more WebLogic Server domains. WebLogic Server establishes a security role for cross-domain users and uses the WebLogic Credential Mapping security provider in each domain to store the credentials to be used by the cross-domain users. The cross-main security feature can be enabled on a per domain basis. A cross-domain credential mapping must be configured for each remote domain where internal communications needs to be secure. JTA, MDBs, and JMS are the three subsystems that depend on this feature. For more information about how to configure Cross-Domain security, see:

Authentication of Users

The following sections provide methods to provide the username and password when accessing JMS, which authenticates an application user, and also authorizes an application for JNDI and JMS operations.

Specifying Credentials for a JNDI Context

In order to access JMS resources, an application must have access to the JNDI provider. The credentials can be supplied when a application code creates an initial context to the JNDI provider. The thread that establishes the initial context carries the subject, and is therefore used for all sub sequential operations. When an application is running on a WebLogic Server and no server URL and security credentials are provided while creating an initial context, the thread continues to have the same credentials that were on the thread before the initial context was created. When the thread that creates an initial context closes the context, the thread will resume the original security credentials that are on the thread before creating the context.

Specifying Credentials for a JMS Connection

The ConnectionFactory.createConnection() call optionally supports a username and password. The credentials that are provided at the connection creation time do not have any affect with respect to security in JMS operations on the connection that is created (This is a WebLogic JMS specific behavior for WebLogic JMS Java clients, with the exception of the .NET client). The credentials are only be used to check, whether or not the user is a valid user in the domain where the connection is created.

Using Credentials of a Foreign JMS Server JNDI Context

Configure the Foreign JMS Server instance with JNDI Properties to gain access to the JNDI provider. The JNDI properties contain the options for setting the security principal and credentials.

Using Credentials of a Foreign JMS Server Connection

The user name and password that can be specified when configuring a Foreign Connection Factory mapping are ignored unless you use an EJB or Servlet resource reference to look up the JMS connection factory. See Improving Performance Through Pooling.

Securing Destinations

WebLogic JMS provides the ability to specify ACLs for destinations. This enables the destination to be secured and only authorized users are allowed to perform operations on that destination. See Java Messaging Service (JMS) Resources in Securing Resources Using Roles and Policies for Oracle WebLogic Server.

Securing Wire Data

When an application must protect JMS data passed on a wire, configure the network to use SSL. See Configuring SSL in Administering Security for Oracle WebLogic Server.

Transaction Considerations

WebLogic Server JTA transaction propagation is thread-based. The thread that starts a transaction should be the one that commits or rolls back the transaction. If there is a WebLogic JTA transaction on the current thread when you perform send or receive operations on a WebLogic JMS destination, then the JMS resources are automatically enlisted with the WebLogic transaction manager, and there is no need to perform your own enlistment.

You only need to do explicit "manual" enlistment when there is a need for WebLogic JMS resources to participate in a foreign or third-party transaction, or there's a need for a non-WebLogic destination to participate in a transaction. Enlisting with a foreign transaction manager (TM) is not directly supported on WebLogic JMS stand-alone clients. EJB and Servlet resource references enable automatic enlistment of non-WebLogic JMS vendors with the WebLogic TM.

Applications should not use transacted sessions if JMS operations are required to participate in a global XA— transaction. Global transactions require use of XA-based connection factories, while local transactions use non-XA based JMS connection factories.

Strategies for Uniform Distributed Queue Consumers

A consumer application can be either running in the same JVM of a WebLogic Server or not, which are called a "server side consumer" and "stand-alone consumer" respectively.

While a JMS UDQ consumer is deployed on a WebLogic Server or cluster, the application can either run on the same cluster/server as the UDQ, or on a different cluster. We call these two different application configurations the local case and the remote case respectively.

Note:

Oracle recommends using MDBs to implement advanced message distribution modes using replicated and partitioned distributed topics. For detailed information about advanced publish/subscribe application design using MDBs, see Developing Advanced Pub/Sub Applications and Configuring and Deploying MDBs Using Distributed Topics in Developing Message-Driven Beans for Oracle WebLogic Server.

For application that cannot use MDBs in their application architecture for some reason, the following guidelines should be followed:

General Strategies

In order to for an application to receive all the messages that are sent to a UDQ, the application must make sure that it creates one consumer on each member of the UDQ using the member JNDI name. This requires that applications know the topology of the domains and UDQ configuration, and this is where JMSDestinationAvailabilityHelper can help.

The general strategy is that each deployment instance of a particular application should register with JMSDestinationAvailabilityHelper. The listener will receive notifications about member availability.

  • Upon receipt of an onDestinationsAvailable() notification, the application gets a list of DestinationDetail instances for all available members, and then it must create one or more consumer instances using the member JNDI name for each member in the list. For remote consumers, each instance of the application should create a consumer on each member of the UDQ. For local consumers, the application should create a consumer on the local UDQ member only. See Best Practice for Local Server Consumers.

  • Upon receipt of an onDestinationsUnavailable() notification, the application gets a list of DestinationDetail instances for all destinations that becomes unavailable since the last notification. Then for each member destination in the list, the application must find the consumer previously created for the member destination and close it.

Best Practice for Local Server Consumers

An application should be deployed on the same server, group of servers, or cluster that host the UDQ whenever possible. Under this configuration, for best performance, the application should receive messages only from the local members; local members can be determined using the DestinationDetail isLocalWLSCluster() call if the servers are in a cluster or the isLocalWLSServer() call for individual servers or individual cluster members. This approach yields high performance because all messaging is local (it avoids transferring messages over network calls), and still ensures that all members are serviced by consumers.

In some use cases, the local server optimization network savings does not outweigh the benefit of distributing message processing for unbalanced queue loads across all JVMs in a cluster. This is especially a concern when message backlogs develop unevenly throughout the cluster, and message processing is expensive. In these use cases, the optimization should be avoided in favor of the general strategy model for remote consumers.

Strategies for Subscribers on Uniform Distributed Topics

Note:

Oracle recommends using MDBs to implement advanced message distribution modes using replicated and partitioned distributed topics. For detailed information about advanced publish/subscribe application design using MDBs, see Developing Advanced Pub/Sub Applications and Configuring and Deploying MDBs Using Distributed Topics in Developing Message-Driven Beans for Oracle WebLogic Server.

For all clustered and distributed applications that process messages from a UDT, Oracle recommends using product 10.3.4 or later topics in combination with the following settings:

  • Set the Client ID Policy to Unrestricted. See Configure an Unrestricted ClientID in Administering JMS Resources for Oracle WebLogic Server.

  • Set Subscription Sharing Policy to SHARABLE. See Configure Shared Subscriptions in Administering JMS Resources for Oracle WebLogic Server.

  • Use the JMSDestinationAvailabilityHelper API to get the notification of member availability

  • Always create subscribers on the member destinations.

WebLogic JMS has two types of Uniform distributed topics:

  • A replicated distributed topic (RDT) has forwarding capability among its members. As a result, each member of a RDT has a copy of all messages that are sent to the RDT.

  • A partitioned distributed topic (PDT) does not have forwarding capability among its members. As a result, each member of a PDT has its own copy of all messages that were sent to this particular member. This is a new type of DT introduced in WebLogic Server 10.3.4.0. See Configuring Partitioned Distributed Topics in Administering JMS Resources for Oracle WebLogic Server.

The following subsections discuss configuration requirements and programming patterns when using RDTs and PDTs:

One Copy Per Instance

The one copy per instance pattern ensures that each instance gets a copy of each message published to a topic. For example, if each instance is a JVM, then this pattern ensures that each JVM gets a copy of each message sent to the source topic. The following sections provide information on developing design patterns based on one copy per instance:

General Pattern Design Strategy for One Copy Per Instance

In order for the instances of a distributed application/container to receive messages that are sent to a DT in a one-copy-per-instance manner, each instance must do the following:

  1. Choose a base ClientID that will be shared by all connections and a durable subscription name that will be shared by all durable subscribers. The subscription name should uniquely identify your application instance. For example, if each instance runs on a differently named WebLogic Server JVM, then the subscription name for each instance could be based on the WebLogic Server name.
  2. Create JMS connections and sessions according to standard JMS specifications. The connection's ClientID should be set to the base ClientID appended by an identifier that is unique for this instance, For example, use the WebLogic Server name or the third-party application server that the application or container is running on. The ClientIDPolicy should be set to Unrestricted.
  3. Set the SubscriptionSharingPolicy to Sharable.
  4. Register with the JMSDestinationAvailabilityHelper for membership availability notifications, specifying the JNDI name of the DT.
  5. Set an Exception listener.
  6. Upon receipt of an onDestinationsAvailable() notification, create a subscriber on each newly available destination in the list. If the DT is a replicated DT, the subscriber must use a "NOT JMS_WL_DDForwarded" selector or prefix "(NOT JMS_WL_DDForwarded) AND" to the existing application provided selector.
  7. Upon receipt of an onDestinationsUnavailable() notification, close the corresponding consumer().
Best Practice for Local Server Consumers using One Copy Per Instance

An application should be deployed on the same server, group of servers, or cluster that hosts the UDT whenever possible. Under this configuration, the application needs follow the same steps as outlined in General Pattern Design Strategy for One Copy Per Instance except that it creates consumers only on local members. You can use the JMSDestinationAvailabilityHelper.DestinationDetail.isLocalWLSServer() call to determine if a member is local.

One Copy Per Application

The one-copy-per application pattern ensures that an application receives one copy of each message sent to a topic, even when the application is clustered across multiple JVMs. For example: If messages "A", "B", and "C" are sent to a topic, the messages are processed once by the application, instead of getting one-copy-per application instance.

The following sections provide information about developing design patterns based on one-copy-per application:

General Pattern Design Strategy for One Copy Per Application

In order for the instances of a distributed application/container to receive messages that are sent to a DT in a one-copy-per-application manner, each instance must do the following:

  1. Choose a base ClientID for all connections and the durable subscription name for all durable subscribers. The subscription name should uniquely identify your application instance. For example, if each instance runs on a differently named WebLogic Server JVM, the subscription name for each instance could be based on the WebLogic Server name then..
  2. Create JMS connections and sessions according to standard JMS specifications. The connection's ClientID should be set to the base ClientID. The ClientIDPolicy should set to Unrestricted.
  3. Set the SubscriptionSharingPolicy to Sharable.
  4. Register with the JMSDestinationAvailabilityHelper for membership availability notifications, specifying the JNDI name of the DT.
  5. Set an Exception listener.
  6. Upon receipt of an onDestinationsAvailable() notification, create a subscriber on each newly available destination in the list. If the DT is a replicated DT, the subscriber needs to use a "NOT JMS_WL_DDForwarded" selector or prefix "(NOT JMS_WL_DDForwarded) AND" to the existing application provided selector.
Best Practice for Local Server Consumers Using One Copy Per Application

An application should be deployed on the same server, group of servers, or cluster that hosts the UDT whenever possible. Under this configuration, the application must follow the same step outlined in General Pattern Design Strategy for One Copy Per Application except that it creates consumers only on local members. You can use the JMSDestinationAvailabilityHelper.DestinationDetail.isLocalWLSServer() call to determine if a member is local.