9 Best Practices for JMS Beginners and Advanced Users

Learn about the recommended and best practices for JMS beginners and advanced JMS users of Oracle WebLogic Server.

The following topics include targeting, integration options, understanding URLs, high availability (HA), and tuning for WebLogic Server:

Configuration Best Practices

Configuring a JMS application includes configuring persistent stores, JMS servers, JMS modules, and JMS resources within JMS modules. JMS resources within modules include JMS connection factories, JMS standalone destinations, or JMS distributed destinations. Configuring a SAF application is very similar except that it substitutes SAF Agents for JMS Servers and imported destinations for distributed destinations.

The following sections outline the basic procedure:

Configure JMS Servers and Persistent Stores

Before you start configuring JMS servers and persistent stores, consider the following:

  • Destinations, connection factories, and other JMS resources are configured separately from their host JMS servers and persistent stores. The best practice steps for configuring JMS resources will be described later.

  • WebLogic JMS distributed destination features require a working WebLogic cluster.

  • There are two types of clustered JMS configuration:

    • Cluster-targeted JMS servers and stores simplify configuration and high availability. With the store's Distribution Policy set to Distributed, instances are created on the cluster's running member servers, and uniform distributed destination members follow the JMS-server targeting. With Singleton, one service instance is placed within the cluster; increasing the cluster size does not create an instance on every member. Configure migration and restart policies separately. See Simplified JMS Cluster and High Availability Configuration.

      Note:

      Cluster-targeted JMS is the only available JMS option if you want to leverage WebLogic dynamic clusters instead of a configured cluster. See Simplified JMS Cluster and High Availability Configuration.

    • Individually configured JMS HA consists of a set of individually configured JMS servers and stores that are in turn targeted to migratable targets within a cluster. This option primarily exists for compatibility with earlier versions.

  • If you are not using a cluster, then you may want to reconsider and use a cluster of at least size one and use distributed destinations instead of standalone destinations. This helps “future-proof" your application for future HA and scaling support, as it ensures configuration and applications are easily capable of expanding to multiple servers. Leveraging a cluster is best done in very early configuration and application design stages as it is a difficult process to convert a non-clustered application and configuration into a clustered topology.

Note:

For high availability and scaling, Oracle recommends targeting the JMS artifacts to a cluster along with appropriate high availability configuration settings instead of using migratable targets.

Use the following steps to configure JMS servers and persistent stores in a cluster.

Steps for setting up cluster-targeted JMS:

  1. Create a custom store and target it to the cluster. Set Distribution Policy to Distributed for JMS servers hosting uniform distributed destinations, or Singleton for a JMS server hosting standalone destinations. To enable automatic migration, configure the store's Migration Policy as On-Failure or Always, as appropriate for the required placement behavior, and configure cluster leasing. Singleton JMS configurations require one of these migration policies. Migration Policy defaults to Off; merely targeting a store to a cluster does not enable migration. See Simplified JMS Cluster and High Availability Configuration and Ensure Your Data is Persisted Safely.

  2. Configure a JMS server and target it to the same cluster, plus configure the JMS server to reference the store that was created in step 1. Multiple JMS servers can reference the same store.

Steps for setting up individually configured JMS in a cluster:

  1. Create a custom store on each WebLogic server in the cluster. Target each store to the default migratable target on its server or to a custom migratable target. See Service Migration in Administering Clusters for Oracle WebLogic Server. Ensure the store is configured to persist your data safely as described in Ensure Your Data is Persisted Safely.

    Note:

    Use a custom persistent store for a JMS service that must migrate independently between WebLogic Server instances, and target the JMS server and its store to the same migratable target. The default file store is associated with its WebLogic Server instance and is not an independently migratable JMS custom store. Whole-server migration and transaction-log recovery have separate storage-access requirements. See Ensure Your Data is Persisted Safely and Service Migration in Administering Clusters for Oracle WebLogic Server.

  2. Configure a JMS server on each WebLogic server. Configure the JMS server to reference the store for the server that was created in step 1. Target the JMS server to the same target that was used for the store. Multiple JMS servers can reference the same store.

Configure JMS Quotas and Paging

Configure finite message-count and byte quotas appropriate for the JMS server's expected backlog and available resources. Paging reduces the memory occupied by message contents, but retained messages still require kernel metadata and other memory. Large backlogs can therefore exhaust heap even when most message contents have been paged out. Size quotas using measurements from representative message sizes, properties, consumers, transactions, and backlog conditions, with capacity reserved for the rest of the server's workload.

Note:

Byte quotas account for message storage size; they are not a limit on total JVM heap usage. Treat per-message memory estimates as sizing aids rather than a guaranteed footprint. Monitor both message count and memory usage when validating the limits.

Although JMS paging is enabled by default, verify that the default behavior is valid for your environment. See Paging Out Messages To Free Up Memory in Tuning Performance of Oracle WebLogic Server.

Configure a JMS Module

A JMS module encapsulates JMS connection factory and destination configuration. It is a best practice to configure a system module and system module subdeployment for each homogeneous set of JMS servers within a cluster. This maintains a simple one to one correspondence between JMS module resource configuration, JMS module subdeployment, and JMS server configuration.

A homogeneous set of JMS servers is either:

  • A single cluster-targeted JMS server with its store’s distribution-policy set to Distributed.

  • A single cluster-targeted JMS server with its store’s distribution-policy set to Singleton.

  • A set of one or more individually configured JMS servers.

Different JMS configurations can co-exist in the same cluster scope as long as they use different configuration names and different JNDI names.

Specifically:
  1. Create a system module. Target it to a single cluster (if using clusters) or a single WebLogic Server instance. You must always target the module even when leveraging subdeployments.

    Note:

    Oracle recommends JMS system modules when administrators need to manage JMS resources independently of application deployment. System modules provide WebLogic configuration and targeting controls. WebLogic JMS application modules are a separate, deprecated deployment option. Standard Jakarta Messaging resource definitions, expressed through annotations or deployment descriptors, remain another option for application-defined resources; their standard elements support portability, while provider-specific properties and external provisioning requirements can limit it. See JMS Resource Definition Elements Reference and Configuring JMS Application Modules for Deployment (Deprecated).

  2. For this recommended layout, use one destination subdeployment per module to keep targeting easy to understand. If resources need different sets or types of targets, create a separate module and subdeployment for each compatible target group. This is a configuration convention, not a product limit of one subdeployment per module.
  3. Populate the subdeployment only with the JMS servers contained in the ‘homogeneous set of JMS Servers` above (this will be a single JMS Server in a simplified cluster-targeted JMS configuration). Do not reference WebLogic Servers or a cluster in the subdeployment. Only include the JMS servers that you wish to host destinations. This ensures that when the JMS resources are configured in the next step below, they are targeted to the correct JMS servers. For modules that support non-distributed destinations, the subdeployment must only reference a single individually-configured JMS server, or a single cluster-targeted JMS server that references a store with its distribution-policy set to Singleton. For modules that support distributed destinations, always choose a single cluster-targeted JMS server with its distribution-policy set to Distributed, or a homogeneous set of individually-configured JMS servers.
If you have a mix of distributed and non-distributed destinations, use two modules each with its own subdeployment.

Configure JMS Resources

Configure your JMS resources and target them properly.

  1. Create destinations and assign each to the subdeployment for its intended hosts, using advanced targeting. For ordinary standalone queues/topics, select one eligible JMS-server instance; for uniform distributed destinations, select the compatible JMS-server configuration described in Configure a JMS Module. Target SAF imported-destination groups separately to eligible sending SAF agents. If an application uses distributed destinations, standalone destinations and SAF imported destinations, use a separate module/subdeployment for each required target group; do not assume that two modules can represent every combination. See Targeting Best Practices.
  2. Create and use custom connection factories instead of using default connection factories. Default connection factories are not tunable.

    In most cases, you can use default targeting with connection factories as default targeting causes the resource to inherit the module's target. For connection factories that are only used by remote clients, use the module's subdeployment target.

  3. On each server hosting the application, or its server template where applicable, consider setting JMSConnectionFactoryUnmappedResRefMode to FailSafe when an unresolved application connection-factory reference should fail rather than fall back to the platform default factory. This is a server setting, not an attribute of an individual connection factory. In FailSafe mode, an otherwise unmapped reference can still resolve an object with the same JNDI name; if none exists, lookup fails with javax.naming.NameNotFoundException. The default ReturnDefault policy may return java:comp/DefaultJMSConnectionFactory after its name-resolution checks. Explicitly map application references to the intended connection factories.
    For more information about setting the unmapped resource reference mode, see Specifying the Unmapped Resource Reference Mode for Connection Factories.

Configure SAF Agents, Stores, and Imported Destinations

Apply the same principles of explicit targeting, persistence, quotas and high availability to SAF. Target imported-destination groups to the sending SAF agents intended to forward their messages, rather than to JMS servers. A sending agent must support Sending-only or Both service. For a cluster-targeted SAF agent, its store must use Distribution Policy Distributed; do not copy the Singleton JMS-server example to a SAF agent. See Simplified JMS Cluster and High Availability Configuration and Administering the Store-and-Forward Service.

Targeting Best Practices

Oracle recommends certain targeting guidelines for JMS resources.

They are:

  • Avoid default targeting, WebLogic server targeting, and cluster targeting with destinations. Instead use advanced targeting (subdeployment targeting) for destinations and ensure that the subdeployment references only JMS servers or SAF agents. This applies to all destination types, including non-distributed, distributed, and imported.

    Even if the current JMS Servers or SAF Agents in your domain are only used for your specific application, this is a best practice because:

    • New JMS Servers or SAF Agents that are unrelated to your current application can be introduced by other applications, web services, or 3rd-party products.

    • In the future, your application may require different destinations and different JMS Servers or SAF Agents for scalability or management purposes.

  • Always use advanced targeting when configuring Web Services deployments and error queues, this includes both development and production environments.

  • To use an error destination within a distributed queue, it must be targeted to the same subdeployment as its parent destination.

  • In most cases, you can use default targeting with connection factories as default targeting causes the resource to inherit the module's target. For connection factories that are only used by remote clients, use the module's subdeployment target.

High Availability Best Practices

Learn some of the best practices to achieve and leverage high availability features in WebLogic Server.

This section includes the following topics:

Develop Applications on a Cluster

To achieve High Availability (HA), develop applications that leverage clustered WebLogic features and use a cluster during development. This approach is best taken in the early configuration and application design stage as it is a difficult process to change a non-clustered application into a clustered application.

Leverage WebLogic HA Features

In WebLogic JMS, a sent message is only available to consumers if the message’s host JMS server instance is running. Even if a message is stored on a shared file system or database, or in a distributed destination, the only JMS server instance that can recover a message is the same instance that originally stored the message. For example, if a message is sent to a distributed queue hosted on multiple JMS server instances, then the message will be internally load balanced to exactly one of these instances and stored in that particular instance, and, if that instance later crashes, the message will not be available to consumers until the instance is restarted.

To restore message availability after a failure, WebLogic includes features for automatically restarting and/or migrating an entire WebLogic Server JVM. It also includes features for restarting a JMS server and store instance within a JVM or migrating the instance to a different JVM within the same cluster after a failure. Finally, it includes features for clustering (distributing) a destination across multiple JMS servers within the same cluster. A distributed destination helps high availability because even if some of the destination’s stored messages are unavailable while they wait for their failed JMS server and store to restart or migrate, other messages for the logical destination can still be produced and consumed via a running JMS server.

HA is normally accomplished using a combination of:

  • WebLogic Clustering (Dynamic or Configured Clusters). See Understanding WebLogic Server Clustering in Administering Clusters for Oracle WebLogic Server.

  • Whole server migration and/or restart. See Whole Server Migration in Administering Clusters for Oracle WebLogic Server.

  • WebLogic JMS server and store Restart In Place. See Service Restart In Place in Administering the WebLogic Persistent Store.

  • JTA Service Migration between JVMs in a cluster (since JMS applications often leverage transactions). See Service Migration in Administering Clusters for Oracle WebLogic Server.

  • JMS Service Migration between JVMs in a cluster. See Service Migration in Administering Clusters for Oracle WebLogic Server.

  • Cluster leasing. Automatic service migration and automatic whole server migration both required setting up cluster leasing. It is a best practice to configure database leasing instead of cluster leasing. See Leasing in Administering Clusters for Oracle WebLogic Server.

  • Distributed destinations. See Using Distributed Destinations in Developing JMS Applications for Oracle WebLogic Server.

Ensure Your Data is Persisted Safely

  • If you are using file stores, ensure the files are located on highly available storage (such as RAID), and are centrally accessible from any machine in a cluster (via SAN, etc) or from any machine that might host a WebLogic Server after a whole server migration, so that file data can be recovered after a failure. Default file stores similarly also need to be highly available and centrally accessible if JTA is not using a JDBC TLog Store since transaction logs are stored in default file stores by default. See File Locations and Additional Requirement for High Availability File Stores in Administering the WebLogic Persistent Store.

    Note:

    It is important to explicitly configure the directory of a custom or default file store when ensuring the file store uses a central directory location. Otherwise, the file store may recover its data using a directory location based on the current WebLogic Server name, and so could recover from an incorrect directory if it moves between WebLogic Servers.

  • Note that paging and cache files do not need high availability and should be located on local file systems for performance reasons.

  • If you are using custom database stores, transaction log JDBC stores, or cluster database leasing, then ensure their database tables are located on a highly available database solution such as Oracle RAC.

  • If you have a Disaster Recovery solution that leverages async replication of data, then file base storage is not usually recommended. Instead, Oracle strongly recommends that all JMS and JTA data be stored on the same database as any applications that perform a combination of messaging and database operations. This ensures that your recovered messages and data stay synchronized even after a disaster recovery. See Using a JDBC Store and Using a JDBC TLog Store in Administering the WebLogic Persistent Store.

Client Resiliency Best Practices

Ensuring JMS resiliency generally requires attention in two main areas: infrastructure level resilience and JMS application resilience.

The first area is infrastructure level resilience, which is generally addressed via configuration and encompasses persistence, leveraging clusters, JVM Migration, and Service Migration as described above in High Availability Best Practices. The second area is JMS application resilience, which is generally addressed via coding best practices that apply to any JMS Provider (not just WebLogic JMS) and is described below.

After an unrecoverable failure of application-managed JMS resources, close the connection or JMSContext that the application owns, clean up any application-created JNDI context, and recreate the connection/session or JMSContext and its producers or consumers as needed. Refresh connection-factory and destination lookups when their bindings may have changed. Complete the appropriate transaction/error handling before deciding whether to repeat the business operation. Do not apply this lifecycle recipe to an injected, container-managed JMSContext: the application must not call close() on it or attempt to recreate the injected object. Let the container manage its lifecycle and follow the applicable transaction and component error-handling rules.

Exception handling in server-side applications is usually simplified by taking advantage of JMS asynchronous containers or pooling:

  • In server-side applications, use the container's supported resource-reference and JMSContext-injection facilities for connection/session management. For resources created by the application through a pooled factory, acquire the handles for the unit of work and close the application-owned handles when finished so that the pool can reuse or replace the underlying resources. An injected JMSContext is managed by the container and must not be closed by application code. Pooling reduces resource-creation overhead; it does not make replay of a business operation automatically safe. See Enhanced Support for Using WebLogic JMS with EJBs and Servlets in Developing JMS Applications for Oracle WebLogic Server.

  • Error handling for asynchronous ‘onMessage’ server side messaging is generally best handled by leveraging WebLogic MDB containers, or a JMS JCA Adapter from your framework if MDBs are not options. These containers will automatically handle failures and retry as needed. See Developing Message-Driven Beans for Oracle WebLogic Server for more information.

For an application-managed asynchronous consumer outside a Jakarta EE web or Enterprise Beans container, register a jakarta.jms.ExceptionListener on its Connection or JMSContext to receive asynchronous connection-failure notifications through onException(JMSException). Use Connection.setExceptionListener(ExceptionListener) or JMSContext.setExceptionListener(ExceptionListener), as appropriate. Applications in Jakarta EE web or Enterprise Beans containers must not set their own connection exception listeners; use the container's messaging and error-handling facilities. An injected JMSContext rejects setExceptionListener() with jakarta.jms.IllegalStateRuntimeException.

Note:

  • A send rejected because a WebLogic message quota is exhausted does not by itself require recreating otherwise usable JMS client objects. The classic API reports this through jakarta.jms.ResourceAllocationException; the simplified API uses jakarta.jms.ResourceAllocationRuntimeException. Handle the capacity condition and use controlled retries when appropriate. Examine the exception details and transaction state: a resource-allocation exception can describe a resource limit, and the class name alone is not a complete recovery policy for every provider or failure.

  • Applications should avoid retrying operations in a tight loop in order to avoid performing relatively expensive create operations too frequently. This is because almost all failures do not resolve immediately, and frequently destroying and creating JMS client objects such as JNDI contexts, connections, sessions, producer, and consumers in the interim can be relatively far more expensive in comparison to normal runtime operations like sending or receiving a message. In short, tight-loop-retries can consume far more resources than other operations. Oracle recommends a single immediate retry attempt, and then progressively longer intervals between retries of up to a maximum of at least a few seconds.

  • It is a highly recommended best practice to pool or cache JMS resources. To simplify error handling, it is tempting to ignore this advice and write applications that always create a new JMS connection, session, etc for each JMS message. But if these items are not pooled or cached, then this approach is not recommended for the same costly reasons that are described above for a tight loop retry. Some messaging applications may see a 5X or more performance hit. If pooling is not available, Oracle recommends caching JMS objects in your application for re-use.

  • Interpret a successful return according to the operation's contract. A send in a transaction is not committed until that transaction commits. For an asynchronous send, where permitted, use its CompletionListener result to determine send completion. A communication failure during send or commit can leave the outcome uncertain: the server may have completed the operation even though the client did not receive its response. Recreating client objects does not resolve that uncertainty. Before retrying the business operation, account for possible duplicates, for example by using an application operation identifier and idempotent processing. A definite rollback indication should be handled as a rollback; do not treat every exception as an unknown outcome.

  • The WebLogic JMS connection-factory reconnect settings and the corresponding reconnect methods on weblogic.jms.extensions.WLConnection and weblogic.jms.extensions.WLJMSContext are deprecated and disabled by default in this release. They do not replace application recovery and cannot handle every failure. Use the resource-lifecycle and retry guidance in this section when an operation fails.

Distributed Destination Best Practices

Applications that use distributed destinations are more highly available than applications that use simple destinations because WebLogic JMS provides load balancing and failover for member destinations of a distributed destination within a cluster.

Distributed Queues

Distributed queues are fairly easy to apply to an arbitrary clustered queueing use case, and easiest to apply when using MDBs, the SOA JMS Adapter, or OSA Adapter to consume from them. The MDB and adapter options automatically ensure that all distributed destination members are serviced by consumers. In addition, these containers are resilient to failures, and generally provide a proven and simple way for securing and multi-threading consumer applications regardless of destination type.

Distributed Topics

Distributed Topics are best applied when you use MDBs, the SOA JMS adapter, or the OSA JMS adapter to subscribe since direct subscribers have limitations and may require use of sophisticated extensions. The MDB and adapter containers automatically setup subscriptions and consumers for you.

Distributed Topics are recommended to be setup up as “Partitioned Distributed Topics” (a type of Uniform Distributed Topic) instead of “Replicated Distributed Topics”. This is because PDTs tend to be more scalable and fully supported in all advanced features, while RDTs are not supported in a dynamic cluster, WebLogic Multi-Tenant, or cluster-targeted JMS configuration. A PDT is a Uniform Distributed Topic that has its forwarding-policy configured to be partitioned instead of replicated. If you are already using RDTs, consider replacing them with PDTs.

See Configuring and Deploying MDBs Using JMS Topics in Developing Message-Driven Beans for Oracle WebLogic Server, Using Distributed Destinations, and Replacing an RDT with a PDT in Developing JMS Applications for Oracle WebLogic Server.

Weighted Distributed Destinations

Oracle strongly recommends using Uniform Distributed Destinations in place of Weighted Distributed Destinations. Weighted Distributed Destinations are deprecated and were superseded by Uniform Distributed Destinations as of WebLogic Server 9.0. Weighted Distributed Destinations are not supported in dynamic cluster, WebLogic Multi-Tenant, or cluster-targeted-JMS configurations.

Understanding WebLogic JMS Client Options

For client applications that have a runtime environment independent of WebLogic Server, there are multiple JMS client options, including: Java, .NET, and C clients. See JMS Clients in Developing Stand-alone Clients for Oracle WebLogic Server.

Note:

WebLogic JMS clients do not directly support foreign transaction managers. Use the WebLogic TM if possible. For advanced users, the transaction subsystem Interposed Transaction Manager feature may be used as an XA resource. See Participating in Transactions Managed by a Third-Party Transaction Manager in Developing JTA Applications for Oracle WebLogic Server.

Understanding WebLogic URLs

Applications that are communicating with a remote WebLogic Server instance or cluster must specify a URL when creating their JNDI InitialContext objects and/or setting application attributes in order to connect to a server or a cluster.
  • Do not specify URLs for applications that run on the same server or cluster as their JMS resources. When an initial context is created without specifying URLs, it automatically references the local server or cluster JNDI.

  • If a URL resolves to multiple addresses, WebLogic Server clients will randomly select an address in the list to start with and then automatically try each address in turn until one succeeds.

  • In production systems, consider using DNS round robin or a hardware load balancer for initial hostname resolution rather than using the multiple host/port URL notation shown in URL syntax.

Note:

JMS connection factories are obtained from JNDI; however, by default, they load balance their connections independently of the JNDI context address. A JMS connection factory normally load balances across the servers included in the JMS connection factory's configured target. Similar to an EJB reference, a JMS connection factory is a 'smart stub' that contains a list of server addresses implicitly obtained from domain configuration and implicitly updated as a cluster grows and shrinks. This means that even if a JNDI context's URL only references a single server in a cluster, and a cluster-targeted or default targeted connection factory is obtained from this JNDI context, the JMS connections will still load balance across the entire cluster.

URL syntax

Learn about the WebLogic URL syntax and how it must be used to construct a URL for an application.

The WebLogic URL syntax is:

[t3|t3s|http|https|iiop|iiops]://address[,address]...

Where

  • address = hostlist : portlist

  • hostlist = hostname [,hostname]...

  • portlist = portrange [+portrange]...

  • portrange = port [-port]

Use port-port to indicate a port range, and + to separate multiple port ranges. For example, a simple address is typically something like t3://hostA:7001; the address t3://hostA,hostB:7001-7002 is equivalent to the following addresses.

  • t3://hostA,hostB:7001+7002

  • t3://hostA:7001-7002,hostB:7001-7002

  • t3://hostA:7001+7002,hostB:7001+7002

  • t3://hostA:7001,hostA:7002,hostB:7001,hostB:7002

Strict Message Ordering Best Practices

Oracle recommends using the WebLogic JMS Unit-of-Order feature when strict message delivery ordering is required. UOO is the simplest and most capable strict delivery ordering option, and it supports parallel consumption of different orderings within the same destination. Normally it requires minimal or even no changes to applications, and it is resilient to any type of failure. In addition, it works with distributed destinations, scheduled messages, delayed messages, transactions, and store-and-forward.

Note that when using JMS Unit-of-Order in combination with a distributed destination or SAF imported destination, Oracle recommends configuring the destination’s unit-of-order routing policy to the Path Service option and configuring a Path Service for the cluster. The Path Service option preserves orderings even when new members are configured for the distributed destination, and is the only supported policy in a cluster-targeted JMS configuration.

See Using Message Unit-of-Order in Developing JMS Applications for Oracle WebLogic Server.

If strict messaging ordering is needed and the Unit-of-Order feature cannot be leveraged, see Ordered Redelivery of Messages in Developing JMS Applications for Oracle WebLogic Server.

Integrating Remote JMS Destinations

To integrate remote JMS destinations into a local WebLogic Server or WebLogic Cluster, it is a best practice to configure a Foreign JMS Server mapping in order to map remote JMS destination and connection factory JNDI names into the local standalone server JNDI or local cluster JNDI namespace. The destinations that can be mapped include remote WebLogic JMS destinations, Oracle AQ JMS destinations, and non-Oracle JMS destinations.

Furthermore, another best practice is to use Foreign JMS Server mappings in combination with MDBs, res-ref or context injection JMS pools, or Messaging Bridges. These components use the mapping plus any security credentials configured in the Foreign JMS Server to access remote JMS resources.

Alternatively, consider using WL JMS SAF agents to forward remote WebLogic JMS messages into a local server or cluster.

See FAQs: Integrating Remote JMS Providers in Developing JMS Applications for Oracle WebLogic Server.

JMS Performance and Tuning

See the following checklist of items to consider when tuning WebLogic JMS.

JMS Performance & Tuning Check List in Tuning Performance of Oracle WebLogic Server.