Skip Headers
Oracle® Containers for J2EE Services Guide
10g (10.1.3.5.0)

Part Number E13975-01
Go to Documentation Home
Home
Go to Book List
Book List
Go to Table of Contents
Contents
Go to Index
Index
Go to Feedback page
Contact Us

Go to previous page
Previous
Go to next page
Next
View PDF

4 Using Oracle Enterprise Messaging Service

The Oracle Enterprise Messaging Service (OEMS) provides a robust messaging platform for building and integrating distributed applications. It provides the framework for Oracle's messaging and message integration solutions.

The following key features make up OEMS:

All of these areas are covered in this chapter. The only OEMS feature not covered here is MGW, which is documented in the Oracle Streams Advanced Queuing User's Guide and Reference document.

Note:

In past releases, Oracle has used the terms "OracleAS JMS" and "OJMS" when describing the In-Memory, File-Based, Database persistence options. "OracleAS JMS" referred to the In-Memory and File-Based options while "OJMS" referred to JMS interface to Streams Advanced Queuing (AQ).

To avoid any confusion regarding JMS, the "OracleAS JMS" and "OJMS" nomenclature will not be used. The "OEMS JMS" reference will be used instead. This reflects the fact that Oracle offers a single JMS interface to the three message persistence options. Your JMS application code will not have to change if you decide to change message persistence between any of the three quality of service choices.

This chapter discusses the following topics:

JMS Tasks

This chapter discusses the following JMS tasks:

New JMS Features

The following OC4J JMS features and behaviors are new for this release:

About JMS

Java clients and Java middle-tier services must be capable of using enterprise messaging systems. Java Message Service (JMS) offers a common way for Java programs to access these systems. JMS is the standard messaging API for passing data between application components and allowing business integration in heterogeneous and legacy environments.

Before reading this chapter, you should be familiar with the basics of JMS and the JMS API. For basic information about JMS, including tutorials and the API documentation, visit the Sun Microsystems Web site at:

http://java.sun.com/products/jms/index.jsp

JMS provides two messaging domains, each associated with a JMS destination type, and a domain-specific set of Java interfaces:

JMS destination objects are bound in the JNDI environment and made available to J2EE applications.

In addition to providing two sets of messaging interfaces, one for each messaging domain, JMS (starting with JMS 1.1) also provides a set of common interfaces for implementing domain-independent application code. This set of common interfaces maintains the distinct behavior of the two messaging domains (where the behavior is governed by the messaging domain used, as associated with the JMS destination type), while providing common programming interfaces for both messaging domains. The interfaces belonging to this set of common interfaces, as well as how they relate to the domain-specific interfaces, are detailed in Table 2-1 in the JMS 1.1 specification document.

Backward Compatibility

Oracle recommends that newer JMS applications be deployed using the JMS Connector, which is based on the J2CA 1.5 specification and mandated by the J2EE 1.4 standard. This path provides the new features introduced in OracleAS. However, Oracle will continue to support JMS applications deployed using the older proprietary OC4J Resource Provider supported in previous versions of OracleAS.

The Oracle JMS Connector is discussed in the "JMS Connector" section starting.

JMS How-To Documents and Demo Sets

How-To documents and a set of examples, including commented configuration files, are available at the How-To Web site: http://www.oracle.com/technology/tech/java/oc4j/1013/how_to/index.html

The JMS documents and demo sets are listed under the Messaging (JMS) heading. The documents and deployment descriptor files in the demo set are organized by resource provider and include the configuration variations called for by the various supported resource providers. Unzip the files that apply to the relevant resource provider.

JMS Configuration Overview

This section gives an overview of the following JMS configuration topics:

This OEMS document and the associated demos and How-To documents describe using the JMS Connector with the various supported resource providers, with emphasis on the OEMS JMS In-Memory and File-Based persistence options.

JMS Configuration Sequence

This section outlines preparing the following components for JMS operation:

You can, but are not required to, create matching sets of connection factories and destination objects, one set on the resource provider and the matching set on the JMS Connector. Alternatively, you can use "automatic destination wrapping" to avoid having to make a matching set of JMS Connector destinations.

Developing and Assembling the Application

The tasks for developing and assembling your application to use JMS messaging are as follows:

  • Write Code to Send and Receive Messages

  • Declare Logical Names for JMS Resources

  • Use Logical Names for JMS Resources

  • Create and Declare an MDB Class

  • Declare Message Destinations

  • Link to Message Destinations

  • Define the onMessage Transaction Attribute

  • List the Application Modules

For details, see the How-To documents included in the demo set. For a list of the How-To documents and demo sets and their URLs, see "JMS How-To Documents and Demo Sets".

Configuring the Resource Provider

Configuring the resource provider usually requires several rounds, arising out of the need for application component developers and application assemblers to have some connection factories and destinations to use for development. The development connection factories and destinations are often not the same connection factories and destinations used for deployment (since the development servers and production servers are often separate machines, and may be configured using different organization strategies, and may even use different resource providers). This document focuses on the production deployment.

When configuring a resource provider, you have to decide the following:

  • How many and what type of resource provider connection factories will be needed to satisfy the application.

  • How many and what type of resource provider destinations are needed to satisfy the application.

  • Create RP Connection Factories

  • Create RP Destinations

  • Declare a Resource Provider Reference

See the How-to documents in the demo set for details. For a list of the How-To documents and demo sets and their URLs, see "JMS How-To Documents and Demo Sets".

Configuring the JMS Connector

The introduction of the JMS Connector functionality in OEMS provides some degree of insulation from the specifics of the various resource providers. Based on the J2CA 1.5 specification, the JMS Connector acts as a compatibility layer and a value-added wrapper for the resource provider.

The tasks for configuring the JMS Connector are as follows:

  • Settings in ra.xml.

  • Create a JMS Connector Instance

  • Create JMS Connector Connection Factories

  • Create JMS Connector Destinations

For details, see the How-To documents included in the demo set. For a list of the How-To documents and demo sets and their URLs, see "JMS How-To Documents and Demo Sets".

Additional Information and Examples

For detailed examples of the oc4j-connectors.xml, the oc4j-ra.xml, and the ra.xml files, go to: http://www.oracle.com/technology/tech/java/oc4j/1013/how_to/index.html

For detailed reference information on the JMS Connector XML files, go to Appendix A, OC4J Resource Adapter Configuration Files of the Oracle Containers for J2EE Resource Adapter Administrator's Guide.

The following links point to the document "How to Configure and Use Oracle's Generic JMS Resource Adapter with OracleAS JMS" and to the ZIP file containing the corresponding set of demo files. In these documents, the term "Generic JMS Resource Adapter" refers to the JMS Connector.

JMS Configuration File Structure

This section points out the consistencies that must exist between the connection-factory and destination references and definitions in the JMS configuration files. Figure 4-1, "JMS Configuration" illustrates the references and definitions that must agree with each other.

Figure 4-1 JMS Configuration

The figure shows JMS mappings for configuration files.

Figure 4-1 depicts the various types of links between the java source code, the application deployment descriptors, the resource adapter deployment descriptors, and the resource provider. At the tail of each arrow is a "link-reference", and at the head of each arrow is the "link-key" (name, JNDI location or Java interface) of the item being referenced. The textual representation of the link-key at the head and link-reference at the tail of any given arrow is always identical except where otherwise noted.

The files are:

  • ra.xml

  • oc4j-ra.xml

  • application.xml

  • orion-application.xml

  • oc4j-connectors.xml

  • ejb-jar.xml

  • orion-ejb-jar.xml

  • application-client.xml

  • orion-application-client.xml

  • web.xml

  • orion-web.xml

The demo set includes expanded explanations of the relationships depicted in Figure 4-1, "JMS Configuration". For a list of the How-To documents and demo sets and their URLs, see "JMS How-To Documents and Demo Sets".

Download and unzip the relevant How-To-gjra-with-xxx.zip file, where xxx is the name of the relevant resource provider.

Open the relevant how-to-gjra-with-xxx.html document. The explanations in this section point to the section in the how-to document that explains the relationship.

The demo set also includes examples of Java code and deployment descriptor XML files.

Java Source Code

In J2EE applications, Java source code typically uses logical names to reference JMS resources. Logical names (references declared with <resource-ref> and <message-destination-ref> elements) are types of environment entries, and all environment entries are placed in the java:comp/env/ JNDI subcontext. For details, see "Application Component Provider Task #3: Use Logical Names for JMS Resources" in the relevant How-To document.

Figure 4-1 depicts the two types of links from the Java source code to the J2EE application component deployment descriptors. The number of each description in the following list corresponds to a numbered link in the figure.

  • 1 - The first link in a typical outbound connection factory "chain" is from the Java source code to a <resource-ref> element in a J2EE application component deployment descriptor. The link-reference is the location used in the JNDI lookup to obtain the JMS connection factory and must include the java:comp/env prefix. The link-key for a <resource-ref> element is the value of its <res-ref-name> subelement and must not include the java:comp/env prefix. Except for the java:comp/env prefix, the link-reference and link-key should be identical.

  • 2 - The first link in a typical outbound destination chain is from the Java source code to a <message-destination-ref> element in a J2EE application component deployment descriptor. The link-reference is the location used in the JNDI lookup to obtain the JMS destination and must include the java:comp/env prefix. The link-key for a <message-destination-ref> element is the value of its <message-destination-ref-name> subelement and must not include the java:comp/env prefix. Except for the java:comp/env prefix, the link-reference and link-key should be identical.

J2EE application component deployment descriptors (application-client.xml, ejb-jar.xml, web.xml)

The logical names used by the Application Component Providers have a many-to-one relationship with physical destinations. The Application Assembler creates logical destinations which have a one-to-one relationship with physical destinations. The Application Assembler then needs to link the message destination references and MDBs created by the Application Component Providers to the message destinations created by the Application Assembler. This is done by adding <message-destination-link> elements that name the appropriate message destination. These links are not part of the destination chain, but instead provide information needed by the Deployer to complete the destination chain. For details, see "Application Assembler Task #2: Link to Message Destinations" in the relevant how-to-gjra-with-xxx.html document, where xxx is the name of the relevant resource provider.

Figure 4-1 depicts the two types of links fully contained within the J2EE application component deployment descriptor:

  • 3 - For outbound messaging, this informational-only link is from a <message-destination-ref> element to a <message-destination> element, both in J2EE application component deployment descriptors (though not necessarily the same one). The link-reference is the value of the <message-destination-link> subelement. The link-key for a <message-destination> element is the value of its <message-destination-name> subelement. The link-reference may be prefixed with the name of the file containing the link-key followed by a # character. (This is only needed when different link-keys from different files happen to have the same exact value.) Except for the optional prefix, the link-reference and link-key should be identical.

  • 4 - For MDB/inbound messaging, this informational-only link is from a <message-driven> element to a <message-destination> element, both in J2EE application component deployment descriptors (though not necessarily the same one). The link-reference is the value of the <message-destination-link> subelement. As previously mentioned, the link-key for a <message-destination> element is the value of its <message-destination-name> subelement. The link-reference may be prefixed with the name of the file containing the link-key followed by a # character. (This is only needed when different link-keys from different files happen to have the same exact value.) Except for the optional prefix, the link-reference and link-key should be identical.

OC4J-specific application component deployment descriptors (orion-application-client.xml, orion-ejb-jar.xml, orion-web.xml)

Figure 4-1 depicts the following seven types of references from the OC4J-specific application component deployment descriptor:

  • Application components declare logical names for connection factories in J2EE application component deployment descriptors. The deployer then maps those logical names to JMS Connector connection factories.

    For details and examples, see "Deployer Task #1: Map Logical Connection Factories to RA ConnectionFactories" in the relevant How-To document.

    The figure depicts the two types of connection factory links provided by the <resource-ref-mapping> element.

    • 6 - The second link in a typical outbound connection factory chain is from a <resource-ref-mapping> element in an OC4J-specific application component deployment descriptor back to a <resource-ref> element in a J2EE application component deployment descriptor. The link-reference is the value of the name attribute of the <resource-ref-mapping> element. As mentioned previously, the link-key for a <resource-ref> element is the value of its <res-ref-name> subelement.

    • 5 - The third link in a typical outbound connection factory chain is from a <resource-ref-mapping> element in an OC4J-specific application component deployment descriptor to a <connector-factory> element in an oc4j-ra.xml file. The link-reference is the value of the location attribute of the <resource-ref-mapping> element. The link-key for a <connector-factory> element is the value of its location attribute (which is also the JNDI location where the resource adapter connection factory defined by the given <connector-factory> element will be bound).

  • Application components declare logical names for destinations in J2EE application component deployment descriptors. The deployer then maps those logical names to JMS Connector destinations, making use of any information provided by the Application Assembler in the form of <message-destination-link>s and <message-destination>s.

    For each <message-destination>, the deployer must map all <message-destination-ref>s and MDBs linked to that <message-destination> to the same destination.

    For details and examples, see "Deployer Task #2: Map Logical Destinations to RA Destinations" in the relevant How-To document.

    The figure depicts the two types of destination links provided by the <destination-ref-mapping> element:

    • 8 - The second link in a typical outbound destination chain is from a <message-destination-ref-mapping> element in an OC4J-specific application component deployment descriptor back to a <message-destination-ref> element in a J2EE application component deployment descriptor. The link-reference is the value of the name attribute of the <message-destination-ref-mapping> element. As mentioned previously, the link-key for a <message-destination-ref> element is the value of its <message-destination-ref-name> subelement.

    • 7 - The third link in a typical outbound destination chain is from a <message-destination-ref-mapping> element in an OC4J-specific application component deployment descriptor to an <adminobject-config> element in an oc4j-connectors.xml file. The link-reference is the value of the location attribute of the <message-destination-ref-mapping> element. The link-key for an <adminobject-config> element is the value of its location attribute (which is also the JNDI location where the resource adapter destination defined by the given <adminobject-config> element will be bound).

  • For each MDB, the deployer must indicate the JMS Connector instance, connection factory and destination that should be used to meet the MDB's inbound messaging requirements.

    For details and examples, see "Deployer Task #2: Map Logical Destinations to RA Destinations" and "Deployer Task #3: Configure the MDB" in the relevant document.

    Figure 4-1 depicts the three types of inbound messaging links from the orion-ejb-jar.xml file to the oc4j-connectors.xml and oc4j-ra.xml files:

    • 9 - The link that tells the container which JMS Connector instance should be used to handle a given MDB's inbound messaging needs is from the MDB's <message-driven-deployment> element in an orion-ejb-jar.xml file to the JMS Connector instance's <connector> element in an oc4j-connectors.xml file. The link-reference is the value of the resource-adapter attribute of the <message-driven-deployment> element. The link-key for a <connector> element is the value of its name attribute (which is also the JNDI location where the resource adapter instance defined by the given <connector> element will be bound).

    • 10 - For MDB/inbound messaging, a single link is used instead of the three connection factory links described to this point. This link is from a <message-driven-deployment> element in an orion-ejb-jar.xml file to a <connector-factory> element in an oc4j-ra.xml file. The link-reference is the value of the <message-driven-deployment>'s ConnectionFactoryJNDIName config property. As mentioned previously, the link-key for a <connector-factory> element is the value of its location attribute (which is also the JNDI location where the resource adapter connection factory defined by the given <connector-factory> element will be bound). Note that this links to the same place as the third link in the outbound case, and the rest of the connection factory chain is the same for both inbound and outbound messaging.

    • 11 - For MDB/inbound messaging, a single link is used instead of the three destination links described to this point. This link is from a <message-driven-deployment> element in an orion-ejb-jar.xml file to an <adminobject-config> element in an oc4j-connectors.xml file. The link-reference is the value of the <message-driven-deployment>'s DestinationName config property. As mentioned previously, the link-key for an <adminobject-config> element is the value of its location attribute (which is also the JNDI location where the resource adapter destination defined by the given <adminobject-config> element will be bound). Note that this links to the same place as the third link in the outbound case, and the rest of the destination chain is the same for both inbound and outbound messaging.

oc4j-connectors.xml

JMS Connector destinations act as wrappers for RP destinations. In order for the JMS Connector to look up an RP destination, the JMS Connector needs to know the JNDI location of the RP destination.

For details and examples, see "Resource Adapter Task #4: Create RA Destinations" in the relevant How-To document. For information on creating resource provider destinations, see "Configuring the Resource Provider" in the relevant How-To document.

Figure 4-1 depicts the two types of links which together tie JMS Connector destinations defined in oc4j-connectors.xml to RP destinations:

  • 12 - The final segment of the destination chain is from an <adminobject-config> element in an oc4j-connectors.xml file (which defines a JMS Connector destination) to a resource provider destination, and is composed of two parallel links. The first link is from the <adminobject-config> element to a <resource-provider> element in an individual application's orion-application.xml file (or the default application's application.xml file). The link-reference is the value of the <adminobject-config>'s resourceProviderName config property. The link-key for a <resource-provider> element is the value of its name attribute (which is also the JNDI location under java:comp/resource where the resource provider reference defined by the <resource-provider> element will be bound - the providerName).

  • 13 - The second link completes the connection from the <adminobject-config> element to the resource provider destination. The link-reference is the value of the <adminobject-config>'s jndiName config property. The link-key is the JNDI location of the RP destination within the resource provider's JNDI context (the resourceName). Together, these two links provide the JMS Connector destination with the full JNDI location

    java:comp/resource/providerName/resourceName
    

    of the RP destination.

oc4j-ra.xml

JMS Connector connection factories act as wrappers for RP connection factories. In order for the JMS Connector to look up an RP connection factory, the JMS Connector needs to know the JNDI location of the RP connection factory.

For details and examples, see "Resource Adapter Task #3: Create RA Connection Factories" in the relevant How-To document. For information on creating resource provider connection factories (but not for the OEMS JMS Database persistence option since all these connection factories are automatically pre-created, see "Configuring the Resource Provider" in the relevant How-To document.

Figure 4-1 depicts three types of links that help define the implementation for JMS Connector connection factories defined in oc4j-ra.xml and tie them to RP connection factories:

  • 15 - In theory this link ties a <connector-factory> element in an oc4j-ra.xml file (which defines a JMS Connector connection factory) to a <connector> element in an oc4j-connectors.xml file (which defines an JMS Connector instance). In practice this link may not actually be used, but for future compatibility it should be set as follows: The link-reference is the value of the connector-name attribute of the <connector-factory> element. As previously mentioned, the link-key for a <connector> element is the value of its name attribute (which is also the JNDI location where the JMS Connector instance defined by the given <connector> element will be bound).

  • 16 - The final segment of the connection factory chain is from a <connector-factory> element in an oc4j-ra.xml file (which defines a JMS Connector connection factory) to an RP connection factory, and is composed of two parallel links. The first link gives the JNDI location under java:comp/resource where the resource provider reference is bound (the providerName). It's link-reference is located in the ra.xml file - see the description for arrow #18. The second link completes the connection from the <connector-factory> element to the resource provider connection factory. The link-reference is the value of the <connector-factory>'s jndiLocation config property. The link-key is the JNDI location of the RP connection factory within the resource provider's JNDI context (the resourceName). Together, these two links provide the JMS Connector connection factory with the full JNDI location

    java:comp/resource/providerName/resourceName
     
    

    of the RP connection factory. NOTE: This link is actually an optional override. (See description for arrow #17.) By convention this override is always set (even if its value is the same as the value it is overriding).

  • 14 - The implementation details for a JMS Connector connection factory (a <connector-factory> element in an oc4j-ra.xml file) are defined by linking the <connector-factory> element to a <connection-definition> element in an ra.xml file. The link-reference is the value of the <connector-factory>'s <connectionfactory-interface> subelement. The link-key for a <connection-definition> element is the value of its <connectionfactory-interface> subelement.

ra.xml

Much of the content in the ra.xml file does not need to be changed when using the JMS Connector. (The reason for this is that the ra.xml file is based on a J2EE Connector Architecture 1.5 schema file, which is a generic schema intended to work with many types of resource adapters, including non-JMS resource adapters.)

For details and examples, see "Resource Adapter Task #1: Customize the ra.xml File" in the relevant How-To document.

Figure 4-1 depicts two types of links that define default JMS Connector connection factory settings in ra.xml:

  • 18 - This is the first link of the final segment of the connection factory chain. (See description for arrow #16.) This link is from a <resourceadapter> element in an ra.xml file to a <resource-provider> element in an individual application's orion-application.xml file (or the default application's application.xml file). The link-reference is the value of the <resourceadapter>'s resourceProviderName config property. As mentioned previously, the link-key for a <resource-provider> element is the value of its name attribute (which is also the JNDI location under java:comp/resource where the resource provider reference defined by the <resource-provider> element will be bound). NOTE: The link-reference value in the ra.xml file is just a default, and for any given JMS Connector instance it may be overridden using the <connector>'s resourceProviderName config property in the JMS Connector instance's oc4j-connectors.xml file. The override is generally not required and is not depicted with an arrow in the figure.

  • 17 - This link acts as a default when a <connector-factory> linked to a <connection-definition> (see description for arrow #14) does not include a jndiLocation config property (see description for arrow #16). The link-reference is the value of the <connection-definition>'s jndiLocation config property. The link-key is the JNDI location of the RP connection factory within the resource provider's JNDI context.

Bypassing the JMS Connector for Application Clients

Most of the features provided by the JMS Connector are not applicable to application clients. In order to keep application clients as light-weight as possible, you may choose to not use the JMS Connector with application clients. When the JMS Connector is bypassed, the JAR files required only by the JMS Connector do not need to be included in the class-path (see Table 4-9 for a list of JAR files required by the JMS Connector).

An application client that is not using the JMS Connector can communicate with application components that are using the JMS Connector so long as the same underlying resource provider (RP) destination is used by both components. Bypassing the JMS Connector is accomplished by referencing resource provider resources instead of JMS Connector resources in the orion-application-client.xml file:

  1. Bypass JMS Connector Connection Factories -

    For each <resource-ref-mapping> element, make the value of its location attribute be

    java:comp/resource/providerName/resourceName
     
    

    where providerName is equal to the link-key for arrow #18 in Figure 4-1, "JMS Configuration" and resourceName is equal to the link-key for arrow #16 in Figure 3-1. This replaces arrows #6, #18 and #16 in Figure 3-1 with a direct link to the RP connection factory, bypassing the JMS Connector's oc4j-ra.mxl and ra.xml files.

  2. Bypass JMS Connector Destinations -

    For each <message-destination-ref-mapping> element, make the value of its location attribute be

    java:comp/resource/providerName/resourceName
     
    

    where providerName is equal to the link-key for arrow #12 in Figure 4-1, "JMS Configuration" and resourceName is equal to the link-key for arrow #13 in Figure 3-1. This replaces arrows #7, #12 and #13 in Figure 3-1 with a direct link to the RP destination, bypassing the JMS Connector's oc4j-connectors.xml file.

Some third-party tools or libraries that access JNDI directly may have rigid location limits or validation rules that do not allow for the java:comp/resource syntax or naming peculiarities of specific resource providers, such as the Queues/ prefix and other prefixes used by OEMS JMS Database option. In that situation, the JMS Connector should not be bypassed. (In general this limitation does not apply to the OEMS JMS In-Memory and File-Based options. This is because, for these resources, the resourceName can be used in a JNDI lookup by itself. That is, the

java:comp/resource/providerName/
 

prefix is purely optional when using OEMS JMS In-Memory or File-Based options.)

An application must not pass JMS Connector destinations to any object derived from an RP connection factory, and must not pass RP destinations to any object derived from a JMS Connector connection factory. The JMS Connector automatically manages the conversion from one destination type to the other for the JMSDestination and JMSReplyTo header fields for all sent, received, and browsed messages. For example, if an application client that is not using the JMS Connector sets the JMSReplyTo header field for an RP message to an RP destination and sends the message, and another application component that is using the JMS Connector receives the message and reads the JMSReplyTo header field, then the receiver will get a compatible JMS Connector message and JMS Connector destination that wrap the original RP message and RP destination. There is no automatic conversion for any other case. For example, if that scenario were repeated, but instead of sending the message directly it was sent as the body of an ObjectMessage, then when the receiver extracted the body of the ObjectMessage it would get an RP message instead of an JMS Connector message, and the JMSReplyTo header field of that RP message would contain an RP destination rather than a JMS Connector destination.

Resource Providers

The underlying connection factories and destinations that application clients use to send and receive JMS messages are resource provider objects. OC4J uses the JMS Connector to plug in the OEMS JMS (In-Memory, File-Based, and Database), IBM MQ, TIBCO, and Sonic resource providers.

Ultimately, the destinations and connection factories must be created in the resource provider.

In general, use the following steps to configure a resource provider:

Each JMS provider requires its own procedure for configuring the provider and creating connection factories and destination objects. For resource providers other than OEMS JMS, refer to the documentation for that provider.

Declaring Resource Provider References

A client can use one or more different JMS resource providers, each with its own resource adapter, choosing according to the integration and quality-of-service (QOS) features desired.

References to the resource provider are declaed in one or more <resource-provider> elements of the orion-application.xml file and the application.xml file.

  • OEMS JMS In-Memory and File-Based Persistence—These two OEMS JMS persistence options are installed with OC4J.

  • OEMS JMS Database Persistence—The OEMS JMS Database persistence option is a feature of the Oracle database and is based on the Streams Advanced Queuing (AQ) messaging system.

    The benefits of the OEMS JMS Database persistence option are as follows:

    • It is backed by the Oracle database.

    • OEMS JMS Database persistence and other Oracle database transactions can be used together in one-phase commit transactions.

    • It also provides access to extra features provided by AQ including interoperability with PL/SQL and OCI.

  • Using Third-Party JMS Providers—You can integrate with the following third-party JMS providers:

    • WebSphere MQ for JMS versions 6.0 and 5.3 resource provider

    • TIBCO Enterprise Message Server version 4.3.0

    • SonicMQ 6.0

Use one of the following files to declare a resource provider reference:

  • To make a resource provider reference visible to all applications (global), then use the global application.xml file.

  • To make a resource provider reference visible only to a single application (local), then use the orion-application.xml file specific to the application.

Add the following code to the appropriate XML file:

<resource-provider class="providerClassName" name="providerName">
     <description>description </description>
     <property name="name" value="value" />
</resource-provider>

For the <resource-provider> attributes, configure the following:

  • class—The name of the resource provider class.

    • For the OEMS JMS In-Memory and File-Based option, use: com.evermind.server.jms.Oc4jResourceProvider

    • For the OEMS JMS Database option, use: oracle.jms.OjmsContext

    • For all third party resource providers, use: com.evermind.server.deployment.ContextScanningResourceProvider

  • name—A name by which to identify the resource provider. This name is used to map the resource provider's JNDI context in the application's JNDI as:

    java:comp/resource/providerName/
    

The subelements of the <resource-provider> are configured as follows:

  • <description> subelement—A description of the specific resource provider.

  • <property> subelement—The name and value attributes are used to identify parameters provided to the resource provider. The name attribute identifies the name of the parameter, and its value is provided in the value attribute.

Before an application or a resource adapter running in OC4J can access a resource provider, a resource provider reference must be declared with the <resource-provider> element. The resource provider reference holds miscellaneous data that OC4J uses to interact with the resource provider. The resource provider reference also provides a JNDI subcontext through which resource provider resources can be accessed. The resource provider reference (and said JNDI access) can be made local to the application by placing it in orion-application.xml, or available to all applications by placing it in %ORACLE_HOME%/j2ee/home/config/application.xml.

The two pieces of information that you must provide whenever declaring a resource provider reference are the name you wish to use for the resource provider reference and the Java class that implements the resource provider interface.

The resource provider reference maps the resource provider's JNDI context, which contains resource provider connection factories and resource provider destinations, to a JNDI subcontext accessible by the application and, more importantly, the JMS Connector. The reason it is more important for the JMS Connector to be able to access resource provider resources than for the application to be able to do so is that, when using a JMS Connector, the application need not (and in general should not) directly look up or use any resource provider resources. That JNDI subcontext is java:comp/resource/providerName where providerName is the name of the resource provider reference.

The demo set at http://www.oracle.com/technology/tech/java/oc4j/1013/how_to/index.html includes examples of declaring resource provider references. For a list of the How-To documents and demo sets and their URLs, see "JMS How-To Documents and Demo Sets".

Download and unzip the How-To-gjra-with-xxx.zip file, where xxx is the name of the relevant resource provider.

Drill down to the following file: /src/META-INF/orion-application.xml.

For more detail, search for "Configuring the Resource Provider" in the relevant How-To document.

In the demo, the data source and the resource provider are declared local to the application. If the data source definition is placed in $J2EE_HOME/config/data-sources.xml and the resource-provider definition is placed in $J2EE_HOME/config/application.xml, then they are visible to all applications. (Only the demo for the OEMS JMS Database Persistence provider requires or includes a data source.)

The following sections give more detail on declaring the resource provider reference for each resource provider supported by OC4J, including the Java class and an example resource provider reference name for each:

OEMS JMS In-Memory and File-Based Persistence

The OEMS JMS In-Memory and File-Based options provide the following features:

  • Complies with the JMS 1.1 specification.

  • Is compatible with the J2EE 1.4 specification.

  • Offers a choice between in-memory or file-based message persistence.

  • Provides an exception queue for undeliverable messages.

Note:

If you see the term "OC4J JMS" or "OracleAS JMS" in the Application Server Control Console, in the MBeans, or in the sample code, this refers to the OEMS JMS In-Memory and File-Based persistence options.

This section covers the following topics:

Configuring Destination Objects and Connection Factories

Destination objects can be queues or topics. The OEMS JMS In-Memory and File-Based options are already installed with OC4J, so the only configuration necessary is for the custom destination objects and connection factories for your applications to use.

The primary tool for configuring Destination objects and connection factories is the Application Server Control Console. You can also edit the XML files directly.

Default Destination Objects and Connection Factories

The defaults are useful as follows:

  • The connection factories can be copied and used as templates for connection factories that you create. The default connection factories can also be used without modification in production.

  • The destinations can be copied and used as templates for destinations that you create. The default destinations should NOT be used in production.

Six default connection factories are created for the different combinations of XA (global transaction enabled), non-XA, and various JMS interfaces. Your applications can use these connection factories without your having to add them in the Application Server Control Console or the jms.xml file. The only reason to define a new connection factory is to specify non default values for one or more of the optional attributes of connection-factory elements.

The default connection factory objects are created internally by OC4J, which binds them to the default JNDI locations within the OC4J server where the JMS connection is created.

The following default connection factories are created, even though they are not explicitly defined in the jms.xml file. It is safer to treat these as reserved JNDI locations and to use other JNDI locations when you create custom connection factories.


XA non-XA
Default Queue Connection Factory jms/XAQueueConnectionFactory jms/QueueConnectionFactory
Default Topic Connection Factory jms/XATopicConnectionFactory jms/TopicConnectionFactory
Default Unified Connection Factory jms/XAConnectionFactory jms/ConnectionFactory

Default destinations are as follows:

  • Default Queue: jms/demoQueue

  • Default Topic: jms/demoTopic

Configuring in the Application Server Control Console

The Application Server Control Console is the primary tool for configuring the OEMS JMS In-Memory and File-Based persistence option connection factories and destination objects. For each destination object, you must specify its name, location, and destination type (queue or topic).

Path to the Application Server Control Console:

OC4J:Home > Administration tab > Services > JMS Providers > Go To Task Configure OracleAS JMS > Select the appropriate tab.

Table 4-1, Configuration Elements table describes the OracleAS JMS resource provider configuration elements and their attributes.

Configuration Elements

Table 4-1 defines the configuration elements and shows where to make the settings in the Application Server Control Console, in the MBeans, and in the jms.xml file.

Table 4-1 Configuration Elements

Console and MBean Setting Locations Element(s) of jms.xml Description and Attributes

The JMSAdministrator MBean enables you to specify the server host name and port, and multiple related attributes and operations.

Path to the JMSAdministrator MBean:

OC4J:Home > Administration tab > Task Name: JMX. System MBean Browser. > Go To Task > Drill down: J2EEDomain:oc4j, J2EEServer:standalone, JMSAdministratorResource, "JMSAdministrator"

<jms-server>

The root element of the server configuration.

The <jms-server> element takes the following attributes:

host - The host name defined in a String (DNS or dot-notation host name) to which this server should bind. By default, the server binds to 0.0.0.0 (also known as [ALL] in the configuration file). Optional.

port - The port defined as an int (valid TCP/IP port number) to which this server should bind. The default setting is 9127. This setting applies only to the standalone configuration of OC4J. In the Oracle Application Server configuration, the port setting in the configuration file is overridden by command-line arguments that are used (by, for example, OPMN and others) when starting the OC4J server. Optional.

Create a resource provider destination and specify its attributes on the Add Destinations page.

Path to the Add Destinations page:

OC4J:Home > Administration tab > Task Name: Services.JMS Providers > Go To Task > Destinations tab > Create New

<queue>

This element configures queues. The queues are available when OC4J starts up, and are available for use until the server is restarted or reconfigured. You can configure zero or more queues in any order. Any newly-configured queue is not available until OC4J is restarted.

The <queue> element takes the following attributes:

name - This required attribute is the provider-specific name (String) for the queue. The name can be any valid non empty string (with white space and other special characters included, although this is not recommended). The name specified here can be used in Session.createQueue() to convert the provider-specific name to a JMS queue. It is invalid for two destinations to specify the same name. There is no default.

location - This required attribute states the JNDI location (String) where the queue is bound. The value should follow the JNDI rules for valid names.

persistence-file - An optional path and filename (String). The path for the persistence-file attribute is either an absolute path of the file or a path relative to the persistence directory defined in application.xml. The default path is J2EE_HOME/persistence/<group> for Oracle Application Server environments and J2EE_HOME/persistence for standalone environments.

Each queue and topic must have its own persistence file name. You must not have two objects writing to the same persistence file.

The persistence-file attribute is discussed further at "Persistence Recovery".

Create a topic destination and specify its attributes on the Add Destinations page.

Path to the Add Destinations page:

OC4J:Home > Administration tab > Task Name: Services.JMS Providers > Go To Task > Destinations tab > Create New

<topic>

This element configures a topic. The topics are available when OC4J starts up, and are available for use until the server is restarted or reconfigured. You can configure zero or more topics in any order. Any newly configured topic is not available until OC4J is restarted.

The <topic> element takes the following attributes:

name - This required attributes is the provider-specific name (String) for the topic. The name can be any valid non empty string (with white space and other special characters included, although this is not recommended). The name specified here can be used in Session.createTopic() to convert the provider-specific name to a JMS topic. It is invalid for two destinations to specify the same name. There is no default.

location - This required attribute states the JNDI location (String) where the topic is bound. The value should follow the JNDI rules for valid names. There is no default.

persistence-file - An optional path and filename (String). The path for the persistence-file attribute is either an absolute path of the file or a path relative to the persistence directory defined in application.xml; the default path is J2EE_HOME/persistence/<group> for Oracle Application Server environments and J2EE_HOME/persistence for standalone environments.

Each queue and topic must have its own persistence file name. You must not have two objects writing to the same persistence file.

The persistence-file attribute is discussed further at "Persistence Recovery".

The Description field is on the Add Destination page where you create the topic or queue to which the description applies.

<description>

A sub-element of <queue> or <topic>. A user-defined string to remind the user for what the queue or topic is used. Optional.

Create a connection factory and specify its attributes on the Add Connection Factory page.

Path to Add or Edit a Connection Factory:

OC4J:Home > Administration tab > Task Name: Services.JMS Providers > Go To Task > Connection Factories tab > Create New or Edit Properties

<connection-factory>

or

<queue-connection-factory>

or

<topic-connection-factory>

Connection factory configuration. A connection factory element takes the following attributes:

  • location - Required. The JNDI location to which the connection factory is bound. The value must follow JNDI rules for valid names.

  • host - Optional. The fixed OC4J host to which this connection factory will connect. By default, a connection factory uses the same host as configured for the jms-server element. Non default values can be used to force all JMS operations to be directed to a specific OC4J JVM, bypassing any locally available OC4J servers and other Oracle Application Server or clustered configurations. Optional, string, DNS or dot notation host name. Default = ALL

  • port - Optional. The fixed port to which this connection factory connects. By default, a connection factory uses the same port as configured for the jms-server element (or the value of the port that was specified for Oracle Application Server or clustered configurations on the command line). Non default values can be used to force all JMS operations to be directed to a specific OC4J JVM, bypassing any locally available servers and other Oracle Application Server or clustered configurations. Optional, int, valid TCP/IP port number. Default = 9127.

  • username - Optional. The user name for the authentication of JMS default connections created from this connection factory. That is, if an application creates a connection and neither the application nor the oc4j-ra.xml file specifies a username/password, then the username and password attributes from this element will be used. The user name itself must be properly created and configured with other OC4J facilities. Optional, string. Default = the empty string.

  • password - Optional. The password for the authentication of JMS default connections created from this connection factory. The password itself must be properly created and configured with other OC4J facilities. The property password attribute supports password indirection. For more information, refer to the Oracle Containers for J2EE Security Guide. Optional, string. Default = the empty string.

  • clientID - Optional. The administratively configured, fixed JMS clientID for connections created from this connection factory. If no clientID is specified, then the default is an empty string, which can also be programmatically overridden by client programs, according to the JMS specification. The clientID is used only for durable subscriptions on topics; its value does not matter for queue and nondurable topic operations. Optional, string. Default = the empty string.

Create an XA-enabled connection factory and specify its attributes on the Add Connection Factory page.

Path to Add or Edit a Connection Factory:

OC4J:Home > Administration tab > Task Name: Services.JMS Providers > Go To Task > Connection Factories tab > Create New or Edit Properties

<xa-connection-factory>

or

<xa-queue-connection-factory>

or

<xa-topic-connection-factory>

XA variants of connection factory configuration.

The XA connection factory elements take the same attributes as the non-XA connection factory elements, which are described in the previous row.

 

<log>

Enables logging of the JMS activity in either file or ODL format. See the section "Enabling OC4J Logging" in the Oracle Containers for J2EE Configuration and Administration Guide for information on logging.

Edit system properties settings in the JMSAdministratorResource MBean.

Path to system properties settings in JMSAdministratorResource MBean:OC4J:Home > Administration tab > Task Name: JMX.System MBean Browser. > Go To Task > Drill down: J2EEDomain:oc4j, J2EEServer:standalone, JMSAdministratorResource, "JMSAdministrator" > Operations tab > setConfigProperty

<config-properties>

Sets system properties. The settings are persisted to the jms.xml file.

<config-property> - Subelement of <config-properties>.

These settings are discussed in "JMS Configuration Properties".


Configuration Using jms.xml

The OEMS JMS In-Memory and File-Based configuration settings are persisted in the jms.xml file. The settings in jms.xml include:

  • Connection factories

  • Destinations

  • JMS Router jobs

  • Global configuration

Note:

Remember that you must restart the OC4J instance to enable configuration changes made directly in the XML files.

The following example shows the structure of elements under <jms-server> within the jms.xml file. This example configures the following destinations and connection factories:

  • The queue "MyQueue" at JNDI location jms/MyQueue

  • The topic "MyTopic" at JNDI location jms/MyTopic

  • A connection factory (unified) at JNDI location jms/Cf

  • A queue connection factory at JNDI location jms/Qcf

  • An XA topic connection factory at JNDI location jms/xaTcf.

<jms>
  <jms-server>

    <queue  name="MyQueue" location="jms/MyQueue" persistence-file="/tmp/MyQueue">
       <description>The demo queue. </description>
    </queue>

    <topic name="MyTopic" location="jms/MyTopic" persistence-file="/tmp/MyTopic">
      <description>The demo topic. </description>
    </topic>

    <connection-factory location="jms/Cf">
    </connection-factory>

    <queue-connection-factory location="jms/Qcf">
    </queue-connection-factory>

    <xa-topic-connection-factory location="jms/xaTcf"
        username="foo" password="bar" clientID="baz">
    </xa-topic-connection-factory>


    <log>
      <file path="../log/jms.log" />
    </log>

    <config-properties>
      <config-property name="oc4j.jms.debug" value="true">
      </config-property>
    </config-properties>

  </jms-server>

   <jms-router>
      <!-- JMS router configuration is shown in the 
      "JMS Router Configuration in jms.xml" section. 
      -->
   </jms-router>

</jms>

A detailed example of the element structure under <jms-router> is available at "JMS Router Configuration in jms.xml".

Configuring Ports

In a standalone OC4J instance, you can set the port range in the JMSAdministrator MBean. You must restart the OC4J instance for your changes to take effect. This restart requirement is a special case for port settings.

In the full Oracle Application Server environment (managed), use the Application Server Control Console to configure the port range.

Path to configure the port range in the Application Server Control Console:

OC4J:Home > Administration tab > Task Name: JVM Properties > JMS Ports

Sending and Receiving JMS Messages

The code for sending and receiving JMS messages is not dependent on the JMS Connector or the resource providers involved.

This example is from the MyChannel.java file in the demo sets at: http://www.oracle.com/technology/tech/java/oc4j/1013/how_to/index.html

Drill down to the following file: /src/common/MyChannel.java

In the demo, MyChannel.java is the only class that sends or receives JMS messages. All other classes call MyChannel to do sends and receives. MyChannel is the same for all of the different resource providers. In fact, all of the .java source is the same for all of the resource providers except for some comments in Player.java that explain alternate JNDI locations (not based on logical names) that may be used for looking up connection factories and destinations.

For a list of the How-To documents and demo sets and their URLs, see "JMS How-To Documents and Demo Sets".

public MyChannel(String connectionFactoryName, String destinationName) throws Exception {

        Context ctx = new InitialContext();

        // Get the destination.
        Destination destination = (Destination) ctx.lookup(destinationName);

        // Get the connection factory.
        ConnectionFactory cf = (ConnectionFactory)
 ctx.lookup(connectionFactoryName);

        // Use the connection factory to create a connection.
        connection = cf.createConnection();

        // Start the connection.
        connection.start();

        // Use the connection to create a session.
        session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);

        // Use the session and destination to create a message producer and a message consumer.
        producer = session.createProducer(destination);
        consumer = session.createConsumer(destination);
    }

    /**
     * Send message.
     * prerequisite: channel is open
     * @param obj object to be sent
     */
    public void send(Serializable obj) throws JMSException {

        // Use the session to create a new message.
        ObjectMessage msg = session.createObjectMessage(obj);

        // Use the message producer to send the message.
        producer.send(msg);
        System.out.println("Sent message: " + obj);
    }

    /**     * Receive message (wait forever).
     * prerequisite: channel is open
     * @return object which was received in message, or <code>null</code> if no message was received
     */
    public Serializable receive() throws JMSException {

        // Use the message consumer to receive a message.
        ObjectMessage msg = (ObjectMessage) consumer.receive();

        System.out.println("Got message: " + msg.getObject());
        return msg.getObject();
    }

    /**
     * Receive message (wait a while).
     * prerequisite: channel is open
     * @param timeout maximum time (in milliseconds) to wait for a message to arrive
     * @return object which was received in message,
     * or <code>null</code> if no message was received     */
    public Serializable receive(long timeout) throws JMSException {

        // Use the message consumer to receive a message (if one comes in time).
        ObjectMessage msg = (ObjectMessage) consumer.receive(timeout);

        if (msg == null) return null;
        System.out.println("Got message: " + msg.getObject());
        return msg.getObject();
    }

    /**
     * Close channel.
     * prerequisite: channel is open
     * Once a MyChannel object is closed, it may no longer be used to send or receive
     * messages.
     */
    public void close() throws JMSException {

        // Close the connection (and all of its sessions, producers and consumers).
        connection.close();
    }

    private Connection connection;
    private Session session;
    private MessageProducer producer;
    private MessageConsumer consumer;
}

Using the JMS Utility

The OEMS JMS implementation comes with a command-line utility that is used to interact with OEMS and perform tasks such as listing or browsing JMS destinations. The utility class (com.evermind.server.jms.JMSServerUtils) is bundled with OC4j in oc4j-internal.jar. Many of the tasks provided by this utility are also available through a set of MBeans that are accessed using the Oracle Enterprise Manager 10g console. For more information on using the MBeans, see "Using JMS MBeans".

The utility requires the following jar files at runtime. These jar files can be added to the CLASSPATH environment variable:

  • J2EE_HOME\oc4j.jar

  • J2EE_HOME\oc4j-api.jar

  • J2EE_HOME\oc4jclient.jar

  • J2EE_HOME\rmic.jar

  • J2EE_HOME\lib\adminclient.jar

  • J2EE_HOME\lib\connector.jar

  • J2EE_HOME\lib\javax77.jar

  • J2EE_HOME\lib\jmxri.jar

  • J2EE_HOME\lib\oc4j-internal.jar

The syntax of the utility is as follows:

java com.evermind.server.jms.JMSServerUtils [generic-options] [command] [command-options] [arguments]

For detailed information on usage, use the help command:

java com.evermind.server.jms.JMSServerUtils help

All options and commands are discussed in Table 4-2, Table 4-3, and Table 4-4. The generic options are used to connect to an OracleAS JMS server.

Note:

The OEMS JMS server must be running before connecting to it with the JMSServerUtils. In addition, JMSServerUtils can only connects to a JMS server as a user within the administrator role. Users are added to roles in the security User Manager. For information on defining users within security roles, see the Oracle Containers for J2EE Security Guide.

Table 4-2 JMS Utility Generic Options

Option Description

-host <hostname>

The (remote) host where the OracleAS JMS server is installed. This is not required if the client exists on the same node as the OracleAS JMS server.

-port <port>

The (remote) port through which the OracleAS JMS server is accessed. The default JMS port number is 9127.

-username <username>

The username to access the OracleAS JMS server for creating the JMS connection. This user is defined in the User Manager security configuration within the administrative roles.

-password <password>

The password to access the OracleAS JMS server for creating the JMS connection. This password is defined in the User Manager security configuration within the administrative roles.

-clientID <ID>

Use this identifier for all JMS connections. This is required only for identifying durable subscriptions on topics.


The commands describe the action to be taken and are discussed in Table 4-3. Some of these commands have their own options (command-options) to further describe the action desired.

Table 4-3 JMS Utility Commands

Command Description

help

Print detailed help for all utilities commands.

check [<other-selector>]

Check validity of a JMS message selector, identified by the -selector command option. Optionally, check if two specified selectors are treated as equivalent (useful for reactivating durable subscriptions), where the second selector is identified in the optional <other-selector>.

knobs

Display all available system properties (shown in Table 4-6) and their current settings on the OC4J JMS server.

stats

Display all available DMS statistics on the OC4J JMS server (this includes non-JMS statistics as well). (For information on DMS, see the Oracle Application Server Performance Guide.)

destinations

Print a list of all permanent Destination objects known to OC4J JMS.

durables

Print a list of all durable subscriptions known to OC4J JMS.

subscribe <topic>

Create a new durable subscription on the <topic>. Specify a name, message selector, whether it is local, and a durable subscription client identifier. This replaces existing, inactive durable subscriptions. The name is identified using the -name command option. The message selector is identified using the -selector command option. Whether the durable subscription is local or not is identified using the -noLocal command option. The client identifier is defined with the -clientID generic option.

unsubscribe

Drop an existing, inactive durable subscription. The durable subscription is identified by a name (-name command option) and the client identifier (-clientID generic option).

browse <destination>

Browse messages on a given destination (queue or topic durable subscription, defined in jms.xml).

drain <destination>

Dequeue messages on a given destination (queue or topic durable subscription).

copy <from-destination> <to-destination>

Copy messages from one destination (queue or topic durable subscription) to a different destination. If the source and sink destinations are the same, then the command is not executed, generating an error instead.

move <from-destination> <to-destination>

Move messages from one destination (queue or topic durable subscription) to a different destination. If the source and sink destinations are the same, then the command is not executed, generating an error instead.


Table 4-4 JMS Utility Command Options

Command Option Description

-selector <selector>

Create queue receivers and durable subscribers with the specified JMS message selector.

-noLocal [true|false]

If set to true, the subscriber does not see the messages that are published in the same connection. Use when creating a durable subscriber. The default value is false.

-name <name>

Defines a name for a durable subscription, operating on a topic. This option is mandatory for commands that read topics, and is ignored for reading queues.

-silent

Do not print messages while processing. Keeps a count of the total number of messages processed, which is printed to standard error.

-count <count>

Do not process more than the indicated number of messages during the current operation. If the count is negative or zero, then all selected messages are processed.


The following example connects to an OracleAS JMS server that is located on the same computer as the client utility, browses the exception queue, and returns the number of messages processed by this queue:

java com.evermind.server.jms.JMSServerUtils -username <username> -password
 <password> browse jms/Oc4jJmsExceptionQueue 

Listening to a topic

In order to listen to a topic, first set a durable subscription (using JMSUtils), then publish some messages (using whatever publisher you have) and finally retrieve these messages (browsing using JMSServerUtils).

To listen to a topic:

  1. Set a durable subscription:

    java com.evermind.server.jms.JMSServerUtils -username oc4jadmin -password welcome1 -port 9127 -clientID demedclient subscribe -name demedjmsutils "Demo Topic"
    
  2. Publish some messages on that topic.

  3. Browse messages:

    java com.evermind.server.jms.JMSServerUtils -username oc4jadmin -password welcome1 -port 9127 -clientID demedclient browse -name demedjmsutils "Demo Topic"
    

Use the same clientID and name in both the subscription and the browsing. These are JMS concepts: clientID identifies a connection factory and name a specific subscription on this connection factory.

Using JMS MBeans

The OEMS JMS implementation comes with a set of JMX MBeans that are used to interact with OEMS and perform tasks such as listing or browsing JMS destinations. The MBeans are accessed using the Oracle Enterprise Manager 10g console. Many of the attributes and operations available through the MBeans are also available through a command-line utility. For more information on using the command-line utility, see "Using the JMS Utility".

The following MBeans are accessed from the Oracle Enterprise Manager 10g console:

  • The JMSAdministrator MBean - Path:

    OC4J:Home > Administration tab > Task Name: JMX.System MBean Browser > Go To Task > Drill down: J2EEDomain:oc4j, J2EEServer:standalone, JMSAdministratorResource, "JMSAdministrator"

  • The JMS MBean - Path:

    OC4J:Home > Administration tab > Task Name: JMX.System Bean Browser > Go To Task > Drill down: J2EEDomain:oc4j, J2EEServer:standalone, JMSResource, "JMS"

  • Various JMSDestinationResource MBeans - Path:

    OC4J:Home > Administration tab > Task Name: JMX.System MBean Browser > Go To Task > Drill down: J2EEDomain:oc4j, J2EEServer:standalone, JMSResource, "JMS", JMSDestinationResource > Select the MBean that represents the desired destination.

Table 4-5 JMS MBean Reference

MBean Implementation Command-Line Equivalent Description

configProperties attribute in the JMSAdministrator MBean

knobs

Display all available system properties (shown in Table 4-6) and their current settings.

Statistics tab in the JMS MBean

stats

The following OEMS JMS In-Memory and File-Based statistics are available through the JMS MBean:

  • activeHandlers

  • activeConnections

  • pendingMessageCount

  • messageDequeued

  • messageExpired

  • messageCommitted

  • messageRolledBack

  • messageEnqueued

  • messageRecovered

  • messageDiscarded

  • messagePagedIn

  • messageCount

validateSelector operation on the JMSAdministrator Mbean.

check <selector>

Check validity of the specified JMS message selector. The operation takes the argument selector.

areSelectorsEqual operation on the JMSAdministrator Mbean.

check <sel1> <sel2>

Check if two specified selectors are treated as equivalent. This is useful for reactivating durable subscriptions.

The operation takes the arguments: sel1 and sel2.

subscribe operation on all JMSDestinationResource MBeans whose domain = topic

subscribe

Creates a durable subscription on the destination. This replaces existing, inactive durable subscriptions.

The operation takes the following arguments:

  • name - name of the durable subscriber

  • noLocal - if true, allows subscriber to inhibit delivery of messages published by its own connection

  • xact - if true, session will be transacted

  • clientId - the client id

  • selector - the message selector

unsubscribe operation on all JMSDestinationResource MBeans whose domain = topic

unsubscribe

Removes the durable subscription.

The operation takes the following arguments:

  • name - name of the durable subscriber

  • xact - if true, session will be transacted

  • clientId - the client id

browse operation on all JMSDestinationResource Mbeans

browse

Browse this destination.

The operation takes the following arguments:

  • sub - name of the durable subscriber, only available for MBeans where domain = topic

  • xact - if true, session will be transacted

  • clientId - the client ID (optional)

  • selector - the message selector (optional)

  • count - the maximum number of messages to process (0 for all)

copy operation on all JMSDestinationResource Mbeans

copy

Copies messages from this destination to the specified destination.

The operation takes the following arguments:

  • sub - name of the durable subscriber, only available for MBeans where domain = topic

  • toDestination - the destination to move the messages to

  • xact - if true, session will be transacted

  • clientID - the client ID (optional)

  • selector - the message selector (optional)

  • count - the maximum number of messages to process (0 for all)

drain operation on all JMSDestinationResource Mbeans

drain

Drain messages from this destination.

The operation takes the following arguments:

  • sub - name of the durable subscriber, only available for MBeans where domain = topic

  • xact - if true, session will be transacted

  • clientId - the client ID (optional)

  • selector - the message selector (optional)

  • count - the maximum number of messages to process (0 for all)

move operation on all JMSDestinationResource Mbeans

move

Moves messages from this destination to the specified destination.

The operation takes the following arguments:

  • sub - name of the durable subscriber, only available for MBeans where domain = topic

  • toDestination - the destination to move the messages to

  • xact - if true, session will be transacted

  • clientID - the client ID (optional)

  • selector - the message selector (optional)

  • count - the maximum number of messages to process (0 for all)


Configuring File-Based Persistence

The following sections discuss file-based persistence:

When file-based persistence is enabled OC4J automatically performs the following:

  • If a persistence file does not exist, then OC4J automatically creates the file and initializes it with the appropriate data.

  • If the persistence file exists and is empty, then OC4J initializes it with the appropriate data.

Caution:

A persistence file must not be copied, deleted, or renamed when the OC4J server is active. Doing so can result in data corruption and message loss.

If OC4J is not active, then deleting a persistence file is equivalent to deleting all messages and durable subscriptions in the destination associated with that persistence file. When OC4J starts up again, the JMS server re initializes the file as usual.

For more information on this, see "Persistence File Management".

Even if persistence is enabled, only certain messages are persisted to a file. For a message to be persisted, all of the following conditions must be true:

  • The destination object is defined to be persistent by specifying a persistence file in the Application Server Control Console or by setting the destination's persistence-file attribute in the jms.xml file.

  • The message has a PERSISTENT delivery mode, which is the default.

    Messages sent to persistent destinations that are defined with a non-persistent delivery mode (defined as DeliveryMode.NON_PERSISTENT) are not persisted.

  • The destination is a queue, or the destination is a topic and the consumer is a durable subscriber.

Setting the DeliveryMode to PERSISTENT or NON_PERSISTENT is described in the JMS specification.

Setting the default DeliveryMode for a message producer is described at: http://java.sun.com/j2ee/1.4/docs/api/javax/jms/MessageProducer.html#setDeliveryMode(int)

Setting DeliveryMode (overriding the default) for each message is described at: http://java.sun.com/j2ee/1.4/docs/api/javax/jms/MessageProducer.html#send(javax.jms.Destination,%20javax.jms.Message,%20int,%20int,%20long)

and at: http://java.sun.com/j2ee/1.4/docs/api/javax/jms/MessageProducer.html#send(javax.jms.Message,%20int,%20int,%20long)

Notes on Enabling File-Based Persistence

Given that the previously-listed conditions are met, the file-based persistence option features recoverable and persistent storage of messages. Each destination can be associated with a relative or absolute path name that points to a file that stores the messages sent to the destination object. The file can reside anywhere in the file system (and not necessarily inside a J2EE_HOME directory). Multiple persistence files can be placed in the same directory. Persistence files can be placed on a remote network file system or can be part of a local file system.

Enabling File-Based Persistence in the Application Server Control Console

The Application Server Control Console is the primary tool for enabling file-based persistence for destination objects. Use the following path to specify the parameters of the persistence file in the Application Server Control Console.

Path to specify persistence files for destinations in the Application Server Control Console:

OC4J:Home > Administration tab > Task Name: Services, JMS Providers:, Go To Task > Destinations > Create New > "Persistence File"

You can specify a persistence file in the Application Server Control Console when creating a new destination. You cannot modify the persistence file specification for an existing destination in the Console. You can modify the persistence specification in the jms.xml file. See Enabling File-Based Persistence in the jms.xml File.

Enabling File-Based Persistence in the jms.xml File

You can enable file-based persistence for destination objects, by specifying the persistence-file attribute in the jms.xml file.

The following XML configuration example demonstrates how the persistence-file attribute defines the name of the file as pers.

<queue name="foo" location="jms/persist" persistence-file="pers">
</queue>

The path for the persistence-file attribute is either an absolute path of the file or a path relative to the persistence directory defined in application.xml.

The OC4J server will not create any directories for persistence files. So when a persistence file is defined in jms.xml it must either be in an existing absolute directory, for example:

persistence-file="/this/dir/exists/PersistenceFile"
 

or simply be a filename for example:

persistence-file="PersistenceFile"
 

In the latter case, by default the persistence file will be created in $J2EE_HOME/persistence (for a standalone instance) or $J2EE_HOME/persistence/<group_name> (in the full Oracle Application Server environment).

The persistence-file attribute is discussed in Table 4-1, "Configuration Elements".

Oracle Application Server may have multiple OC4J instances writing to the same file directory, even with the same persistence filename. Setting this attribute enables file-based persistence, but also creates the possibility that your persistence files can be overwritten by another OC4J instance.

Persistence Recovery

The following sections discuss the various aspects of persistence recovery:

Scope of Recoverability

The OEMS JMS File-Based persistence option can recover from some but not all possible failures. If any of the following failures occurs, then recoverability of the persistence file is not guaranteed:

  • Media corruption - The disk system holding the persistence file fails abnormally or gets corrupted.

  • External corruption - The persistence file is deleted, edited, modified, or otherwise corrupted (by software). Only the JMS server should write into a persistence file.

  • Silent failure or corruption - The I/O methods in the JDK fail silently or corrupt data that are being read or written silently.

  • A java.io.FileDescriptor.sync() failure - The sync() call does not properly and completely flush all file buffers associated with the given descriptor to the underlying file system.

Persistence File Management

When the JMS server is running, you must not copy, delete, or rename persistence files currently in use. It is an unrecoverable error to perform any of these actions on any of the persistence files when they are being used.

However, when no OEMS server is using a persistence file, you can perform the following administrative and maintenance operations on the persistence files:

  • delete - Deleting a persistence file removes all messages and, in the case of topics, all durable subscriptions. On startup, OEMS JMS initializes a new (and empty) persistence file.

  • copy - An existing persistence file can be copied for archival or backup purposes. If an existing persistence file becomes corrupted, an earlier version can be used (as long as the association between the OEMS JMS destination name and the file is maintained), pointed to by any suitable path name, to go back to the previous contents of the JMS destination.

Persistence files cannot be concatenated, split up, rearranged, or merged. Attempting any of these operations causes unrecoverable corruption of the data in these files.

In addition to persistence files specified by a user and lock files, the OEMS JMS In-Memory and File-Based options use a special file, jms.state, for internal configuration and transaction state management. The OEMS JMS server cleans up this file and its contents during normal operations. You must never delete, move, copy, or otherwise modify this file, even for archival purposes. Attempting to manipulate the jms.state file can lead to message and transaction loss.

Note:

The location of the jms.state file is different depending on whether you are operating OC4J in standalone or in Oracle Application Server mode, as follows:
  • Standalone: J2EE_HOME/persistence directory

  • Oracle Application Server: J2EE_HOME/persistence/<group_name> directory

The location of the persistence directory is defined in the application.xml file.

Reporting Errors to the JMS Client

The sequence of operations when a JMS client enqueues or dequeues a message, or commits or rolls back a transaction, is as follows:

  1. Client makes a function call

  2. Pre-persistence operations

  3. Persistence occurs

  4. Post-persistence operations

  5. Client function call returns

If a failure occurs during the pre-persistence or persistence phase, then the client receives a JMSException or some other type of error, but no changes are made to the persistence file.

If a failure occurs in the post-persistence phase, the client may receive a JMSException or some other type of error; however, the persistence file is still updated, and OEMS JMS recovers as if the operation succeeded.

Abnormal Termination

If OC4J terminates normally, then the lock files are cleaned up automatically. However, if OC4J terminates abnormally, for example, a kill -9 command, then the lock files remain in the file system. OC4J can usually recognize leftover lock files. If not, you must manually remove lock files before restarting OC4J after abnormal termination.

The default location of the lock files is in the persistence directory—J2EE_HOME/persistence. The persistence directory is defined in the application.xml file. Other locations can be set within the persistence-file attribute of the destination object.

Recovery Steps

Lock files prevent multiple OC4J processes from writing into the same persistence file. If multiple OC4J JVMs are configured to point to the same persistence file in the same location, then they could overwrite each other's data and cause corruption or loss of persisted JMS messages. To protect against such sharing violations, OEMS JMS associates each persistence file with a lock file. Thus, each persistence file—for example, /path/to/persistenceFile— is associated with a lock file named /path/to/persistenceFile.lock. See "Configuring File-Based Persistence" for more information on persistence files.

OC4J must have appropriate permissions to create and delete the lock file.

On termination and restart, one of the following lock-file scenarios will apply:

  • Normal termination - Lock files are automatically cleaned up. Restart proceeds normally.

  • Abnormal termination - On restart, lock files are recognized. Restart proceeds normally.

  • Abnormal termination - On restart, a CRITICAL message is delivered indicating a sharing violation. Restart cannot continue. Delete the lock file indicated in the error message and restart. If more than one lock file is involved, you may have to do this once for each.

JMS persistence lock files are tagged with (contain) server and persistence directory location info. If the lock file exists when the JMS server starts, and the lock file was created by the same server (having the same ip address) and using the same persistence directory location, then the JMS server will assume control of the lock file and start up successfully.

The remainder of this discussion of OEMS JMS File-Based recovery steps in this subsection assumes that all lock files in question have been removed.

OEMS JMS performs recovery operations on all persistence files as configured in OEMS JMS at the time of abnormal termination. In other words, if OC4J terminates abnormally and then the user modifies the JMS server configuration and restarts OC4J, the JMS server still attempts to recover all the persistence files in the original configuration, and, after recovery is successful, moves to using the new configuration specified.

If recovery of the old configuration fails, then the JMS server does not start. The server must be shut down or restarted repeatedly to give recovery another chance, until recovery is successful.

The JMS server caches its current persistence configuration in the jms.state file, which is also used to maintain transaction state. If you wish to bypass all recovery of the current configuration, you can remove the jms.state file, remove all lock files, possibly change the configuration, and start the server in a clean-slate mode. (Oracle does not recommend doing this.) If the JMS server cannot find a jms.state file, then it creates a new one.

If, for some reason, the jms.state file itself is corrupted, then the only recourse is to delete it, with the attendant loss of all pending transactions—that is, transactions that have been committed, but the commits not yet performed by all individual destination objects participating in the transactions.

If messaging activity was in progress during abnormal termination, then OEMS JMS tries to recover its persistence files. Any data corruption (of the types mentioned earlier) is handled by clearing out the corrupted data; this may lead to a loss of messages and transactions.

If the headers of a persistence file are corrupted, OEMS JMS may not be able to recover the file, because such a corrupted file is often indistinguishable from user configuration errors. The oc4j.jms.forceRecovery administration property (described in Table 4-6, "System Properties") instructs the JMS server to proceed with recovery, clearing out all invalid data at the cost of losing messages or masking user configuration errors.

Predefined Exception Queue

As an extension to the JMS specification, OEMS JMS In-Memory and File-Based options come with a predefined exception queue for handling undeliverable messages. This is a single, persistent, global exception queue to store undeliverable messages in originating in any OEMS JMS destination. The exception queue has the following fixed properties:

  • A fixed name - jms/Oc4jJmsExceptionQueue

  • A fixed JNDI location - jms/Oc4jJmsExceptionQueue

  • A fixed persistence file - Oc4jJmsExceptionQueue

Note:

The location of the Oc4jJmsExceptionQueue persistence file varies according to whether you are operating OC4J in standalone or Oracle Application Server mode, as follows:
  • Standalone directory: J2EE_HOME/persistence

  • Oracle Application Server directory: J2EE_HOME/persistence/<group_name>

The location of the persistence directory is defined in the application.xml file.

The exception queue is always available to the JMS server and its clients, and should not be explicitly defined in the jms.xml configuration file. Attempting to do so is an error. The name, JNDI location, and persistence path name of the exception queue are reserved words in their respective name spaces. Any attempt to define other entities with these names is an error.

Messages can become undeliverable because of message expiration and listener errors. The following subsection explains what happens to undeliverable messages in case of message expiration.

Message Expiration

By default, if a message sent to a persistent destination expires, then it is moved to the exception queue. The JMSXState of the expiring message is set to the value 3 (indicating EXPIRED), but the message headers, properties, and body are not otherwise modified. The message is wrapped in an ObjectMessage and the wrapping message is sent to the exception queue.

The wrapping ObjectMessage has the same DeliveryMode as the original message.

By default, messages expiring on non persistent or temporary destination objects are not moved to the exception queue. Normally, the messages sent to these destination objects are considered not worth persisting and neither are their expired versions.

You can specify that all expired messages be sent to the exception queue, regardless of whether they are sent to persistent, non persistent, or temporary destination objects, by setting the oc4j.jms.saveAllExpired administration property, described in Table 4-6, "System Properties", to true when starting the OC4J server. In this case, all expired messages are moved to the exception queue. Even though this causes non persistent messages to be sent to the exception queue, it does not change their non persistent nature.

Message Paging

The OEMS JMS In-Memory and File-Based options support paging in and out message bodies under the following circumstances:

  • The message has a persistent delivery mode.

  • The message is sent to a persistent destination object (see "Configuring File-Based Persistence").

  • The destination is a queue, or the destination is a topic and the consumer is a durable subscriber.

  • The amount of used memory in the OC4J server's JVM is above some user-defined threshold.

Only message bodies are paged. Message headers and properties are never paged. You can set the paging threshold through the system property, oc4j.jms.pagingThreshold, described in Table 4-6, "System Properties".

The value ranges from somewhere above 0.0 to somewhere below 1.0. It is almost impossible to write a Java program that uses no JVM memory, and programs almost always die by running out of memory before the JVM heap gets full.

For example, if the paging threshold is 0.5, and the memory usage fraction of the JVM rises to 0.6, the JMS server tries to page out as many message bodies as possible until the memory usage fraction reduces below the threshold, or no more message bodies can be paged out.

When a message that has been paged out is requested by a JMS client, the JMS server automatically pages in the message body (regardless of the memory usage in the JVM) and delivers the correct message header and body to the client. After the message has been delivered to the client, it may once again be considered for paging out, depending on the memory usage in the server JVM.

If the memory usage fraction drops below the paging threshold, then the JMS server stops paging out message bodies. The bodies of messages already paged out are not automatically paged back in. The paging in of message bodies happens only on demand (that is, when a message is dequeued or browsed by a client).

By default, the paging threshold is set to 1.0. In other words, by default, message bodies are never paged.

The user should choose a suitable value for the paging threshold depending on the JMS applications, the sizes of the messages they send and receive, and the results of experiments and memory usage monitoring on real-life usage scenarios.

No value of the paging threshold is ever incorrect. JMS semantics are always preserved regardless of whether paging is enabled or disabled. Control of the paging threshold does allow the JMS server to handle more messages in memory than it might have been able to without paging.

JMS Configuration Properties

Runtime configuration of the OEMS JMS In-Memory and File-Based options and JMS clients is accomplished through JVM system properties. None of these properties affect basic JMS functionality. They pertain to features, extensions, and performance optimizations that are specific to the JMS server. These are the properties that you see when you use the knobs command line command.

The primary tool for editing configuration properties at runtime is the JMSAdministrator MBean.

As a secondary method, in standalone, you can pass the configuration properties in as a command line argument as follows:

java -D<propertyname>=<value>

These property settings are persisted in the jms.xml file.

Path to JMS configuration properties settings in the JMSAdministratorResource MBean:

OC4J:Home > Administration tab > Task Name: JMX.System MBean Browser > Go To Task > Drill down: J2EEDomain:oc4j, J2EEServer:standalone, JMSAdministratorResource, "JMSAdministrator" > Operations tab > setConfigProperty

Table 4-6 lists and describes the system properties for the OEMS JMS resource provider In-Memory and File-Based options.

Table 4-6 System Properties

JVM System Property Server/ Client Description

oc4j.jms.serverPoll

JMS client

Interval (in milliseconds) that JMS connections ping the OC4J server and report communication exceptions to exception listeners.

Type =long. Default = 15000.

oc4j.jms.messagePoll

JMS client

Maximum interval (in milliseconds) that JMS consumers wait before checking for new messages.

Type =long. Default = 1000.

oc4j.jms.listenerAttempts

JMS client

Number of listener delivery attempts before the message is declared undeliverable.

This property only limits the number of delivery attempts when the message is being received by means of a MessageListener registered with JMS using one of the setMessageListener() methods. It does not limit the number of delivery attempts when a message is being received by means of one of the receive methods (except in the case where the message was already declared undeliverable by a previous delivery attempt to a MessageListener). Note that the JMS Connector implements inbound messaging for MDBs using the receive methods, so this property does not apply in that situation. Furthermore, due to J2EE 1.4 restrictions on the use of Message Listeners, this property is only applicable to application clients. For MDBs, the MaxDeliveryCnt activation spec property should be used to limit message delivery attempts. The orion-ejb-jar.xml demo file contains comments describing the MaxDeliveryCnt property.

Type =int. Default = 5.

oc4j.jms.maxOpenFiles

OC4J server

Maximum number of open file descriptors for persistence files. This is relevant if the server is configured with more persistent destination objects than the maximum number of open file descriptors allowed by the operating system.

Type =int. Default = 64.

oc4j.jms.saveAllExpired

OC4J server

Save all expired messages on all destination objects (persistent, nonpersistent, and temporary) to the exception queue.

Type =boolean. Default = false.

oc4j.jms.socketBufsize

JMS client

When using TCP/IP sockets for client/server communication, use the specified buffer size for the socket I/O streams. A minimum buffer size of 8 KB is enforced. The larger the size of messages being transferred between the client and server, the larger the buffer size should be to provide reasonable performance.

Type =int. Default = 64*1024.

oc4j.jms.debug

JMS client

If true, JMS server dumps configurations in startup when JMS log level is fine or higher.

Type = boolean. Default = false.

oc4j.jms.noDms

JMS client

If true, disable instrumentation.

Type =boolean. Default = false.

oc4j.jms.forceRecovery

OC4J server

If true, forcibly recover corrupted persistence files. By default, the JMS server does not perform recovery of a persistence file if its header is corrupted (because this condition is, in general, indistinguishable from configuration errors). Forcible recovery allows the JMS server almost always to start up correctly and make persistence files and destination objects available for use.

Type =boolean. Default = false.

oc4j.jms.pagingThreshold

OC4J server

Represents the memory usage fraction above which the JMS server begins to consider message bodies for paging. This value is an estimate of the fraction of memory in use by the JVM. This value can range from 0.0 (the program uses no memory at all) to 1.0 (the program is using all available memory).

Type =double. Default = 1.0.

See "Message Paging" for more information.

oc4j.jms.pseudoTransactionEnlistment

OC4J server

This property should only be used for backward compatability and is disabled by default. If true, the auto-enlisting feature is enabled. This feature allows non-XA JMS connections as well as XA JMS connections to be automatically enlisted into an OC4J global transaction by the native JMS provider. This feature will no longer be available in future releases.

To enlist an XA or non-XA JMS connection into an OC4J global transaction, do not set this configuration property. Instead:

Use the JMS API's to explicitely enlist an XA connection into an OC4J global transaction using the javax.jms.XA* implementation of OC4J-JMS. In addition, explicitely commit or rollback the local transaction of a given JMS session created from a non-XA JMS connection.


Setting JMS Configuration Properties in the jms.xml File

The following fragment shows how a configuration property is set in the jms.xml file.

<config-properties>
      <config-property name="oc4j.jms.debug" value="true">
      </config-property>
    </config-properties>

This fragment is shown in context in the jms.xml example at "Configuration Using jms.xml". It is also covered in Table 4-1, "Configuration Elements".

Resource Naming for OEMS JMS In-Memory and File-Based

The variable resourceName is used in this section to represent the JNDI location of an RP resource (connection factory or destination) within the resource provider's JNDI context.

The resourceName of an OEMS JMS resource is specified as a JNDI location in the console as described in Configuring Destination Objects and Connection Factories. Connection factory resourceName values are used to identify a specific OEMS JMS connection factory (as the link-key for arrow #16 in Figure 4-1). Destination resourceName values are used to identify a specific OEMS JMS destination (as the link-key for arrow #13 in Figure 4-1). Connection factory and destination resourceName values may also be used when bypassing the JMS Connector as discussed in Bypassing the JMS Connector for Application Clients.

Required Class Path for Application Clients Using Direct OEMS JMS In-Memory and File-Based Lookup

When using OEMS JMS In-Memory and File-Based options directly from an application client, the JAR files that must be included in the class path are listed inTable 4-7, "Client-side JAR Files Required for OEMS JMS In-Memory and File-Based Lookup".

Table 4-7 Client-side JAR Files Required for OEMS JMS In-Memory and File-Based Lookup

JAR ORACLE_HOME Path

oc4jclient.jar

/j2ee/<instance>

jta.jar

/j2ee/<instance>/lib

jms.jar

/j2ee/<instance>/lib

jndi.jar

/j2ee/<instance>/lib

javax77.jar

/j2ee/<instance>/lib

optic.jar

(Required only if the opmn:ormi prefix is used in Oracle Application Server environment.)

/opmn/lib


OEMS JMS Database Persistence

The OEMS JMS Database persistence option is the JMS interface to the Oracle Database Streams Advanced Queuing (AQ) feature. This section details the configuration and usage of OEMS JMS using AQ as the persistent store for messages.

As with the OEMS JMS In-Memory and File-Based options, Oracle recommends that your applications use the JMS Connector when accessing AQ through the OEMS JMS Database option.

For details about configuring OEMS JMS with AQ, see the Oracle Streams Advanced Queuing User's Guide and Reference.

This section describes the following topics:

Note:

In past Oracle Application Server documentation and collateral, as well as in the the Oracle Streams Advanced Queuing User's Guide and Reference, you will see the OEMS JMS Database persistence option described as "OJMS". When you encounter the acronym, "OJMS", it is describing the OEMS JMS Database persistence option.

Using the OEMS JMS Database Option

To create and access OEMS JMS Database resource provider destination objects (queues and topics), do the following:

Install and Configure OEMS JMS Database

You or your DBA must install OEMS JMS according to the Oracle Streams Advanced Queuing User's Guide and Reference and generic database manuals. After you have installed and configured OEMS JMS, you must apply additional configuration. This includes the following:

  1. You or your DBA must create an RDBMS user through which the JMS client connects to the database. Grant this user appropriate access privileges to perform OEMS JMS operations. OEMS JMS allows any database user to access queues in any schema if the user has the appropriate access privileges. See "Create User and Assign Privileges".

  2. You or your DBA must create the tables and queues to support the JMS destination objects. See "Creating OEMS JMS Database Destination Objects".

    Note:

    The following sections use SQL for creating queues, topics, and their tables, and for assigning privileges.

    For examples, see http://www.oracle.com/technology/tech/java/oc4j/1013/how_to/index.html.

Create User and Assign Privileges

Create an RDBMS user through which the JMS client connects to the database. Grant access privileges to this user to perform OEMS JMS operations. The privileges that you need depend on what functionality you are requesting. Refer to the Oracle Streams Advanced Queuing User's Guide and Reference for more information on privileges necessary for each type of function.

The following example creates jmsuser, which must be created within its own schema, with privileges required for OEMS JMS operations. You must be a SYS DBA to execute these statements.

DROP USER jmsuser CASCADE ;

GRANT connect,resource,AQ_ADMINISTRATOR_ROLE TO jmsuser 
   IDENTIFIED BY jmsuser ;
GRANT execute ON sys.dbms_aqadm  TO  jmsuser;
GRANT execute ON sys.dbms_aq     TO  jmsuser;
GRANT execute ON sys.dbms_aqin   TO  jmsuser;
GRANT execute ON sys.dbms_aqjms  TO  jmsuser;

connect jmsuser/jmsuser;

You may need to grant other privileges, such as two-phase commit or system administration privileges, based on what the user needs. See Chapter 3, "OC4J Transaction Support", for information on two-phase commit privileges.

Creating OEMS JMS Database Destination Objects

Refer to the Oracle Streams Advanced Queuing User's Guide and Reference for information on the DBMS_AQADM packages and OEMS JMS Database messages types.

The following examples demonstrate creating a queue and a topic in OEMS JMS Database.

  1. Create the table that handles the OEMS JMS destination (queue or topic).

    Both topics and queues use a queue table. The following SQL example creates a single table, demoTestQTab, for a queue.

    DBMS_AQADM.CREATE_QUEUE_TABLE(
            Queue_table            => 'demoTestQTab',
            Queue_payload_type     => 'SYS.AQ$_JMS_MESSAGE',
            sort_list => 'PRIORITY,ENQ_TIME',
            multiple_consumers  => false,
            compatible             => '8.1.5');
    

    The multiple_consumers parameter specifies whether there are multiple consumers. Set multiple_consumers to false for a queue. Set multiple_consumers to true for a topic.

  2. Create the JMS destination. This SQL example creates a queue called demoQueue within the queue table demoTestQTab and then starts the queue.

    DBMS_AQADM.CREATE_QUEUE(
          Queue_name          => 'demoQueue',
          Queue_table         => 'demoTestQTab');
    
    DBMS_AQADM.START_QUEUE(
          queue_name         => 'demoQueue');
    

Example:

The following example shows how you can create a topic called demoTopic within the topic table demoTestTTab. After creation, two durable subscribers are added to the topic. Finally, the topic is started.

Note:

OEMS JMS Database uses the DBMS_AQADM.CREATE_QUEUE method to create both queues and topics.
DBMS_AQADM.CREATE_QUEUE_TABLE(
        Queue_table            => 'demoTestTTab',
        Queue_payload_type     => 'SYS.AQ$_JMS_MESSAGE',
        multiple_consumers  => true,
        compatible             => '8.1.5');
DBMS_AQADM.CREATE_QUEUE( 'demoTopic', 'demoTestTTab');
DBMS_AQADM.START_QUEUE('demoTopic');

Note:

OEMS JMS Database incorporates the (Queue_name) names passed into the DBMS_AQADM.CREATE_QUEUE method into the JNDI names for the destinations. For example, OEMS JMS Database makes the queue created with Queue_name "demoQueue" available with the JNDI name "Queues/demoQueue".

In order to wrap an OEMS JMS destination with a JMS Connector destination, the OEMS JMS-provided JNDI name for the destination and the "jndiName" <config-property> for the JMS Connector destination defined in the oc4j-connectors.xml file (either the global one in $J2EE_HOME/config or a local one optionally contained in an application's .ear file) must match. See arrow #13 in Figure 4-1, "JMS Configuration"

Declaring the OEMS JMS Database Reference

For an overview of declaring the resource provider reference, see "Declaring Resource Provider References".

The two pieces of information you must provide whenever declaring a resource provider reference are the name you wish to use for the resource provider reference and the Java class that implements the resource provider interface.

For OEMS JMS Database, the class is oracle.jms.OjmsContext. To declare a resource provider reference named OJMSReference, use:

<resource-provider class="oracle.jms.OjmsContext" name="OJMSReference">    ...    </resource-provider>

For example, if the OEMS JMS reference is named OJMSReference, and the JNDI location (within the resource provider's JNDI context of a resource provider queue is Queues/MY_QUEUE, then that resource provider queue is accessible to the application and resource adapter at JNDI location java:comp/resource/OJMSReference/Queues/MY_QUEUE.

In general, use the following steps to declare an OEMS JMS reference:

  1. First create a local data-source in the data-sources.xml file. The demo set has an example of this at: /ojms/src/META-INF/data-sources.xml.

  2. Then tell OC4J where the data-sources.xml file has been placed by adding a <data-sources> element to orion-application.xml:

    <data-sources path="data-sources.xml"/>
    

    Note that the data-sources path is relative to the orion-application.xml file.

  3. Finally, set the datasource for the resource provider reference by adding a <property> subelement to the previously created <resource-provider> element:

    <resource-provider class="oracle.jms.OjmsContext" name="OJMSReference">
            <property name="datasource" value="jdbc/xa/MyChannelDemoDataSource"></property>
        </resource-provider>
    

    Configuring data sources is discussed in the "Data Sources" chapter of this guide. When selecting which driver to use (OCI or thin), it is best to measure actual application performance. The OCI driver may be faster for non-XA operations, but can be significantly slower than the thin driver for XA operations.

For a list of the How-To documents and demo sets and their URLs, see "JMS How-To Documents and Demo Sets".

Resource Naming for OEMS JMS Database

The resourceName of an OEMS JMS Database resource is:

typeName/instanceName

The values for typeName and instanceName depend on the type of resource (connection factory or destination), and are described next.

For OEMS JMS Database connection factories:

typeName corresponds to the connection factory type and is one of the following:

  • ConnectionFactories

  • QueueConnectionFactories

  • TopicConnectionFactories

  • XAConnectionFactories

  • XAQueueConnectionFactories

  • XATopicConnectionFactories

instanceName can be anything (because it is ignored - OEMS JMS Database connection factories are not customizable so there is no need for multiple instances of the same connection factory type).

For example, the resourceName for an OEMS JMS Database non-XA queue connection factory (where the ignored instanceName is arbitrarily set to myQCF) is:

QueueConnectionFactories/myQCF

Connection factory resourceName values created as described in the preceding instructions are used to identify a specific OEMS JMS Database connection factory (that is, as the link-key for arrow #16 in Figure 4-1, "JMS Configuration"). They may also be used when bypassing the resource adapter as discussed in Bypassing the JMS Connector for Application Clients.

The following table shows the javax.jms.* interfaces implemented.

Table 4-8 javax.jms.* Interfaces Implemented

typeName CF QCF TCF XACF XAQCF XATCF

ConnectionFactories

X

         

QueueConnectionFactories

X

X

       

TopicConnectionFactories

X

 

X

     

XAConnectionFactories

X

   

X

   

XAQueueConnectionFactories

X

X

 

X

X

 

XATopicConnectionFactories

X

 

X

X

 

X


If the application requires a javax.jms.TopicConnectionFactory (as specified by the <res-type> element), the only type names that will return a suitable connection factory are "TopicConnectionFactories" and "XATopicConnectionFactories".

For OEMS JMS Database destinations:

typeName corresponds to the destination type and is one of the following:

  • Queues

  • Topics

Note:

A destination is a queue (typeName = Queues) if the multiple_consumers parameter passed to DBMS_AQADM.CREATE_QUEUE_TABLE was false. Otherwise the destination is a topic (typeName = Topics).

instanceName is the name of the destination (the Queue_Name parameter provided to DBMS_AQADM.CREATE_QUEUE). If the destination is not owned by the user specified in the username property in the <resource-provider> element, then instanceName must be prefixed with "owner." where owner is the owner of the destination. (Even when not required, the "owner." prefix is still allowed.)

For example, the resourceName for an OEMS JMS Database queue given the name demoQueue in the call to DBMS_AQADM.CREATE_QUEUE is:

Queues/demoQueue

If the owner (for example, someUser) needs to be specified, then the resourceName would be:

Queues/someUser.demoQueue

Destination resourceName values created according to the preceding instructions are used to identify a specific OEMS JMS Database destination (that is, as the link-key for arrow #13 in Figure 4-1). They may also be used when bypassing the resource adapter as discussed in Bypassing the JMS Connector for Application Clients.

Sending and Receiving Messages Using OEMS JMS Database Persistence

Oracle recommends that the application use the JMS Connector for sending and receiving messages. In this way the sending and receiving code can be independent of the resource provider used. The examples at "Sending and Receiving JMS Messages" can be used for all resource providers, including OEMS JMS Database, with only the passed-in destination and connection factory locations being different.

Required Class Path for Application Clients Using Direct OEMS JMS Database Lookup

When using OEMS JMS Database options directly from an application client, the JAR files that must be included in the class path are listed inTable 4-9, "Client-side JAR Files Required for OEMS JMS Database Lookup".

Table 4-9 Client-side JAR Files Required for OEMS JMS Database Lookup

JAR ORACLE_HOME Path

oc4jclient.jar

/j2ee/<instance>

ejb.jar

/j2ee/<instance>/lib

jta.jar

/j2ee/<instance>/lib

jms.jar

/j2ee/<instance>/lib

jndi.jar

/j2ee/<instance>/lib

javax77.jar

/j2ee/<instance>/lib

adminclient.jar

/j2ee/<instance>/lib

ojdbc14dms.jar

/j2ee/<instance>/../../oracle/jdbc/lib

dms.jar

/j2ee/<instance>/../../oracle/lib

bcel.jar

/j2ee/<instance>/lib

optic.jar

(Required only if the opmn:ormi prefix is used in Oracle Application Server environment.)

/opmn/lib


Using OEMS JMS Database with the Oracle Application Server and the Oracle Database

This section discusses common issues encountered by users of OEMS JMS Database with Oracle Application Server.

Error When Copying aqapi.jar

A common error encountered when using the OEMS JMS database option with the Oracle Application Server is:

PLS-00306 "wrong number or types of arguments"

If you receive this message, then the aqapi.jar file being used in the Oracle Application Server is not compatible with the version of the Oracle Database being used for AQ. The previous Oracle Databases that are supported with the current version of the OEMS JMS database option are: 9.0.1.4, 9.2.0.2+, 10.1.0+, and 10.2.0+.

The Oracle Application Server and the Oracle Database both ship the OEMS JMS client JAR file. A common mistake is to copy the aqapi.jar file from the Oracle database installation into the Oracle Application Server installation (or from the Oracle Application Server installation into the Oracle database installation) under the false assumption that they are interchangeable. Do not copy this file from either installation.

In an Oracle Application Server installation, the OEMS JMS Database client JAR file can be found at ORACLE_HOME/rdbms/jlib/aqapi.jar and should be included in the CLASSPATH.

Preserving Ordering When Using Message Selectors

When using message selectors in database persistence mode, and if ordering is important, users should set the Java system property oracle.jms.orderWithSelector to True. By default, this property is set to false.The use of this system property requires ALTER SESSION privileges for AQ users. Also, because it translates into an additional ORDER BY clause, setting this property to true has a negative impact on performances.

Using Third-Party JMS Providers

This section briefly discusses declaring references to the supported third-party JMS resource providers.

OC4J supports two-phase commit (2pc) for all supported resource providers as long as the resource provider has an XA interface and the JMS Connector and application are configured to use it. All of the supported third party providers have an XA interface.

The versions of each third-party JMS provider that OC4J supports are listed at Using Third-Party JMS Providers.

This section provides information on declaring references for the following third-party JMS providers:

The context-scanning resource provider class is a generic resource provider class shipped with OCJ for use with third-party message providers.

Note:

To declare a resource provider reference, use one or the other of the following files:
  • To make the resource provider reference visible to all applications (global), then use the global application.xml file.

  • To make the resource provider reference visible to a single application (local), then use the orion-application.xml file specific to the application.

Declaring an IBM WebSphere MQ Resource Provider Reference

WebSphere MQ is an IBM messaging provider. WebSphere MQ resources are available under

java:comp/resource/providerName 

where providerName is the name used in the <resource-provider> element.

To declare a WebSphere MQ resource provider reference, perform the following steps:

  1. Install and configure WebSphere MQ on your system, then verify the installation by running any examples or tools supplied by the vendor. See the documentation supplied with the WebSphere MQ software for instructions.

  2. Add WebSphere MQ as a custom resource provider.

    The following example demonstrates using the <resource-provider> element in the orion-application.xml file to declare a WebSphere MQ resource provider reference.

    <resource-provider
        class="com.evermind.server.deployment.ContextScanningResourceProvider"
        name="MQSeries">
      <description> MQSeries resource provider </description>
      <property
          name="java.naming.factory.initial"
          value="com.sun.jndi.fscontext.RefFSContextFactory">
      </property>
      <property
          name="java.naming.provider.url"
          value="file:/home/developer/services_guide_demo/mqseries/src/bindings">
      </property>
    </resource-provider>
    

    This example shows how this configuration was accomplished in the demo set. It applies to the demo author's environment only and must be edited to work in any other environment.

  3. Add to J2EE_HOME/applib any JAR files required by a Websphere MQ JMS client as described in the IBM documentation.

    The section "Resource Provider Task #3: Declare a Resource Provider Reference" in the how-to-gjra-with-mqseries.html document in the demo set has more detail.

For a list of the How-To documents and demo sets and their URLs, see "JMS How-To Documents and Demo Sets".

Declaring a TIBCO Enterprise Message Service Resource Provider Reference

TIBCO Enterprise Message Service is a message provider from TIBCO Software. TIBCO resources are available under

java:comp/resource/providerName
 

where providerName is the name used in the <resource-provider> element.

To declare a TIBCO resource provider reference, perform the following steps:

  1. Install and configure TIBCO Enterprise Message Service on your system, then verify the installation by running any examples or tools supplied by the vendor. See the documentation supplied with the TIBCO software for instructions.

  2. Add TIBCO as a custom resource provider. The following example demonstrates using the <resource-provider> element in the orion-application.xml file to declare a TIBCO resource provider reference.

    <resource-provider
           class="com.evermind.server.deployment.ContextScanningResourceProvider"
           name="TibcoJMSReference">
            <property 
                name="java.naming.factory.initial" 
                value="com.tibco.tibjms.naming.TibjmsInitialContextFactory">
            </property>
            <property 
                name="java.naming.provider.url" 
                value="tibjmsnaming://jleinawe-sun:7222">
            </property>
        </resource-provider>
    

    This example shows how this configuration was accomplished in the demo set. It applies to the demo author's environment only and must be edited to work in any other environment.

  3. Add to J2EE_HOME/applib any JAR files required by a TIBCO JMS client as described in the TIBCO documentation.

    The section "Resource Provider Task #3: Declare a Resource Provider Reference" in the how-to-gjra-with-tibco.html document in the demo set has more detail.

For a list of the How-To documents and demo sets and their URLs, see "JMS How-To Documents and Demo Sets".

Declaring a SonicMQ Resource Provider Reference

SonicMQ is a messaging provider from Sonic Software Corporation. Sonic resources are available under

java:comp/resource/providerName
 

where providerName is the name used in the <resource-provider> element.

To declare a SonicMQ resource provider reference, perform the following steps:

  1. Install and configure SonicMQ on your system, then verify the installation by running any examples or tools supplied by the vendor. See the documentation supplied with the Sonic software for instructions.

  2. Add SonicMQ as a custom resource provider. The following example demonstrates using the <resource-provider> element in the orion-application.xml file to declare a SonicMQ resource provider reference.

    <resource-provider
           class="com.evermind.server.deployment.ContextScanningResourceProvider"
           name="SonicJMSReference">
            <property
                name="java.naming.factory.initial"
                value="com.sonicsw.jndi.mfcontext.MFContextFactory">
            </property>
            <property 
                name="java.naming.provider.url"
                value="tcp://stadd41:2506">
            </property>
            <property
                name="com.sonicsw.jndi.mfcontext.domain"
                value="Domain1">
            </property>
        </resource-provider>
    

    This example shows how this configuration was accomplished in the demo set. It applies to the demo author's environment only and must be edited to work in any other environment.

  3. Add to J2EE_HOME/applib any JAR files required by a SonicMQ JMS client as described in the Sonic documentation.

    The section "Resource Provider Task #3: Declare a Resource Provider Reference" in the how-to-gjra-with-sonic.html document in the demo set has more detail.

For a list of the How-To documents and demo sets and their URLs, see "JMS How-To Documents and Demo Sets".

JMS Connector

Oracle Application Server provides a J2CA 1.5-compliant resource adapter called the JMS Connector. The JMS Connector provides applications with a unified mechanism for accessing any JMS provider that implements JMS 1.1 or 1.02b. OracleASjms is an instance of the JMS Connector that is already configured for use with the OEMS JMS in-Memory and File-Based options. The JMS Connector does not use any Oracle proprietary APIs. Supported JMS implementations include OEMS JMS and third-party products such as IBM Websphere MQ JMS, TIBCO Enterprise Message Server, and SonicMQ JMS.

The JMS Connector is recommended when using JMS in OC4J implementation. It is based on the J2CA 1.5 and JMS 1.1 and 1.02b standards and includes minimal customization for OC4J, and none for individual JMS providers. It is intended to seamlessly integrate any standard JMS implementation.

Note:

The JMS Connector does not typically provide optimal access to a particular JMS provider, because many JMS providers utilize custom extensions.

The JMS Connector includes features in the following areas:

Typically, the JMS Connector is used in situations where the EIS being connected is a JMS resource provider. However, it can also be used in situations where the EIS uses JMS messaging as a means of notifying J2EE application components. In this case, the resource adapter (along with a JMS resource provider) can be used instead of the inbound communication features (if any) of the EIS-specific resource adapter. This two-adapter solution, where the EIS-specific adapter is used for outbound communication and the JMS Connector is used for inbound communication, enables bidirectional communication between the EIS and J2EE applications where it may otherwise not be possible.

For more information on resource adaptors see the Oracle Containers for J2EE Resource Adapter Administrator's Guide.

Modifying the JMS Connector

The JMS Connector provided with OC4J is configured out-of-the-box to support the OEMS JMS In-Memory and File-Based persistence options. If you need to integrate with the OEMS JMS Database option or one of the supported non-Oracle JMS providers, then you must create another configuration for the JMS Connector. Another reason you may want to create another JMS Connector is to support an application-local adapter to connect to the OEMS JMS In-Memory and File-Based options.

For a list of the How-To documents and demo sets and their URLs, see "JMS How-To Documents and Demo Sets".

Create and configure a new JMS Connector module as follows:

  1. Go to the demo set for the resource provider to be connected.

  2. Read the How-to document.

  3. Copy the following files to be used as templates for your new JMS Connector module:

    • ra.xml

    • oc4j-ra.xml

    • oc4j-connectors.xml

  4. Modify the ra.xml, the oc4j-ra.xml, and the oc4j-connectors.xml files according to the instructions at "Configuring the Resource Adapter" in the How-to document.

  5. Create a new .rar file (You can name it whatever you want.) with the following structure:

    META-INF/ra.xml

    META-INF/oc4j-ra.xml

  6. Place the new oc4j-connectors.xml in one of the following locations according to the desired level of visibility:

    • For application-local visibility, place the new oc4j-connectors.xml file in the top-level META-INF/ directory of your application's .ear file

      For global visibility, copy the new <connector> element(s) into the $J2EE_HOME/config/oc4j-connectors.xml file. Make sure the name of your new connector (the <connector>'s name attribute) does not conflict with the name of other connectors or any other JNDI objects.

  7. Prepare deployment as follows:

    • For local visibility, do the following:

      • Place the new .rar file in the .ear file.

      • Insert a <connectors> element that looks like the following into the META-INF/orion-application.xml file in the .ear file.

        <connectors path="oc4j-connectors.xml"/>
        
      • Insert a <module> element that looks like the following into the META-INF/application.xml file in the .ear file.

        <module>
            <connector>rarFileName</connector>
        </module>
        
    • For global visibility, follow the instructions for deploying a connector in the Oracle Containers for J2EE Deployment Guide

Configuring the JMS Connector

The Application Server Control Console is the primary tool for configuring the JMS Connector.

Connection Factories and Destinations

The default application defines the following destination objects for the default JMS Connector:

  • A queue bound to JNDI location OracleASjms/MyQueue1.

  • A topic bound to JNDI location OracleASjms/MyTopic1.

  • An automatic destination wrapping JNDI subcontext for queues bound to JNDI location OracleASjms/Queues.

  • An automatic destination wrapping JNDI subcontext for topics bound to JNDI location OracleASjms/Topics.

Applications can use these destinations and automatic destination wrapping JNDI subcontexts without first having to define the destinations in the Console or the JMSAdministrator MBean. When using the automatic destination wrapping feature, the JNDI lookup name would be in the form:

<JNDIsubcontext>/providerName

where <JNDIsubcontext> is the automatic destination wrapping JNDI subcontext as specified in the oc4j-connectors.xml file. For example, if automatic destination wrapping is used with the JMS Connector, the JNDI name would be of the form:

OracleASjms/Queues/jms/<queue_name>

or

OracleASjms/Topics/jms/<topic_name>

The JMS Connector default connection factories are as follows:


XA non-XA
Default Queue Connection Factory OracleASjms/MyXAQCF OracleASjms/MyQCF
Default Topic Connection Factory OracleASjms/MyXATCF OracleASjms/MyTCF
Default Unified Connection Factory OracleASjms/MyXACF OracleASjms/MyCF

The default connection factories in the table are explicitly declared in the default oc4j-ra.xml file that ships with OC4J).

Destinations for Database Persistence

Automatic destination wrapping is also available when customizing the JMS Connector in order to use OEMS JMS Database option. As with the default connector, previously described, the JNDI lookup name would be in the form:

<JNDIsubcontext>/providerName

where <JNDIsubcontext> is the automatic destination wrapping JNDI subcontext as specified in the oc4j-connectors.xml file and the <providerName> would be the physical database destination preceded by Queues or Topics respectively.

For example, if automatic destination wrapping is used with an OEMS Database JMS Connector, deployed with a JNDIsubcontext of OracleDB/wrap, the JNDI names for the database would be of the form:

OracleDB/wrap/Queues/<queue_name>

or

OracleDB/wrap/Topics/<topic_name>

Creating JMS Connector connection factories and destinations

For information on configuring the JMS Connector connection factories and destinations, including examples of the oc4j-connectors.xml, oc4j-ra.xml, and ra.xml files, go to: http://www.oracle.com/technology/tech/java/oc4j/1013/how_to/index.html

Download and unzip the relevant how-to-gjra-with-xxx.zip file, where xxx is the name of the resource provider. Search for "Configuring the Resource Adapter" in the relevant How-To document.

For detailed reference information on the JMS Connector XML files, go to "Appendix A, OC4J Resource Adapter Configuration Files" of the Oracle Containers for J2EE Resource Adapter Administrator's Guide

JMS Connector Settings

Table 4-10 lists and describes the JMS Connector configuration settings.

Path to JMS Connector Settings in the Application Server Control Console:

OC4J:Home > Applications tab > View: Standalone Resource Adapters > OracleASjms

Table 4-10 JMS Connector Configuration Settings

Console Settings XML Persistence File(s) Description

OC4J:Home > Applications tab > View: Standalone Resource Adapters > OracleASjms > Connection Factories tab > Create button

Connection Factory Interface

This is the link-reference for arrow #14 in Figure 4-1.

This setting is persisted in the <connectionfactory-interface> element of the oc4j-ra.xml file.

The Connection Factory Interface setting defines the type of connection factory to be created.

JNDI Location

This is the link-key for arrow #5 in Figure 4-1.

This setting is persisted in the location attribute of a <connector-factory> element of the oc4j-ra.xml file.

The JNDI Location setting specifies the JNDI location where the new resource adapter connection factory is to be bound. Enter a valid JNDI location so the application component can locate the connection factory when it needs to connect to the EIS.

Note that "JNDI Location" is not the same as "jndiLocation".

Connection Pooling

This setting is persisted in the <connection-pooling> element of the oc4j-ra.xml file.

Connection pooling allows a set of connections to the EIS to be reused within an application. An application can choose to either create its own exclusive connection pool or use one of the shared connection pools available for this resource adapter.

No Connection Pool - Select this option to disable connection pooling.

Use Private Connection Pool - Select this option to create a new connection pool for exclusive use by the selected connection factory.

Use Shared Connection Pool - Select this option to use a shared connection pool that can be used by multiple connection factories.

The oc4j-ra.xml file contains OC4J-specific configuration for the JMS Connector. Subelements of <connector-factory> include <connection-pooling>, to set up connection pooling for the factory, and <security-config>, to set up container-managed sign-on. Each connector factory can have configuration for a private connection pool, or can use a shared connection pool that is set up through a <connection-pool> subelement of <oc4j-connector-factories>.

jndiLocation

This is the link-reference for arrow #16 in Figure 4-1.

This setting is persisted in a <config-property> subelement of a <connector-factory> element of the oc4j-ra.xml file.

The jndiLocation setting specifies the resource provider connection factory to be wrapped by the resource adapter connection factory that you are creating.

Note that "jndiLocation" is not the same as "JNDI Location".

<none>

This setting is persisted in a <config-property> subelement of a <connector-factory> element of the oc4j-ra.xml file.

The clientId setting specifies what client id should be applied to any newly created resource provider connection created by the JMS Connector connection.

OC4J:Home > Applications tab > View: Standalone Resource Adapters > OracleASjms > Administered Objects tab > Create button

Object Class

This setting is persisted in an <adminobject-class> subelement of an <adminobject-config> element of the oc4j-connectors.xml file.

The Object Class setting defines the type of administered object (destination) to be created. Select from the drop-down list.

JNDI Location

This is the link-key for arrows #7 and #11 in Figure 4-1.

This setting is persisted in the location attribute of an <adminobject-config> element of the oc4j-connectors.xml file.

The JNDI Location setting specifies the JNDI location where the new resource adapter administered object (destination) is to be bound.

jndiName

This is the link-reference for arrow #13 in Figure 4-1.

This setting is persisted in the value attribute of a <config-property> subelement of a <adminobject-config> element of the oc4j-connectors.xml file.

The jndiName setting is the JNDI name of the resource provider destination to be wrapped by the resource adapter administered object (destination) that you are creating.

Note: This description of the jndiName setting applies to individually-bound resource provider queues and topics. See the comments in the oc4j-connectors.xml files in the demo set for more information.

resourceProviderName

This is the link-reference for arrow #12 in Figure 4-1.

This setting is persisted in the value attribute of a <config-property> subelement of a <adminobject-config> element of the oc4j-connectors.xml file.

The resourceProviderName setting identifies the resource provider that owns the destination to be wrapped by the resource adapter administered object (destination) that you are creating.

ResourceAdapter> Administration>

enableDMS

This setting persists in a <config-property> subelement of <resourceadapter> subelement of ra.xml.

This setting also persists in a <config-propety> subelement of <connector> subelement of oc4j-connector.xml.

The oc4j-connector.xml file takes precedence over the ra.xml.

This property specify whether the JMS resource adapter collects the DMS performance metrics. This property is set to true by default. When this property is set to false, the JMS resource adapter stops collecting any DMS performance metrics.

ResourceAdapter> Administration>

loggerName

This setting persists in a <config-property> subelement of <resourceadapter> subelement of ra.xml.

This setting also persists in a <config-propety> subelement of <connector> subelement of oc4j-connector.xml.

The oc4j-connector.xml file takes precedence over the ra.xml.

This property specifies the name of the logger that handles the logging of this JMS resource adapter. User can define a logger in j2ee-logging.xml. The default value for this property is null (when null, the logger name is set to oracle.j2ee.ra.jms.generic.


Configuring the JMS Connector in the XML Files

The JMS Connector configuration settings are persisted in the following files:

  • oc4j-connectors.xml - The oc4j-connectors.xml file is used to create JMS Connector instances and JMS Connector destinations.

  • oc4j-ra.xml - The oc4j-ra.xml file contains OC4J-specific configuration for a JMS Connector. When you use Application Server Control Console to create or edit a JMS Connector connection factory, OC4J updates the oc4j-ra.xml file.

  • ra.xml - The standard JMS Connector module configuration file provided by Oracle. When you configure a JMS Connector, entries in ra.xml typically serve as defaults.

For detailed examples of the oc4j-connectors.xml, the oc4j-ra.xml, and the ra.xml files, go to: http://www.oracle.com/technology/tech/java/oc4j/1013/how_to/index.html

For detailed reference information on the JMS Connector XML files, go to Appendix A, OC4J Resource Adapter Configuration Files of the Oracle Containers for J2EE Resource Adapter Administrator's Guide.

Note:

You must restart the OC4J instance to enable configuration changes made directly in the XML files.

Using Message-Driven Beans

OC4J supports MDBs using the JMS Connector to plug in a message provider. The providers include OEMS JMS as well as the supported third-party message providers. This offers significant advantages such as JMS connection pooling, and MDB listener thread sets that size themselves according to changing load (dynamic load adjustment).

A full example of using MDB is included in the messaging demos located at: http://www.oracle.com/technology/tech/java/oc4j/1013/how_to/index.html

Download and unzip one of the how-to .zip files. MDB example configuration can be viewed in the following files: /src/ejb/META-INF/ejb-jar.xml and /src/ejb/META-INF/orion-ejb-jar.xml

Connection Pooling

The JMS Connector uses J2CA connection pooling. For information on connection pooling, see the Oracle Containers for J2EE Resource Adapter Administrator's Guide

Fine Tuning MDB Endpoints

Each MDB endpoint is associated with a set of configuration properties (referred to as ActivationSpec properties). The properties are used when the JMS connector activates a message endpoint and associates the message endpoint with a message-driven bean. The properties are used to manipulate among other things: performance, logging, exception queues, message acknowledgment, and subscriptions.

The properties are typically set in the orion-ejb-jar.xml. However, the properties can also be set in the ejb-jar.xml file if the JMS connector is included in an application's .ear file. The syntax for each file is different.

When using the orion-ejb-jar.xml, the properties are added to each <message-driven-deployment> node, using the following syntax:

<config-property>
   <config-property-name>ExamplePropertyName</config-property-name>
   <config-property-value>ExampleValue</config-property-value>
</config-property>

When using the ejb-jar.xml file, the properties are added to each <message-driven> node, using the following syntax:

<activation-config-property>
   <activation-config-property-name>ExamplePropertyName
   </activation-config-property-name>
   <activation-config-property-value>ExampleValue
   </activation-config-property-value>
</activation-config-property>

The following table describes the configuration properties that can be used to fine tune an MDB endpoint.

Table 4-11 MDB Configuration Properties

Configuration Properties Description

ReceiverThreads

(integer, default = 1)

This sets the maximum number of listener threads to create for this endpoint. For queues, using more than one thread may be useful in increasing the rate at which messages can be consumed. For topics this value should always be 1. (Each listener thread gets its own session and TopicSubscriber. For durable subscribers it would be an error to have more than one subscriber with the same subscription name. For nondurable subscribers having more than one thread will not help because more threads translates into more subscribers which translates into more copies of each message.) See also: ListenerThreadMinBusyDuration.

ListenerThreadMaxPollInterval

(milliseconds, default = 5000)

Listener threads "poll" to see if there is a message waiting to be processed. The more frequently this polling is performed, the faster (on average) a given listener thread can respond to a new message. The price for frequent polling is overhead - the resource provider must process a receive request each time it is polled.

Oracle's JMS Connector implementation applies an adaptive algorithm which uses shorter polling intervals (high polling rates) during periods of activity (once activity is noticed) and longer polling intervals (lower polling rates) during periods of inactivity. The ListenerThreadMaxPollInterval property places an upper limit on the polling interval used by this adaptive algorithm.

ListenerThreadMaxIdleDuration

(milliseconds, default = 300000)

This is how long a listener thread which is not receiving any messages will be kept around. (At least one listener thread will remain as long as the endpoint is active.)

ListenerThreadMinBusyDuration

(milliseconds, default = 10000)

If a listener thread has just received a message, has not been idle (had to wait for a new message to arrive) at any point during the past ListenerThreadMinBusyDuration milliseconds, and the current number of listener threads for this endpoint is less than ReceiverThreads, the (application server willing) an additional listener thread will be created.

MaxDeliveryCnt

(integer, default = 5)

If a message has the "JMSXDeliveryCount" property and the value of that property is greater than MaxDeliveryCnt, then the message will be discarded (and not sent to onMessage). If the exception queue is enabled (see UseExceptionQueue), a copy of the message will be sent to the exception queue. If MaxDeliveryCnt is set to 0, no messages will be discarded. (Note that when an MDB responds to a message by throwing an exception, the message is not considered delivered and it may be redelivered. If the MDB might always respond to a given message by throwing an exception, and MaxDeliveryCnt is set to 0 to prevent the message from ever being discarded, the result may be an MDB stuck in an "infinite loop" - failing to process the same message over and over again.)

EndpointFailureRetryInterval

(milliseconds, default = 60000)

Listener threads are automatically ended on JMS provider failures. (For example, if a listener thread call to MessageConsumer.recieve() results in an exception.) If all listener threads end while the endpoint is still supposed to be running, this is an "endpoint failure" - the MDB cannot receive messages in this state. This may happen, for example, due to a sustained network failure or if the JMS server is not up. In this situation, the JMS Connector will attempt to start a new listener thread (and reconnect with the JMS provider) every EndpointFailureRetryInterval milliseconds until it is either successful or the endpoint is shut down. Once a listener thread is successfully created, listener thread management returns to its normal behavior. (See ReceiverThreads, ListenerThreadMaxIdleDuration and ListenerThreadMinBusyDuration.) Note that while this provides nearly transparent recovery from a connection failure, it is not 100% transparent in all cases:

  • Since it requires the creation of a new JMS session, and JMS message ordering guarantees only apply to messages received within a single session, messages received after the reconnect may not be ordered with respect to messages received before the reconnect. Whether or not this is the case depends on the behavior of the JMS provider. (JMS providers which provide total message ordering, which is a stricter ordering than is required by JMS, will not exhibit any message ordering issues.)

  • If the endpoint is a non-durable subscriber, messages may be lost or duplicated. This problem will not happen when using queues or when using topics with durable subscribers. Whether or not message loss/duplication happens in practice (and which of the two problems happen) may be subject to the specific behavior of the JMS provider. To avoid this problem, do not use non-durable subscribers in combination with JMS provider connections which may fail.

ClientId

(string, no default)

If set, connection(s) used by the listener threads will be set to use this client ID.

ResUser, ResPassword

(string, default = null)

These properties allow a user/password to be passed to the resource provider. When neither of these properties are set, connections used for this MDB's inbound message handling (as well as for exception queue handling, if enabled) are created using the no-argument version of the create*Connection method. When one or both of these properties are set, they are passed to the create*Connection method as the user/password arguments. (If only one property is not set, then 'null' is used for that particular create*Connection argument.) The ResPassword property supports the standard password indirection options (for example, using "->joeuser" to represent the password of "joeuser").

AcknowledgeMode

(string, default = Auto-acknowledge)

This should be set to Auto-acknowledge or Dups-ok-acknowledge. This controls the quality-of-service provided by listener threads which consume messages and call the MDB's onMessage method.

MessageSelector

(string, default = no message filtering)

This is the selector expression used to filter messages sent to the MDB's onMessage method. (i.e., this is used as the messageSelector for the JMS MessageConsumers created for the listener threads.)

SubscriptionDurability

(string, default = NonDurable)

For topics this should be set to Durable or NonDurable. (This should not be set for queues.) This controls the durability of the topic consumer used by the listener thread. When SubscriptionDurability is set to Durable (and DestinationType is javax.jms.Topic or javax.jms.Destination), the SubscriptionName property is required.

SubscriptionName

(string, no default)

This property is required when SubscriptionDurability is Durable (andDestinationType is javax.jms.Topic or javax.jms.Destination). (In all other cases it is ignored.) This is the name used when creating the durable subscriber used by the listener thread. For a given JMS server, a given subscription name should be assigned to at most one MDB (which must have most one listener thread).

TransactionTimeout

(milliseconds, default = 300000)

This limits the amount of time that the JMS Connector will wait for a message to arrive before exiting the current transaction. The transaction manager limits the amount of time a transaction can last (see transaction-timeout in transaction-manager.xml). TransactionTimeout should be set such that the transaction manager will not timeout the transaction during the onMessage routine unless something is wrong. For example, If the transaction mananager timeout is set to 30 seconds, and the onMessage routine will never take more than 10 seconds unless something is wrong, then this property could be set to 20 seconds (20000 milliseconds).

UseExceptionQueue

(boolean, default = false)

When UseExceptionQueue is true, messages that would otherwise be discarded are sent to the exception queue. (Currently the only case where this happens is when the max delivery count is exceeded. See MaxDeliveryCnt property.) Rather than sending the original message directly to the exception queue, the following procedure is used:

  • Create a new message of the same type.

  • Copy the properties and body from the original message to the new message.

  • If the headers were copied, sending the message to the exception queue would cause most of them to be lost (over-written by the resource-provider). So instead, translate headers in the original to properties in the copy, assigning each header obtained using "getJMS{Header}" to property "GJRA_CopyOfJMS{Header}". Since javax.jms.Destination is not a valid property type, translate destination headers into descriptive messages. (Currently this same service is not provided for JMSX* properties, most notably the JMSXDeliveryCount property.)

  • If some part of the copy process or augmentation process (preceding) fails, do not quit. Attempt to complete the rest of the procedure. (For Bytes/Map/Stream message types, this can mean that part of the body is copied and the rest is not.)

  • If the copy process is 100% successful, add a boolean property called GJRA_CopySuccessful with the value true.

  • Add a string property called GJRA_DeliveryFailureReason which indicates why the message was not delivered.If the MDB onMessage method generated an exception immediately prior to the delivery failure, add a string property called GJRA_onMessageExceptions which contains exception information.Send the resulting message to the exception queue. Send the resulting message to the exception queue. Note that only one attempt is made to send the message to the exception queue. Should this attempt fail, the message will be discarded without being placed in the exception queue.

See IncludeBodiesInExceptionQueue property for potential variations of the preceding procedure.

The ExceptionQueueName property is required.

In addition to being used for the primary destination, the connection factory specified by the ConnectionFactoryJndiName property will also be used for the exception queue. If the primary destination (specified by the DestinationName property) is a topic, then the connection factory must support both queues and topics. (i.e., the <connectionfactory-interface> [see oc4j-ra.xml] for the given connection factory must be either javax.jms.ConnectionFactory or javax.jms.XAConnectionFactory.)

ExceptionQueueName

(string, no default)

This is the JNDI location of the javax.jms.Queue object to use as the exception queue. (See UseExceptionQueue property for information about the use of the exception queue.) This property is required when UseExceptionQueue is true, and ignored when UseExceptionQueue is false.

IncludeBodiesInExceptionQueue

(boolean, default = true)

This controls whether or not messages sent to the exception queue will include a message body. (See UseExceptionQueue property for information about the use of the exception queue.) If many messages are sent to the exception queue during normal operation and the message body is of no use in the exception queue, then this property may be set false to improve performance. This property is ignored when UseExceptionQueue is false. There are two cases where this property does not apply:

  • If the original message did not have a message body, then the message sent to the exception queue will not have one either.

  • If a copy of the original message cannot be created for any reason, then the original may be sent to the exception queue instead. This may result in a message body being sent to the exception queue.

LogLevel

(string, no default)

This controls the level of detail of messages logged by the JMS Connector. These messages are primarily intended for debugging the JMS Connector itself, but may also be useful when debugging issues related to the use of the JMS Connector. This property should not be set in production code. (It should only be set temporarily for debugging purposes - specific log messages and log levels may be and will be added/removed/modified in future versions of the JMS Connector.) Currently the allowed values are:

  • ConnectionPool

  • ConnectionOps

  • TransactionalOps

  • ListenerThreads

  • INFO

  • CONFIG

  • FINE

  • FINER

  • FINEST

  • SEVERE

  • WARNING

  • OFF


Dynamic Load Adjustment

Dynamic load adjustment for listener threads is based on the following <activation-config> properties That are described in Table 4-11, "MDB Configuration Properties":

  • ListenerThreadMaxIdleDuration

  • ListenerThreadMinBusyDuration

  • ReceiverThreads

For information on MDB configuration, including dynamic load adjustment for MDB instances, see the Oracle Containers for J2EE Enterprise JavaBeans Developer's Guide.

Using Logical Names to Reference Resources

This section describes how you can use logical names in your client application, thereby reducing the number of dependencies on installation-specific JMS configuration within the non-OC4J-specific deployment descriptors. With this indirection, you can make your client implementation generic for any JMS configuration (and therefore independent of any specific JMS resource provider).

Using logical names enables you to make your client application code resource provider-independent. In general, configure and use logical names as follows:

  1. In your client application code, use logical names for JMS destinations and connection factories.

  2. Declare the logical names in the J2EE application component deployment descriptors, such as application-client.xml and ejb-jar.xml.

  3. Map the logical names to explicit JNDI locations in the OC4J-specific application component deployment descriptors, such as orion-application-client.xml and orion-ejb-jar.xml.

Configuring and using logical names is discussed and demonstrated in the How-To documents and the .java and .xml files available at: http://www.oracle.com/technology/tech/java/oc4j/1013/how_to/index.html

Download and unzip one of the how-to-gjra-with-xxx.zip files, where xxx is the name of the resource provider.

This section describes the following topics:

The client uses JMS destinations and connection factories to send and receive messages. The recommended method for a client to retrieve a JMS destination object or connection factory is by using a logical name (an environment entry). Using direct JNDI locations should generally not be used unless logical names are not suitable, or some other mechanism is used to maintain the application's portability.

How to Declare Logical Names

To use a logical name in your application code, you must declare the logical name in one of the following XML deployment files before the application is deployed:

  • A standalone Java client—in the application-client.xml file

  • An EJB —the ejb-jar.xml file

  • For a JSP or servlet —the web.xml file

This is covered in the How-To documents available at: http://www.oracle.com/technology/tech/java/oc4j/1013/how_to/index.html. Under "Developing the Application Components" look at task #2 "Declare Logical Names for JMS Resources".

Declare logical names for connection factories and destinations as follows:

  • Declare a logical name for a connection factory using a <resource-ref> element.

    • Specify the logical name for the connection factory in the <res-ref-name> element. This is the link-key for arrows #1 and #6 in Figure 4-1.

    • Specify the connection factory class type in the <res-type> element as one of the following:

      • javax.jms.ConnectionFactory

      • javax.jms.QueueConnectionFactory

      • javax.jms.TopicConnectionFactory

    • Specify the authentication responsibility (Container or Application) in the <res-auth> element.

    • Specify the sharing scope (Shareable or Unshareable) in the <res-sharing-scope> element.

  • Declare a logical name for a JMS destination using a <message-destination-ref element.

    • Specify the logical name for the destination in the <message-destination-ref-name> element. This is the link-key for arrows #2 and #8 in Figure 4-1.

    • Specify the destination type in the <message-destination-ref-type> element as either javax.jms.Queue or javax.jms.Topic.

    • Specify whether the client will produce messages to this destination, consume messages from this destination, or both by setting the <message-destination-usage> element to Produces, Consumes, or ConsumesProduces.

Example

The following example illustrates how to specify logical names for a queue. In the example, jms/PlayerConnectionFactory is the logical name for the connection factory and jms/PlayerCommandDestination is the logical name for the destination queue. This example is from the application-client.xml file in the demo set.

<resource-ref>
  <res-ref-name>jms/PlayerConnectionFactory</res-ref-name>
  <res-type>javax.jms.ConnectionFactory</res-type>
  <res-auth>Application</res-auth>
</resource-ref>
<message-destination-ref>
  <message-destination-ref-name>jms/PlayerCommandDest</message-destination-ref-name>  
  <message-destination-type>javax.jms.Queue</message-destination-type>
  <message-destination-usage>Produces</message-destination-usage>
</message-destination-ref>

A full example of specifying logical names, with descriptive comments, is included in the demo at: http://www.oracle.com/technology/tech/java/oc4j/1013/how_to/index.html

Drill down to the following files: /src/client/META-INF/application-client.xml

and

/src/ejb/META-INF/ejb-jar.xml

For a list of the How-To documents and demo sets and their URLs, see "JMS How-To Documents and Demo Sets".

Mapping Logical Names to Explicit JNDI Locations

After the logical names are created, the logical names must be mapped to the JNDI locations of resources. Normally, the deployer sets these up. This mapping is defined in one of the following OC4J deployment descriptor files:

  • For a standalone Java client, the mapping is defined in the client's orion-application-client.xml file.

  • For an EJB, the mapping is defined in the EJB's orion-ejb-jar.xml file.

  • For a JSP or a servlet, the mapping is defined in the orion-web.xml file of the JSP or the servlet.

The logical names in the application component's deployment descriptor are mapped as follows:

  • For connection factories, the logical name (declared in a <resource-ref> element) is mapped to a JNDI location using a <resource-ref-mapping> element. This is represented by arrows #6 and #5 in Figure 4-1.

  • For destinations, the logical name, declared using a <message-destination-ref> element, is mapped to a JNDI location using a <message-destination-ref-mapping> element. This is represented by arrows #8 and #7 in Figure 4-1.

See the following sections for how the mapping occurs for the three OEMS JMS quality of service options and how application components use this naming convention:

JNDI Naming Property Setup for Java Application Clients

In an OC4J standalone environment, a Java application client accesses an OEMS JMS destination object by defining the following properties in the jndi.properties file:

java.naming.factory.initial=
   com.evermind.server.ApplicationClientInitialContextFactory 
java.naming.provider.url=ormi://myhost/myApplicationDeploymentName 
java.naming.security.principal=oc4jadmin 
java.naming.security.credentials=welcome 

If you wish to specify the port, use the optional :port element as follows:

java.naming.provider.url=ormi://myhost:port/myApplicationDeploymentName

The default RMI port is 23791.

You must:

  • Use the ApplicationClientInitialContextFactory as your initial context factory object.

  • Supply the standalone OC4J host and port, and the application deployment name in the provider URL.

In the Oracle Application Server, a Java application client accesses an OEMS JMS destination object by defining the following properties in the jndi.properties file:

java.naming.factory.initial=
   com.evermind.server.ApplicationClientInitialContextFactory 
java.naming.provider.url=opmn:ormi://$HOST:$OPMN_REQUEST_PORT:$OC4J_INSTANCE/myApplicationDeploymentName 
java.naming.security.principal=oc4jadmin 
java.naming.security.credentials=welcome 
  • Use the ApplicationClientInitialContextFactory as your initial context factory object.

  • Supply the OPMN host and port, the OC4J instance, and the application deployment name in the provider URL.

You can see a full example of a jndi.properties file at: http://www.oracle.com/technology/tech/java/oc4j/1013/how_to/index.html

Drill down to the following file:

/src/client/jndi.properties

Client Sends JMS Message Using Logical Names

After the resources have been defined and the JNDI properties configured, the client must perform the following steps to send a JMS message. These steps summarize the procedure shown in "Sending and Receiving JMS Messages".

  1. Retrieve both the configured JMS destination and its connection factory using a JNDI lookup.

  2. Create a connection from the connection factory.

  3. Create a session over the connection.

  4. Providing the retrieved JMS destination, create a message producer.

  5. Create the message.

  6. Send the message using the message producer.

  7. Close the connection.

Required Class Path for Application Clients Using JMS Connector Lookup

When using the JMS Connector from an application client, the JAR files that must be included in the class path are listed inTable 4-12, "Client-side JAR Files Required for JMS Connector Lookup".

Table 4-12 Client-side JAR Files Required for JMS Connector Lookup

JAR ORACLE_HOME Path

oc4jclient.jar

/j2ee/<instance>

jta.jar

/j2ee/<instance>/lib

jms.jar

/j2ee/<instance>/lib

jndi.jar

/j2ee/<instance>/lib

javax77.jar

/j2ee/<instance>/lib

adminclient.jar

/j2ee/<instance>/lib

oc4j-internal.jar

/j2ee/<instance>/lib

connector.jar

/j2ee/<instance>/lib

jmxri.jar

/j2ee/<instance>/lib

jazncore.jar

/j2ee/<instance>

oc4j.jar

/j2ee/<instance>

dms.jar

/lib


Using High Availability and Clustering for OEMS JMS

A highly available JMS server provides a guarantee that JMS requests will be serviced with no interruptions because of software or hardware failures. One way to achieve high availability is through fail-over; if one instance of the server fails, then a combination of software, hardware, and infrastructure mechanisms causes another instance of the server to take over the servicing of requests.

For information about high availability, see the Oracle Application Server High Availability Guide

Table 4-13, "High Availability Summary" summarizes the support for high availability in OEMS JMS.

Table 4-13 High Availability Summary

Feature Database In-Memory and File-Based

High availability

RAC + OPMN

OPMN

Configuration

RAC configuration, resource provider configuration

Dedicated JMS server, jms.xml configuration, opmn.xml configuration

Message store

On RAC database

In dedicated JMS server/persistence files

Failover

Same or different machine (depending on RAC)

Same or different machine within Oracle Application Server Cold Failover Cluster (Midtier)


OEMS JMS clustering provides an environment where JMS applications deployed in this type of environment can load balance JMS requests across multiple OC4J instances or processes. Clustering of stateless applications is trivial: the application is deployed on multiple servers, and user requests are routed to one of them.

JMS is a stateful API. Both the JMS client and the JMS server contain state about each other, which includes information about connections, sessions, and durable subscriptions. Users can configure their environment and use a few simple techniques when writing their applications to make them cluster-friendly.

The following sections discuss how to achieve high availability and clustering with OEMS JMS:

Configuring OEMS JMS In-Memory and File-Based High Availability

OEMS JMS clustering normally implies that an application deployed in this type of environment is able to load balance messages across multiple instances of OC4J. There is also a degree of high availability in this environment because the container processes can be distributed across multiple nodes. If any of the processes or nodes goes down, then the processes on an alternate node continue to service messages.

This section describes the following OEMS JMS clustering topics:

  • Terminology

  • Distributed Destinations

    In this configuration, all factories and destinations are defined on all OC4J instances. Each OC4J instance has a separate copy of each destination.

    This configuration is good for high-throughput applications where requests must be load balanced across OC4J instances. No configuration changes are required for this scenario.

  • Cold Failover Cluster

    This configuration is a two-node cluster. Only one node is active at any time. The second node is made active if the first node fails.

  • Dedicated JMS Server

    In this configuration, a single JVM within a single OC4J instance is dedicated as the JMS server. All other OC4J instances that are hosting JMS clients forward their JMS requests to the dedicated JMS server.

    This configuration is the easiest to maintain and troubleshoot and should be suitable for the majority of JMS applications, especially those where message ordering is a requirement.

  • Custom Topologies

    This section discusses reasons for using custom topologies, lists requirements and impacts of various topology choices, and explains how custom topologies can be created.

    Custom topologies by their very nature are more complex to understand and use correctly, and involve more configuration effort. They should only be used when none of the standard configurations is adequate.

Terminology

The terms introduced here are explained in the Oracle Application Server High Availability Guide and the Oracle Process Manager and Notification Server Administrator's Guide.

  • OHS—Oracle HTTP Server

  • OracleAS Cluster—A grouping of similarly configured Oracle Application Server instances

  • Oracle Application Server Instance—Represents an installation of Oracle Application Server (that is, an ORACLE_HOME)

  • OC4J Instance—Within an Oracle Application Server instance there can be multiple OC4J instances.

  • Factory—Denotes a JMS connection factory

  • Destination —Denotes a JMS destination

Distributed Destinations

In this configuration, OHS services HTTP requests and load balances them across two or more Oracle Application Server instances in an Oracle Application Server cluster.

Each copy of the destinations is unique and is not replicated or synchronized across OC4J instances. Destinations can be persistent or in-memory. A message enqueued to one OC4J instance can be dequeued only from that OC4J instance.

This type of deployment has several advantages:

  • High throughput is achieved because applications and the JMS server are both running inside the same JVM and no interprocess communication is necessary.

  • Load balancing promotes high throughput as well as high availability.

  • There is no single point of failure. As long as one OC4J process is available, then requests can be processed.

  • Oracle Application Server instances can be clustered without impacting JMS operations.

  • Destination objects can be in-memory or file-based.

Figure 4-2 Distributed Destinations

Shows multiple destinations in a server cluster

Configuring a Distributed Destinations Cluster

Within each Oracle Application Server instance, two OC4J instances have been defined. Each of these OC4J instances is running a separate application. In other words, OC4J instance #1 (Home1) is running Application #1 while OC4J instance #2 (Home2) is running Application #2. Remember, each OC4J instance can be configured to run multiple JVMs, allowing the application to scale across these multiple JVMs.

Within an Oracle Application Server cluster, the configuration information for each Oracle Application Server instance is identical (except for the instance-specific information such as host name, port numbers, and so on). This means that Application #1 deployed to OC4J instance #1 in Oracle Application Server instance #1 is also deployed on OC4J instance #1 in Oracle Application Server instance #2. This type of architecture allows for load balancing of messages across multiple Oracle Application Server instances—as well as high availability of the JMS application, especially if Oracle Application Server instance #2 is deployed to another node to ensure against hardware failure.

The sender and receiver of each application must be deployed together on an OC4J instance. In other words, a message enqueued to the JMS Server in one OC4J process can be dequeued only from that OC4J process.

All factories and destinations are defined on all OC4J processes. Each OC4J process has a separate copy of each destination. The copies of destinations are not replicated or synchronized. So, in the diagram, Application #1 is writing to a destination called myQueue1. This destination physically exists in two locations (Oracle Application Server instance #1 and #2) and is managed by the respective JMS servers in each OC4J instance.

Note that this type of JMS deployment is suited only for specific types of JMS applications. Assuming that message order is not a concern, messages are enqueued onto distributed queues of the same name. Given the semantics of JMS point-to-point messaging, messages must not be duplicated across multiple queues. In the preceding case, messages are sent to whatever queue the load balancing algorithm determines, and the MDBs dequeue them as they arrive.

Cold Failover Cluster

This configuration is a two-node cluster. Only one node is active at any time. The second node is made active if the first node fails. For larger clusters, Cold Failover Clustering can be used in combination with the dedicated JMS server configuration described in the next section by having two nodes configured to be the dedicated JMS server, but having only one of them active at any given time. For Cold Failover documentation, see the Oracle Application Server High Availability Guide.

Configuring a Cold Failover Cluster

Configure both nodes identically as described in the following example. Modify the jms.xml file for both OC4J instances. Set the host parameter in the jms-server to be:

<jms-server host=vmt.my.company.com port="9127">
….
….
</jms-server>
 

When using file-based message persistence for a queue, the file must be located on a shared disk that is accessible by both nodes. The shared disk must fail over with the virtual IP when failing over from one node to the other. Configure the persistence-file as follows:

<queue name="Demo Queue" location="jms/demoQueue" persistence-file="/path/to/shared_file_system/demoQueueFile">
        <description>A dummy queue</description>
</queue> 
 

Stop and Start

On each node, use the following commands to stop and start:

$ORACLE_HOME/opmn/bin/opmnctl stopall
$ORACLE_HOME/opmn/bin/opmnctl startall
 

Dedicated JMS Server

In this configuration, a single OC4J instance is configured as the dedicated JMS server within an Oracle Application Server clustered environment. This OC4J instance handles all messages, thus message ordering is always maintained. All JMS applications use this dedicated server to host their connection factories and destinations, and to service their enqueue and dequeue requests.

Only one OC4J JVM is acting as the dedicated JMS provider for all JMS applications within the cluster. This is achieved by limiting the JMS port range in the opmn.xml file to only one port for the dedicated OC4J instance.

Although this diagram shows the active JMS server in the OC4J Home instance, Oracle recommends that the JMS provider be hosted in its own OC4J instance. For example, although Home is the default OC4J instance running after an Oracle Application Server installation, you should create a second OC4J instance with the Oracle Enterprise Manager 10g Application Server Control Console. In the opmn.xml file example following, we have created an OC4J instance called JMSserver.

Figure 4-3 Dedicated JMS Server

shows a single JMS server in an application server cluster

After creating an OC4J instance called JMSserver, we must make the following two changes to the opmn.xml file for this Oracle Application Server instance:

  1. Make sure that only one JVM is started for this OC4J instance (JMSserver).

    The single JVM in the OC4J instance ensures that other JVMs will not attempt to use the same set of persistent files.

  2. Specify only one value for the JMS port range for this instance.

    The single port value ensures that OPMN always assigns this value to the dedicated JMS server. This port value is used to define the connection factory in the jms.xml file that other OC4J instances will use to connect to the dedicated JMS server.

For more information on OPMN and dynamic port assignments, see the Oracle Process Manager and Notification Server Administrator's Guide.

Modifying the OPMN Configuration

The following XML from the opmn.xml file shows what changes must be made and how to find where to make these changes.

  • Assuming an OC4J instance has been created through Application Server Control Console called JMSserver, then the line denoted by (1) demonstrates where to locate the start of the JMSserver definition.

  • The line denoted by (2) is the JMS port range that OPMN uses when assigning JMS ports to OC4J JVMs. For the desired dedicated OC4J instance that acts as your JMS provider, narrow this range down to one value. In this example, the original range was from 3701-3800. In our connection factory definitions, we know the port to use by configuring this value as 3701-3701.

    Note:

    The port assigned to the dedicated JMS Server must not be available for any other application on this host. In addition, the port must be excluded from all OC4J components' port ranges for all OC4J instances which share this host.
  • The line denoted by (3) defines the number of JVMs that will be in the JMSserver default group. By default, this value is set to 1. This value must always be 1.

<ias-component id="OC4J">
  (1) <process-type id="JMSserver" module-id="OC4J" status="enabled"> 
     <module-data>
       <category id="start-parameters">
         <data id="java-options" value="-server 
           -Djava.security.policy=$ORACLE_HOME/j2ee/home/config/java2.policy 
           -Djava.awt.headless=true
         "/>
       </category>
       <category id="stop-parameters">
         <data id="java-options" 
           value="-Djava.security.policy=
             $ORACLE_HOME/j2ee/home/config/java2.policy 
           -Djava.awt.headless=true"/>
       </category>
    </module-data>
    <start timeout="600" retry="2"/>
    <stop timeout="120"/>
    <restart timeout="720" retry="2"/>
    <port id="ajp" range="3000-3100"/>
    <port id="rmi" range="3201-3300"/>
    (2) <port id="jms" range="3701-3701"/> 
    (3) <process-set id="default_group" numprocs="1"/> 
  </process-type>
</ias-component>
Configuring OEMS JMS

As already described in this scenario, one of the OC4J instances is dedicated as the JMS server. Other OC4J instances and standalone JMS clients running outside OC4J must be set up to forward JMS requests to the dedicated JMS server. All connection factories and destinations are defined in the JMS server instance's jms.xml file. This jms.xml file should then be copied to all the other OC4J instances that will be communicating with the JMS server.

The connection factories configured in the jms.xml file on the dedicated JMS server must specify, explicitly, the host name and the port number of the server. The host name and port number in jms.xml must match the host name and single port number defined by OPMN for the dedicated server as previously discussed. The same connection factory configuration must also be used in all other OC4J instances so that they all point to the dedicated JMS server for their operations.

Thus, if the dedicated JMS server runs on host1, port 3701, then all connection factories defined within the jms.xml file for each OC4J instance in the cluster must point to host1, port 3701—where this port is the single port available in the opmn.xml file used in the dedicated OC4J instance (in our example, JMSserver) used for the dedicated JMS server.

The destinations configured in the jms.xml file on the dedicated JMS server should also be configured on all other OC4J instances; the physical store for these destinations, however, is on the dedicated JMS server.

Queue Connection Factory Definition Example

Here is an example for defining a queue connection factory in the jms.xml file of the dedicated server:

<!-- Queue connection factory -->
<queue-connection-factory name="jms/MyQueueConnectionFactory"
          host="host1" port="3701"
          location="jms/MyQueueConnectionFactory"/>

Administrative changes (that is, adding a new destination object) should be made to the dedicated JMS server's jms.xml file. These changes should then be made in the jms.xml files of all other OC4J instances running JMS applications. Changes can be made either by hand or by copying the dedicated JMS server's jms.xml file to the other OC4J instances.

Deploying JMS Connector

A JMS connector may be deployed at each OC4J instance that hosts applications that send and receive messages with the dedicated JMS Server. This JMS connector provides the JNDI mapping for the JMS connection factories configured locally that reference the dedicated JMS server. Applications deployed at the OC4J instance can then access the underlying JMS administration objects through the JMS connector implementation. For detailed information on using the JMS connector, refer to "JMS Connector".

Defining the Queue Connection Factory for the JMS Connector

The following example defines a queue connection factory in the oc4j-ra.xml file that maps to the queue connection factory (jms/MyQueueConnectionFactory) that was previously (see the example above) defined in the jms.xml file:

<connector-factory location="MyJMSConnector/QCF"
   connector-name="MyJMSConnector">
   <config-property name="jndiLocation" value="jms/MyQueueConnectionFactory"/>
   <connection-pooling use="private">
      <property name="waitTimeout" value="300" />
      <property name="scheme" value="fixed_wait" />
      <property name="maxConnections" value="50" />
      <property name="minConnections" value="0" />
   </connection-pooling>
   <security-config use="principal-mapping-entries">
      <principal-mapping-entries>
         <principal-mapping-entry>
            <initiating-user>servletuser</initiating-user>
            <res-user>jmsuser</res-user>
            <res-password>->jmsuser</res-password>
         </principal-mapping-entry>
      </principal-mapping-entries>
   </security-config>
   <connectionfactory-interface>
      javax.jms.QueueConnectionFactory</connectionfactory-interface>
</connector-factory>

Using the above example, applications deployed on the OC4J instance may look up the dedicated server's connection factory using the location MyJMSConnector/QCF which maps to the actual JMS queue connection factory's JNDI location (jms/MyQueueConnectionFactory) which is defined in the jms.xml file. See "JMS Connector" for a detailed description for configuring and deploying resource adapters and configuring JMS Connectors.

Deploying Applications

The user decides where the JMS applications will actually be deployed. Although the dedicated JMS server services JMS requests, it can also execute deployed JMS applications. JMS applications can also be deployed to other OC4J instances (that is, Home).

Remember, the jms.xml file from the dedicated JMS server must be propagated to all OC4J instances where JMS applications are to be deployed. JMS applications can also be deployed to standalone JMS clients running in separate JVMs.

High Availability

OPMN provides the failover mechanism to keep the dedicated JMS server up and running. If for some reason the JMS server fails, then OPMN detects this and restarts the JVM. If a hardware failure occurs, then the only way to recover messages is to have the persisted destinations hosted on a network file system. An OC4J instance can then be brought up and configured to point to these persisted files.

See the Oracle Process Manager and Notification Server Administrator's Guide for more information on how OPMN manages Oracle Application Server processes.

Custom Topologies

In addition to the previously discussed configurations, OEMS JMS can be configured into arbitrary user-defined topologies.

Mechanisms

This section discusses the mechanisms that allow custom topologies to be created and to function. These mechanisms are already defined in other places in this document, however this section also covers some of the finer points that need to be understood when using a custom topology.

Using a JMS server other than the one in the local OC4J JVM requires a connection factory that references the desired JMS server. This is done by way of a host and port mapping.

First, the JMS server must be associated with a host and port. Usually, the host is the single host/IP address of the machine on which the JMS server is run. In the case of a machine with multiple host/IP addresses, all addresses will be associated with the JMS server unless a specific address is specified using the host attribute of the <jms-server> element in the jms.xml file. The port is 9127 unless a different value is specified using the port attribute. See the <jms-server> entry in Table 4-1, "Configuration Elements", and also see "Configuring Ports" . When OPMN is used, the "port" attribute is ignored and port assignment is handled automatically from a range of port values set in the opmn.xml file. See "Modifying the OPMN Configuration" .

Once the host and port have been designated for each JMS server, then connection factories can be made to reference specific JMS servers. The first step in making a connection factory reference a specific JMS server is to set the host attribute of the connection factory element to be the same as the host/IP address of the given JMS server. See <connection-factory>, <xa-connection-factory>, and the other connection factory elements in Table 4-1, "Configuration Elements". When making a connection factory reference a JMS server on the same machine where that machine has a single host/IP address, this step may be skipped (the "host" attribute may be left out). The next step in making a connection factory reference a specific JMS server is to set the "port" attribute of the connection factory element to be the same as the port of the given JMS server. If the port is 9127, this step may be skipped (the "port" attribute may be left out).

If connection factory CF1 has been configured (as described in the previous paragraph) to reference JMS server JMS1, then a connection created from CF1 is a connection to JMS1. All operations performed through that connection go to JMS1. It is not possible to use that connection to interact with any other JMS server. (It is not even possible to use that connection to interact with the JMS server running in the local JVM, unless it happens to be JMS1.) Likewise, if that connection is used to create a session, and that session to create a message producer, then that session and message producer are both connected to JMS1. All messages sent through that message producer will go to JMS1, will be stored (in memory or file) by JMS1, and can only be received or browsed from JMS1 (using a message consumer or queue browser that is connected to JMS1). Note that this JMS server association does not extend to javax.jms.Message objects. Message objects created or received from a session or message producer associated with one JMS server may be sent using any message producer. For example, an application could receive a message from a physical destination maintained by JMS server "JMS1" using a message consumer associated with "JMS1", and then send that message to a physical destination maintained by JMS server "JMS2" using a message producer associated with "JMS2".

When dealing with multiple JMS servers, it is necessary to draw a distinction between physical destinations (physical locations where messages are stored), destination configuration (elements/attributes in jms.xml) and destination admin objects (Java objects looked up in JNDI).

From the perspective of a JMS server:

  • A name (whether from a destination configuration or from a destination admin object) uniquely identifies a physical destination - one controlled solely by the given JMS server.

  • The persistence-file attribute (or its absence) tells the JMS server where it should persist the messages for a given physical destination.

  • The location attribute tells the JMS server where to bind a destination admin object (containing the value of the name attribute) in JNDI in the local JVM.

From the perspective of a JMS client:

  • Destination admin objects do not contain JNDI locations. Instead, they are looked-up at a JNDI location.

  • Destination admin objects do not have any persistence file settings. Instead, the persistence file (if any) used for a given physical destination is determined by the JMS server that controls that physical destination.

  • Destination admin objects contain only a name, and names do not uniquely identify a physical destination. When interacting with JMS server JMS1, a destination admin object will be considered to be a reference to a physical destination controlled by JMS1. When interacting with JMS server JMS2, that same destination admin object will be considered to be a reference to a different physical destination - one controlled by JMS2. (If, when interacting with a JMS server, a destination admin object is used whose name does not match the name of any physical destination on the given JMS server, the operation will fail.)

For example, given an excerpt from JMS server JMS1's jms.xml file:

<queue name="queue1"
          location="jms/alpha"
          persistence-file="foo">
   </queue>

And given an excerpt from JMS server JMS2's jms.xml file:

<queue name="queue1"          location="jms/omega"          persistence-file="bar">   </queue>

   <queue name="queue2"
          location="jms/alpha">
   </queue>

In Table 4-14, "Results for Various Message Scenarios", if a destination is looked-up from the server in column 1 using the JNDI location from column 2, and then a message producer connected to the server in column 3 is used to send a PERSISTENT message, the result is as described in the final column.

Table 4-14 Results for Various Message Scenarios

Destination looked-up in the same JVM as JNDI location used to look up destination Message producer connected to Result (physical destination that receives message, or error)

JMS1

jms/alpha

JMS1

JMS1's "queue1", persisted to file "foo"

JMS1

jms/alpha

JMS2

JMS2's "queue1", persisted to file "bar"

JMS2

jms/alpha

JMS2

JMS2's "queue2", stored in memory on JMS2

JMS2

jms/alpha

JMS1

Error (JMS1 does not have a "queue2")

JMS1

jms/omega

don't care

Error looking up "jms/omega" in JNDI

JMS2

jms/omega

JMS1

JMS1's "queue1", persisted to file "foo"

JMS2

jms/omega

JMS2

JMS2's "queue1", persisted to file "bar"


Note that the preceding example (and the connection factories in the "Distributed Destinations" configuration) bind/require different values for the same JNDI location in different JVMs, and therefore require that JNDI values not be automatically propagated from one JVM to another.

When using the following combination:

  • OPMN (automatic JMS port assignment)

  • One or more dedicated JMS servers

  • Multiple OC4J instances on a machine

Care should be taken to ensure that:

  • The range of available JMS ports is just enough for the number of JMS servers on the given machine. This guarantees that the dedicated JMS server port number actually gets assigned to one of the available JMS servers.

  • The persistence files (if any) for the destination(s) controlled by the dedicated JMS serve are specified in the jms.xml file(s) using absolute paths. If a path is relative to the OC4J instance, then previously persisted messages would be lost after a server restart when OPMN assigns the dedicated JMS server port number to a JMS server in a different OC4J instance than it did after the previous restart.

Considerations

The "Dedicated JMS Server" and "Distributed Destinations" configurations are the only configurations where each instance of an arbitrary JMS application is guaranteed to only ever communicate with a single JMS server. The considerations discussed in this section do not apply to those scenarios. They also do not apply to other scenarios where it can be guaranteed that a JMS application instance only ever communicates with a single JMS server.

For example, if all instances of application A use JMS server #1 and all instances of application B use JMS server #2, then the following considerations are not applicable.

In other scenarios, where a single JMS application instance interacts with two or more JMS servers, there are several consequences:

  • There is an application-complexity impact:

    Since a JMS server is selected based on the connection factory (and its derived objects), using multiple JMS servers from a single application instance requires the use of multiple connection factories (and derived objects such as sessions, consumers and producers). For example, if an application uses producer A to enqueue a message to JMS server #1, it is not possible to also use producer A to enqueue a message to JMS server #2. Instead, a different producer, derived from a different connection factory than the one from which producer A was derived, must be used. (To be specific, a producer derived from a connection factory associated with JMS server #2 must be used.) This also means that using multiple JMS servers may not be possible with a pre-existing JMS application unless the application already accommodates (or can be modified to accommodate) this prerequisite.

  • There is a performance impact:

    Since two different JMS servers represent two different resource managers, global transactions involving two JMS servers will always require two-phase commit, even if no other resource types (such as JDBC) are used during the transaction. Even if two-phase commit was already required for a given transaction, when more resource managers participate in a transaction, the cost (in performance) of the transaction goes up. However, using multiple JMS servers is still a performance win in many scenarios since it can be used to offload work from potential bottlenecks (such as a single, dedicated JMS server) and increase both parallelism and locality.

These same considerations also apply if a single JMS application instance is using two different JMS resource providers. For example, an application might use OEMS JMS In-Memory for memory-based or file-based persistence and also use OEMS JMS Database for database-backed persistence.

Cases

This section shows two example situations driven by application-specific messaging requirements, along with custom topologies that could be used to improve throughput in each case. These examples should not be considered exhaustive, either in terms of situations you may encounter or in topologies that can be created.

Case #1: Only some destinations need global consistency:

It may be that some destinations must provide global consistency, as provided by the "Dedicated JMS Server" configuration, and other destinations have no such requirement. In that case, it is not necessary to pay the expense of global consistency (routing all messages through a single JMS server) for the destinations that do not require it and could instead be locally partitioned, such as in the "Distributed Destinations" configuration.

Say that destinations A and B need global consistency, and that destinations C and D do not. In that case, all jms.xml files define all four destinations. One machine is selected to host the dedicated JMS server for destinations A and B. The dedicated JMS server must have fixed host and port values in order to allow connection factories to reference it. At least two connection factories are defined in the jms.xml files, one that references the dedicated JMS server (that is, with a fixed host and port value) and one that references the JMS server in the local JVM (that is, with the default host and port values). In order to access destinations A and B (and maintain global consistency), the Java code must use a connection factory that references the dedicated JMS server. In order to access destinations C and D, the Java code must use a connection factory that references the JMS server in the local JVM.

Case #2: Using multiple dedicated JMS servers for load-balancing:

In the previous example, two destinations (A and B) needed global consistency. This requires that destination A has a dedicated JMS server and that destination B has a dedicated JMS server, but does not require that those two JMS servers be the same. When multiple destinations requiring global consistency are heavily used, it may be worth while to divide the load of those destinations across multiple dedicated JMS servers. This is especially true for destinations that tend to not be involved in a common transaction or when a multi-destination dedicated JMS server is acting as a system bottleneck.

For this case, all jms.xml files define all four destinations. One machine is selected to host the dedicated JMS server for destination A. Another machine (or another JVM on the same machine) is selected to host the dedicated JMS server for destination B. Both dedicated JMS servers must have fixed host and port values in order to allow connection factories to reference them. At least three connection factories are defined in the jms.xml files, one that references the dedicated JMS server for destination A, one that references the dedicated JMS server for destination B, and one that references the JMS server in the local JVM. In order to access destination A, the Java code must use a connection factory that references the dedicated JMS server for destination A. In order to access destination B, the Java code must use a connection factory that references the dedicated JMS server for destination B. In order to access destinations C and D, the Java code must use a connection factory that references the JMS server in the local JVM.

Configuring OEMS JMS Database High Availability

To enable high availability the OEMS JMS Database option, run the following:

  • Run an Oracle database that contains the AQ queues and topics in RAC-mode. This ensures that the database is highly available.

  • Run Oracle Application Server in OPMN-mode. This ensures that the application servers (and applications deployed on them) are highly available.

Each application instance in an Oracle Application Server cluster uses OC4J resource providers to point to the back end Oracle database, which is operating in RAC-mode. JMS operations invoked on objects derived from these resource providers are directed to the real application clusters (RAC) database.

If a failure of the application occurs, then state information in the application is lost (that is, state of connections, sessions, and messages not yet committed). As the application server is restarted, the applications must re-create their JMS state appropriately and resume operations.

If network failover of a back-end database occurs, where the database is a non-RAC database, then state information in the server is lost (that is, state of transactions not yet committed). Additionally, the JMS objects (connection factories, destination objects, connections, sessions, and so on) inside the application may also become invalid.

After the failure of the database occurs, those JMS objects will throw exceptions whenever the application code attempts to use them. In order to recover, the application must re-create any and all JMS objects which are throwing such exceptions. This includes relooking up connection factories using JNDI.

Failover Scenarios When Using a RAC Database

An application that uses a RAC database must handle database failover scenarios. There are two types of failover scenarios, that are described in this section:

RAC Network Failover

A standalone client running against an RAC database must write code to obtain the connection again, by invoking the API oracle.oc4j.sql.DataSourceUtils.isOracleFatalError(), to determine if the connection object is invalid. It must then reestablish the database connection if necessary. The isOracleFatalError() method detects if the SQL error thrown by the database during network failover is a fatal error. This method takes in the SQL error and the database connection, and returns true if the error is a fatal error. If true, you may wish to aggressively roll back transactions and re-create the JMS state (such as connections, session, and messages that were lost).

The following example outlines the logic:

Message getMessage(QueueSession session, Queue rcvrQueue) {
   try {          Message msgRec = null;      QueueReceiver rcvr = session.createReceiver(rcvrQueue);      msgRec = rcvr.receive();      rcvr.close();      return msgRec;   }
   catch (Exception ex) {    
      if (ex instanceof JMSException) {
         Exception exLinked = ((JMSException) ex).getLinkedException();         if (exLinked instanceof SQLException) {            if (DataSourceUtils.isOracleFatalError((SQLException) exLinked) {               // failover logic
            }
         }      }   }
}
Transparent Application Failover (TAF)

In most cases where TAF is configured, the application does not notice that failover to another database instance has occurred. So, you need not do anything to recover from failure.

However, in some cases, OC4J throws an ORA error when a failure occurs. The JMS client passes these errors to the user as a JMSException with a linked SQL exception. In this case, do one or more of the following:

  • As described in "RAC Network Failover", you can use the isOracleFatalError() method to determine if the error is a fatal error. If it is not a fatal error, then the client recovers by sleeping for a short time and then retrying the current operation.

  • You can recover from failback and transient errors caused by incomplete failover by trying to use the JMS connection after a short time. Waiting allows the database failover to recover from the failure and reinstate itself.

  • In the case of transaction exceptions (such as "Transaction must roll back" (ORA-25402) or "Transaction status unknown" (ORA-25405)) you must roll back the current operation and retry all operations past the last commit. The connection is not usable until the cause of the exception is dealt with. If this retry fails, then close and re-create all connections and retry all non committed operations.

Sample Code for Connection Recovery

The following example shows OEMS JMS application code that is can be used with any of the persistence options, for a queue that is tolerant to intermittent connection failures, such as may happen during network outages, server reboots, JMS server failover, and other situations.

while (!shutdown) {
        Context ctx = new InitialContext();

        // get the queue connection factory
        QueueConnectionFactory qcf =
                        (QueueConnectionFactory) ctx.lookup(QCF_NAME);

        // get the queue
        Queue q = (Queue) ctx.lookup(Q_NAME);

        ctx.close();

        QueueConnection qc = null;
        try {
            // create a queue connection, session, sender and receiver
            qc = qcf.createQueueConnection();
            QueueSession qs = qc.createQueueSession(true, 0);
            QueueSender snd = qs.createSender(q);
            QueueReceiver rcv = qs.createReceiver(q);

            // start the queue connection
            qc.start();

            // receive requests using the queue receiver and send
            // replies using the queue sender
            while (!done) {
                Message request = rcv.receive();
                Message reply = qs.createMessage();

                // put code here to process request and construct reply

                snd.send(reply);
                qs.commit();
            }
        } catch (JMSException ex) {
            if (transientServerFailure) {
                // retry
            } else {
                shutdown = true;
            }
        } finally {
           // close the queue connection
           if (qc != null) qc.close();
        }
    }

J2CA Configuration for Connection Recovery

Note that connection pooling means that when a connection is closed by the application, the physical connection is not actually closed by the connector but is instead returned to the connection pool. If a connection fails, this can result in an invalid connection being returned to the pool. Subsequent attempts to create a new connection may then obtain an invalid connection, negating the value of the preceding code. In order to make failover reliable, connection pooling should be disabled for the connection factory used to create the connection. This is done by modifying the the connection factory's <connector-factory> element in the oc4j-ra.xml file to include the following:

<connection-pooling use="none">
    </connection-pooling>

Clustering Best Practices

  • Minimize JMS client-side state.

    • Perform work in transacted sessions.

    • Save/checkpoint intermediate program state in JMS queues/topics for full recoverability.

    • Do not depend on J2EE application state to be serializable or recoverable across JVM boundaries. Always use transient member variables for JMS objects, and write passivate/activate and serialize/deserialize functions that save and recover JMS state appropriately.

  • Do not use nondurable subscriptions on topics.

    • Nondurable topic subscriptions duplicate messages for each active subscriber. Clustering and load-balancing creates multiple application instances. If the application creates a nondurable subscriber, it causes the duplication of each message published to the topic. This is either inefficient or semantically invalid.

    • Use only durable subscriptions for topics. Use queues whenever possible.

  • Do not keep durable subscriptions active for extended periods of time.

    • Only one instance of a durable subscription can be active at any given time. Clustering and load-balancing creates multiple application instances. If the application creates a durable subscription, only one instance of the application in the cluster succeeds. All other instances fail with a JMSException.

    • Create, use, and close a durable subscription in small time/code windows, minimizing the duration when the subscription is active.

    • Write application code that accommodates failure to create durable subscription due to clustering (when some other instance of the application running in a cluster is currently in the same block of code) and program appropriate back-off strategies. Do not always treat the failure to create a durable subscription as a fatal error.

JMS Router

Complex and disparate enterprise-computing environments require a messaging infrastructure that integrates and interoperates with various messaging systems. The JMS Router provides a reliable asynchronous JMS message routing service that can bridge:

The JMS Router guarantees the following behavior:

Users can specify a message selector to selectively route messages when creating a router job. Only the messages that satisfy the selector are routed from the source destination to the target destination by the JMS Router. The message selectors must be valid JMS message selectors. See the JMS 1.1 specification for the message selector syntax and semantics for JMS queues and topics.

The JMS Router requires that the participating JMS provider support JMS 1.1 if either the source or target of a JMS Router job is a JMS topic.

You can access the JMS 1.1 specification at: http://java.sun.com/products/jms/docs.html.

By bridging JMS destinations, the JMS Router provides users the following benefits:

JMS Providers

The JMS Router uses the JMS Connector to access the following JMS providers:

  • OEMS JMS In-Memory, File-Based, and Database persistence options

  • IBM WebSphere MQ V6.0 JMS, MQ V5.3 JMS with Fix Pack 8 (CSD08)

  • TIBCO Enterprise Message Server version 4.3.0

  • SonicMQ 6.0 JMS

The JMS Router relies on the OC4J pre-packaged standalone JMS Connector instance OracleASjms to access the OEMS JMS In-Memory and File-Based options that run in the same container as the JMS Router. Therefore, there is no need to deploy any additional adapters for routing messages to and from OEMS JMS In-Memory or File-Based Destinations.

For routing messages to and from any JMS provider other than OracleAS JMS, there must be a standalone JMS Connector deployed for the JMS provider.

The JMS Router uses the J2CA adapter's declarative container-managed sign-on mechanism for JMS provider authentication and authorization. The JMS Router runs on behalf of the role jmsRouter. Therefore, all the resource adapters used by the JMS Router must have a valid principal mapping with either the <default-mapping> element or a <principal-mapping-entry> element that has jmsRouter as <initiating-user> in the oc4j-ra.xml.

Additional information on how to use the JMS Router for OEMS JMS is available at http://www.oracle.com/technology/tech/java/oc4j/1013/how_to/index.html.

Configuration

This section discusses configuration with respect to the following JMS Router objects:

The primary administration interface of the JMS Router is the JMS Router MBean. The MBean enables you to manage configuration, to start and stop individual JMS Router jobs, and to monitor the status of the jobs.

The JMS Router may also be configured statically through the jms.xml file.

Router Jobs

The JMS Router job is defined as a message routing task to move messages from the source destination to a target destination. When processing a router job, the JMS Router dequeues messages from the source destination and enqueues the messages to the target destination.

The source and the target destinations can be either JMS queues or topics. If the source is a JMS queue, then the JMS Router moves all messages from the queue. If the source is a topic, then the JMS Router moves all messages that are published to the topic since the JMS durable subscriber was created.

Note:

JMS Router jobs must not share a source, whether it is a queue or a durable subscriber.

A JMS Router job uses the objects described in Table 4-16, "JMS Router Settings".

The JMS Router uses the JMS Connector to access JMS destinations and connection factories. The JMS Router requires that source and target destinations for all JMS Router jobs exist in the accessed JMS provider, and are configured in the appropriately configured JMS Connector. For information on configuring Queues, Topics, and ConnectionFactories, see "Configuring Destination Objects and Connection Factories". For additional resource adapter configuration information, see "JMS Connector" and the Oracle Containers for J2EE Resource Adapter Administrator's Guide.

Global Router Parameter(s)

The number of concurrent jobs is configurable as a JMS Router attribute maxLocalConcurrency. This attribute prevents a JMS Router with many active jobs from dominating the OC4J J2EE container. This also sets the upper limit on the number of JMS sessions created by JMS Connectors that are used by the JMS Router.

Subscription

If the source is a JMS topic, the user may provide a durable subscriber name on the topic. The actual durable subscriber can be created before the associated router job is created. If the name of the durable subscriber is not specified, then the JMS Router creates a subscriber name based on the name of the job. If the durable subscriber associated with the subscriber name does not exist when the JMS Router starts to process the job, then the router creates the durable subscriber. The JMS Router moves all messages that are published to the topic since the durable subscriber was created.

By default, when a JMS Router job is deleted, the JMS Router attempts to remove the durable subscriber. If the JMS Router fails to remove the durable subscriber, then the user must remove it through the administration interface of the messaging system to avoid unnecessary message accumulation. Users can also optionally ask the JMS Router not to remove the durable subscriber when deleting a JMS Router job.

Log Queues and Exception Queues

This section discusses log queues and exception queues.

Log Queues

The JMS Router uses queues for internal logging. Each router job must have a source log queue and a target log queue. These queues are used to ensure quality of service when processing router jobs. For the OEMS JMS In-Memory and File-Based options, the JMS Router creates log queues. For the OEMS JMS Database option and other supported non-Oracle JMS providers, a JMS queue must be created on that system, and the name of the queue must be specified when creating the router job. Log queues may be shared by multiple jobs.

Log queues for the JMS Router must exist in the accessed messaging system and must be configured in the appropriate resource adapter.

Exception Queues

When the JMS Router fails to send a message to the target destination, it blocks processing of the associated router job in order to maintain message order.

In order for the JMS Router to keep processing a job with problematic messages, users can configure the job with an exception queue into which the JMS Router can move the problematic messages in order to process the remaining messages in the source destination.

Each JMS Router job can have one exception queue, which must be a JMS queue in the same messaging system as the source destination and accessible through the same connection factory as that of the source destination. The physical JMS destination for the exception queue must exist before it is used for any JMS Router jobs. In the OEMS JMS In-Memory and File-Based options, an exception queue is already defined by default -- Oc4jJmsExceptionQueue.

In order for the JMS Router to move problematic messages into the exception queue, the useExceptionQueue flag must be set to true for the associated router job.

Optionally, exception queues, if configured, for the JMS Router must exist in the accessed messaging system and must be configured in the appropriate resource adapter.

Configuring the JMS Router and Its Objects

The primary administration interface of the JMS Router is the JMS Router MBean. Use the MBean to manage configuration, to start and stop individual JMS Router jobs, and to monitor the status of the jobs.

This section describes the operations and settings available in JMS Router MBean.

Path to the JMS Router MBean:

OC4J:Home > Administration tab > Services > JMS Providers > Click the icon. > Select the appropriate tab. > Related Links: OracleASJMSRouter

Note:

The JMS Router exports a single JMS Router MBean for each OC4J instance: "jmsrouter:j2eeType=OracleASJMSRouter".

The following table lists and describes the operations available on the JMS Router MBean. All operations update the JMS Router dynamically and persist the changes to jms.xml.

Table 4-15 JMS Router MBean Operations

Operation Description

addRouterJob

Configures a JMS Router job.

alterRouterJob

Alters the attributes of a JMS Router job. The default value for all parameters to alterRouterJob is to leave them unchanged.

configureRouter

Configures certain global parameters of the JMS Router, such as maxLocalConcurrency.

pauseRouterJob

Suspend the execution of a JMS Router job.

removeRouterJob

Removes a JMS Router job.

resetRouterJob

Resets the number of failures in the JMS Router job to zero.

resumeRouterJob

Resume the execution of a JMS Router job.


Table 4-16, "JMS Router Settings" lists and describes the router and router job settings in the JMS Router MBean. The first column of the table lists the name of the setting in the JMS Router MBean. The settings that you make in the JMS Router MBean are persisted to the jms.xml file. The second column of the table lists the name of the corresponding elements in the jms.xml file.

Table 4-16 JMS Router Settings

MBean Setting XML Entity Description

jobName

Editable through the addRouterJob operation.

<job-name>

Router job element

The name given to this router job. It must be unique for the OC4J instance for which it is configured.

messageSource

Editable through the addRouterJob operation.

<message-source>

Router job element

The JNDI location of the destination (topic or queue) to be used as the source of messages.

If automatic destination wrapping is used, then the name may be of the form:

<JNDIsubcontext>/providerName

where <JNDIsubcontext> is the automatic destination wrapping JNDI subcontext as specified in oc4j-connectors.xml.

For example, if automatic destination wrapping is used with the JMS Connector, a name would be of the form:

OracleASjms/Queues/jms/queue_name

or

OracleASjms/Topics/jms/topic_name

sourceConnectionFactory

Editable through the addRouterJob operation.

<source-connection-factory>

Router job element

The JNDI location of the connection factory used to access the message source.

For example, using the JMS Connector, a name might be

OracleASjms/MyCF

If the message source is a JMS Topic, this name must refer to a connection factory that supports both JMS Queues and Topics.

messageTarget

Editable through the addRouterJob operation.

<message-target>

Router job element

The JNDI location of the destination (topic or queue) to be used as the target for message propagation.

If automatic destination wrapping is used, then the name may be of the form:

<JNDIsubcontext>/providerName

where <JNDIsubcontext> is the automatic destination wrapping JNDI subcontext as specified in oc4j-connectors.xml.

For example, if automatic destination wrapping is used with the JMS Connector, a name would be of the form:

OracleASjms/Queues/jms/queue_name

or

OracleASjms/Topics/jms/topic_name

targetConnectionFactory

Editable through the addRouterJob operation.

<target-connection-factory>

Router job element

The JNDI location of the connection factory used to access messageTarget.

For example, using the JMS Connector, a name might be

OracleASjms/MyCF

If the message source is a JMS Topic, this name must refer to a connection factory that supports both JMS Queues and Topics.

sourceLogQueue

Editable through the addRouterJob operation.

<source-log-queue>

Router job element

The JNDI location of the queue to be used for JMS Router internal logging for the source messaging system. The log queue must be accessible through the connection factory indicated by

sourceConnectionFactory.

This parameter is optional when using OEMS JMS In-Memory or File-Based Destinations. In this case, if not specified, then the JMS Router uses the queue

OracleASRouter_LOGQ

If this queue does not exist, then the JMS Router will create it.

targetLogQueue

Editable through the addRouterJob operation.

<target-log-queue>

Router job element

The JNDI location of the queue to be used for JMS Router internal logging for the target messaging system. The log queue must be accessible through the connection factory indicated by

targetConnectionFactory.

This parameter is optional when using OEMS JMS In-Memory or File-Based Destinations. In this case, if not specified, then the JMS Router uses the queue

OracleASRouter_LOGQ

If this queue does not exist, then the JMS Router will create it.

messageSelector

Editable through the addRouterJob operation.

<message-selector>

Router job element

Optional. A message selector for selectively receiving messages from the messageSource. The default is none.

subscriberName

Editable through the addRouterJob operation.

<subscriber-name>

Router job element

Optional. The name for a durable subscriber to use if the messageSource is a topic. If the specified durable subscriber does not exist and the messageSource is a topic, then the JMS Router attempts to create it

The default value is

OracleASRouter_jobName 

where jobName is the name of the Router job.

exceptionQueue

Editable through the addRouterJob and alterRouterJob operations.

<exception-queue>

Router job element

The JNDI location of a queue into which undeliverable messages are placed. The exception queue must be accessible from sourceConnectionFactory.

This parameter need only be specified if useExceptionQueue is true. When useExceptionQueue is true, this parameter is optional when the message provider is OEMS JMS In-Memory or File-Based option. If not specified, then the JMS Router will use the OEMS JMS exception queue, Oc4jJmsExceptionQueue. This queue already exists, so does not need to be created separately.

The default is null when using alterRouterJob.

maxRetries

Editable through the addRouterJob and alterRouterJob operations.

max-retries

Router job attribute

Optional. The number of times the JMS Router will attempt to deliver a message for this job before suspending execution of the job.

The value must be an integer-valued string. If the string does not represent an integer, then it is ignored and the default is used.

The default is 16 when using addRouterJob. The default is null when using alterRouterJob.

pollingInterval

Editable through the addRouterJob and alterRouterJob operations.

polling-interval

Router job attribute

Optional. If no message is present in the message source, then this parameter represents the minimum time in seconds to wait before checking the message source again.

The value must be a string representing an integer. If the string does not represent an integer, then it is ignored and the default is used.

The default is 5 when using addRouterJob. The default is null when using alterRouterJob.

useExceptionQueue

Editable through the addRouterJob and alterRouterJob operations.

use-exception-queue

Router job attribute

Optional. If the value is set to true and an exception queue is available, then undeliverable messages will be placed in it. Otherwise, no exception queue will be used.

The default is false when using addRouterJob. The default is null when using alterRouterJob.

pauseJob

Editable through the addRouterJob operation.

pause-job

Router job attribute

Optional. If true, then the job is added in deactivated mode.

To start the job, invoke resumeJob.

If not true, then the job is created in activated mode.

The default is false.

batchSize

Editable through the addRouterJob and alterRouterJob operations.

batch-size

Router job attribute

Optional. The number of messages to dequeue and enqueue in a single transaction.

The default is 30 when using addRouterJob. The default is null when using alterRouterJob.

removeSubscriber

Editable through the removeRouterJob operation.

remove-subscriber

Router job attribute

If true and the router job used a durable subscriber, then the JMS Router attempts to remove that durable subscriber.

If false, then no attempt is made to remove the durable subscriber. If the durable subscriber is not removed successfully by the JMS Router, then the user is responsible for its removal.

The default is true.

maxLocalConcurrency

Editable through the configureRouter operation.

maxlocalconcurrency

Global JMS Router attribute

Optional. The maximum concurrency of dequeue operations possible. This argument places a limit on the number of threads that the JMS Router can use to dequeue messages at one time. The parameter can help limit the amount of container resources that are used by the JMS Router.

The default value is -1 which means there is no limit on how many router jobs can be processed concurrently.


JMS Router Configuration in jms.xml

The file J2EE_HOME/config/jms.xml is used to persist JMS Router jobs and global configuration.

In the jms.xml file, the JMS Router is configured in the <jms-router> element. A <jms-router> element consists of zero or more <router-job> elements. A JMS Router job is defined in the element <router-job>.

Table 4-16, "JMS Router Settings" lists and describes the JMS Router elements of the jms.xml file.

Minimal Example: JMS Router in jms.xml

This example illustrates a minimal configuration for a single JMS Router job that uses an OEMS JMS In-Memory queue as a source and an OEMS JMS In-Memory queue as target, utilizing the globally deployed JMS Connector instance OracleASjms for JMS objects.

<?xml version="1.0"?>
<jms xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchema Location="http://www.oracle.com/technology/oracleas/schema/jms-server-10_1.xsd" schema-major-version="10" schema-minor-version="1">
  <!-- OracleAS JMS server configuration -- omitted for brevity  -->
  <jms-server>
     ...
  </jms-server>

  <!-- JMS Router configuration -->
  <jms-router max-local-concurrency="-1" >

     <!-- Minimal configuration for a JMS Router job.-->
     <router-job job-name="routerjob1">

        <!-- The name of a JMS Router destination -->
        <message-source>OracleASjms/Topics/jms/mySource</message-source>

        <!-- Connection factory for the message source. -->
        <source-connection-factory>OracleASjms/MyCF</source-connection-factory>

        <!-- The name of a JMS Router destination -->
        <message-target>OracleASjms/Queues/jms/myTarget</message-target>

        <!--Connection factory for the message target. -->
        <target-connection-factory>OracleASjms/MyCF</target-connection-factory>

     </router-job>
  </jms-router>

</jms>

Syntax Example: JMS Router in jms.xml

This example illustrates the syntax of the JMS Router portion of jms.xml by defining a router job that provides values for all available attributes. It defines a configuration for a single JMS Router job that uses OEMS JMS In-Memory queue as source and OEMS JMS Database queue as target, utilizing the JMS Connector instance OracleASjms for the source JMS objects, and the JMS Connector instance ojmsaq for the target objects.

<?xml version="1.0"?>
<jms xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchema Location="http://www.oracle.com/technology/oracleas/schema/jms-server-10_1.xsd" schema-major-version="10" schema-minor-version="1">
  <!-- OracleAS JMS server configuration -- omitted for brevity  -->
  <jms-server>
     ...
  </jms-server>

  <!-- JMS Router configuration -->
  <jms-router max-local-concurrency="-1" >

      <router-job
          job-name="routerjob1"
          max-retries="16"
          polling-interval="5"
          pause-job="false"
          use-exception-queue="true"
          batch-size="30"
      >
          <!-- The name of an JMS Router source destination -->
          <message-source>OracleASjms/Topics/jms/mySource</message-source>

          <!-- Connection factory for the message source. -->
          <source-connection-factory>OracleASjms/MyCF</source-connection-factory>

          <!-- A message selector used at the message source -->
          <message-selector>color='blue'</message-selector>

          <!--This is the default subscriber name for this job as written to this file by the JMS Router -->
          <subscriber-name>OracleASRouter_routerjob1</subscriber-name>

          <!--There is no need to specify the log queue for OracleAS JMS, but the default value will be written back to this file by the JMS Router -->
          <source-log-queue>OracleASjms/Queues/OracleASRouter_LOGQ</source-log-queue>

          <!-- An exception queue --> 
          <exception-queue>OracleASjms/Queues/jms/myExQ</exception-queue>

          <!-- The name of an JMS Router target destination -->
          <message-target>ojmsaq/Queues/Queues/MyDBTarget</message-target>

          <!-Connection factory for the message target. -->
          <target-connection-factory>ojmsaq/CF</target-connection-factory>

          <!-- A log queue must be specified for all providers but OracleAS JMS. This queue must already exist  ->
          <target-log-queue>ojmsaq/Queues/Queues/MyJMSRouterLog</target-log-queue>

      </router-job>
  </jms-router>

</jms>

Managing the Router

This section describes the JMS Router MBean operations for managing the JMS Router.

The JMS Router MBean enables you to:

  • Start and stop individual JMS Router jobs

  • Monitor router job status

  • Monitor and query the JMS Router

Table 4-15, "JMS Router MBean Operations" lists and describes the JMS Router MBean operations.

Path to the JMS Router MBean:

OC4J:Home > Administration tab > Services > JMS Providers > Click the icon. > Select the appropriate tab. > Related Links: OracleASJMSRouter

Router Logging

The JMS Router logs all significant events and error messages to the standard OC4J log file. The logger name is oracle.j2ee.jms.router.

JMS Router Status Information

You can access JMS Router run-time status information using the RouterJobsStatus and RouterGlobalStatus attributes of the JMS Router MBean.

Table 4-17 JMS Router and Router Job Status

Statistic Description

NumberJobs

The number of configured jobs

RouterState

A string representing the JMS Router state

Retries

Number of times the JMS Router has failed to deliver a message for this job

ExceptionQMessages

Number of messages moved to exception queue by this job

LastErrorTime

If this job is in an error state, the time last error occurred

TargetQMessages

Number of messages propagated to target queue by this job

JobState

A string representing the state of this job


Error Handling

While processing a JMS Router job, the JMS Router may encounter various failures, such as an unreachable source or target destination or messaging operation failures. Based on the nature of the failures and the router job configuration, the JMS Router handles failures as follows:

If the JMS Router fails to enqueue a message to the target destination due to the content of the message and

  • if no exception queue exists or the flag useExceptionQueue is set to false for the associated router job, then the JMS Router stops processing the router job.

  • if an exception queue is provided for the job and the flag useExceptionQueue is set to true for the associated router job, then the JMS Router moves the message into the exception queue and the job continues processing subsequent messages.

When moving a message from the source destination to the exception queue, the JMS Router adds certain message properties to the original message to preserve error information. These messages are listed and described in Table 4-18, "Properties Added to Messages in Exception Queue".

Table 4-18 Properties Added to Messages in Exception Queue

JMS Property Description

oraMsgRouter_origMsgid

ID of the source message

oraMsgRouter_jobName

Name of the router job

oraMsgRouter_srcCF

Name of the connection factory used for dequeue/enqueue

oraMsgRouter_srcQName

Name of the source queue from which the message was obtained

oraMsgRouter_moveReason

Reason the message was moved to exception queue

oraMsgRouter_moveTime

Time the message was moved to exception queue


If the failure is not due to the content of a message, the JMS Router will automatically retry the failing operation in the increasing intervals

(2^n) * (pollingInterval),

with a maximum of 15 minutes, until it either succeeds or stops processing the router job when it reaches the configurable maximum number of retries specified in the maxRetries attribute, as described in Table 4-16, "JMS Router Settings" .

If the JMS Router stops processing a router job because the number of retries specified in the maxRetries setting has been reached, then users can call resetJob to reset the failure count to 0 to resume processing of the job.

The failure count of each job is stored in memory. Therefore, when the JMS Router restarts, the failure count of every job is reset to 0.

Pausing and Resuming a Job

A JMS Router job is in either activated or deactivated mode, as specified in the pauseJob setting, described in Table 4-16, "JMS Router Settings" .

The JMS Router does not process jobs that are in deactivated mode.

You can use the pauseJob operation in the JMS Router MBean to put a job in deactivated mode.

You can use the resumeJob operation in the JMS Router MBean to put a job in activated mode.

By default, jobs are created in activated mode.

Running In a Clustered OC4J Environment

In a clustered OC4J environment, a JMS Router instance may run on each OC4J instance. These JMS Router instances are configured independently and run without knowledge of each other. A JMS Router job that is configured on an OC4J instance is processed by only the JMS Router instance running in that OC4J instance.

  • Creating or managing a JMS Router job must be done using the JMS Router MBean or jms.xml file of a particular OC4J instance.

  • All JMS connection factories and JMS destinations that are referenced by JMS Router jobs defined on an OC4J instance must be accessible from that OC4J instance

  • If an OC4J instance is terminated, no jobs defined for the JMS Router instance running on the OC4J instance will be processed.

As a rule, different JMS Router jobs must not share a common source (i.e., a queue or a durable subscriber); otherwise, the JMS Router jobs may run into unrecoverable failures. In a clustered OC4J environment, this rule applies across all OC4J instances in the cluster.

  • A JMS queue that is not an OEMS JMS In-Memory or File-Based distributed destination, can only be the source of one JMS Router job across the entire OC4J cluster.

  • A JMS topic that is not an OEMS JMS In-Memory or File-Based distributed destination can be the source of multiple JMS Router jobs across the entire OC4J cluster. However, the associated durable subscriber names must be unique in the cluster. Specifically, if subscriber names of the JMS Router jobs are specified, the subscriber names must be different. If the subscriber names are not specified, the JMS Router job name must be unique across the cluster for jobs sharing the same topic as a source, since the JMS Router generates the durable subscriber names based on the JMS Router job names.

  • Each copy of an OEMS JMS In-Memory or File-Based distributed destination on an OC4J instance in a cluster is treated by the JMS Router as a separate JMS destination. In order to route messages from an OEMS JMS In-Memory or File-Based distributed destination, a JMS Router job using the destination as the source must be defined on each OC4J instance.

Routing with Remote Destinations

The JMS Router can route messages from one OC4J instance to another through OEMS JMS by using OEMS JMS remote connection factories. For more information, see Custom Topologies.

If a JMS Router job is defined using a connection factory for a remote OEMS JMS instance, any JMS destinations accessed using that connection factory must be defined on both the remote and local OC4J instances. If the source connection factory is remote, these JMS destinations include the message source, the JMS Router source log queue, and, optionally, an exception queue. If the target connection factory is remote, applicable JMS destinations include the message target, and the JMS Router target log queue.

When the message source or message target is remote, a JMS Router log queue needs to be created manually on the remote instance and specified when creating the JMS Router job.

Routing to Remote Destinations with OEMS JMS HTTP Tunneling

OEMS JMS provides HTTP tunneling to allow JMS messaging through firewalls. This feature is enabled by configuring a JMS HTTP tunnel provider on a web-serving OC4J instance. The web-serving OC4J instance may be located behind a firewall. This feature is only available for OEMS JMS In-Memory and File-Based. For more information regarding routing to remote destinations, see "Routing with Remote Destinations" and "Custom Topologies".

When a JMS HTTP tunnel provider is configured, JMS applications may use HTTP tunneling by looking up a connection factory with the tunnel, host, and port attributes defined. The tunnel attribute specifies the URL of the JMS HTTP tunnel provider. The host and port attributes specify the target JMS server which will service JMS requests. When the JMS application creates a JMS connection using such a connection factory, communications to the target JMS server are routed through the JMS HTTP tunnel provider. Communication between the application and the JMS HTTP tunnel provider uses HTTP (or HTTPS if configured to use SSL). Communication between the JMS HTTP tunnel provider and the target JMS server uses TCP.

Configuring the JMS HTTP Tunnel Provider

An OC4J instance acts as a JMS HTTP tunnel provider if an <http-tunnel> element is included in the OC4J instance's jms.xml configuration file. The <http-tunnel> element is an optional sub-element of the <jms-server> element. Each OC4J instance can have at most one JMS HTTP tunnel defined.

Note:

The OC4J instance must be restarted when the <http-tunnel> element is added, changed, or removed from an OC4J instance's jms.xml configuration file.

The following table describes the configuration elements for an <http-tunnel> node.

Table 4-19 OEMS JMS HTTP Tunnel Configuration

Elements and Attributes Description

authentication

The authentication attribute takes the value required or none. The default value is required.

The value required means the connection's user/password are authenticated by the JMS HTTP tunnel provider before being relayed to the target JMS server. Any authentication failure results in the request being rejected.

The value none means that the JMS HTTP tunnel provider relays JMS requests to the target JMS server without first authenticating the user (if all other settings allow it). Setting this property to none does not inhibit any authentication that the target JMS server may perform.

tcp-relay

The tcp-relay element indicates that JMS requests, whose target JMS server is in a different JVM than the JMS HTTP tunnel provider, are relayed to the target JMS server by the JMS HTTP tunnel provider (if all other settings allow it).

If the tcp-relay element is omitted, JMS requests whose target JMS server is in a different JVM than the JMS HTTP tunnel provider are rejected by the JMS HTTP tunnel provider.

filter

The filter attribute of the tcp-relay element can be either list or auto and is set to list by default.

The list value means the JMS HTTP tunnel provider only relays JMS requests to a target JMS server if the target JMS server's address is included in the list of target addresses. All other JMS requests are rejected by the JMS HTTP tunnel provider. Each target JMS server address in the list is specified using a target sub-element.

The auto value means the JMS HTTP tunnel provider checks if the target JMS server address (as specified by the host/port attributes in the connection factory definition) appears to address an actual JMS server. The provider sends a request to the given host/port using the tunneling protocol (sent using TCP). If a response is returned, the host/port is assumed to be a valid target for JMS requests and the request is relayed (if all other settings allow it).

Specific host/port combinations that are positively auto-detected are cached so auto-detection is not repeated for a given host/port. Auto-detection is convenient since no host/port list needs to be manually created. However, there is the potential that a server process listening on a non-JMS host/port which has not bee robustly coded might have a bad reaction to being probed during the auto-detection procedure. Auto-detection is considered to have failed if a valid response is not received within timeout.

timeout

The timeout attribute of the tcp-relay element limits the amount of time the JMS HTTP tunnel provider waits for a response from a target JMS Server. The value is entered in Milliseconds. The default value is 5000.

target

Each target sub-element under tcp-relay lists the host and port of a target JMS servers to which the JMS HTTP tunnel provider may relay JMS requests. This element is used when the tcp-relay filter is "list" and ignored when filter is auto. Multiple target elements may be specified. Each target address must be in the form:

<target host="host" port="port"/>


The following example demonstrates a JMS HTTP tunnel configured in the jms.xml file.

<jms>
   <jms-server>         ...                <http-tunnel authentication="required">                            <tcp-relay filter="list" timeout="5000">                                      <target host="host1" port="9127"/>                                         <target host="host2" port="9127"/>                              </tcp-relay>                      </http-tunnel>    ...     </jms-server>        <jms-router>         ...     </jms-router></jms>

Additional HTTP-Tunnel Examples

The JMS HTTP tunnel provider can be configured to relay JMS requests to a JMS server if both the JMS connection's username/password are valid at the JMS HTTP tunnel provider's OC4J instance (since authentication is set to required), and the target JMS server responds affirmatively to the JMS tunneling protocol:

<http-tunnel authentication="none"/>

The JMS HTTP tunnel provider can be configured to forward requests to any JMS Server if both the JMS Connection's username/password are valid at the JMS HTTP tunnel provider's OC4J instance (since authentication is set to required), and the target JMS Server responds affirmatively to the JMS HTTP protocol.

<http-tunnel authentication="required">      <tcp-relay filter="auto"/></http-tunnel>

The JMS HTTP tunnel provider can be configured such that it only relays JMS requests that are addressed to JMS servers at server1.xyz.com port 9127 or server2.xyz.com port 2000:

<http-tunnel authentication="none">          <tcp-relay filter="list">                  <target host="server1.xyz.com" port="9127">                <target host="server2.xyz.com" port="2000">     </tcp-relay></http-tunnel>

JMS HTTP Tunneling with SSL

The JMS HTTP tunnel provider feature is configured as a web application and can leverage OC4J's support for Secure Socket Layer (SSL) communication in both the Oracle Application Server using the Oracle HTTP Server and standalone without the Oracle HTTP Server.Refer to the Oracle Containers for J2EE Security Guide for instructions on setting up SSL communication.

Configuring Connection Factories

OEMS JMS applications only tunnel through a JMS HTTP tunnel when the connection factory configuration includes a tunnel attribute set to the URL of a configured OEMS JMS HTTP tunnel provider.The JMS connection factory attributes are set in addition to the connection factory attributes described earlier in this chapter in Table 4-1.

Note:

The OC4J instance must be restarted when a connection factory is added, changed, or removed from an OC4J instance's jms.xml configuration file.

Table 4-20 Connection Factory Attributes

Attributes Description

tunnel

This attribute is the URL of the JMS HTTP tunnel provider servlet. The URL must point to a JMS server which has the <http-tunnel> element defined in its jms.xml configuration file. This must be specified in the following format:

OC4J Standalone:

  • http:///hostname:port//jms (for non-SSL HTTP tunneling)

  • https:///hostname:port//jms (for HTTP over SSL tunneling)

iAS:

  • http:///hostname:port/j2ee//jms (for non-SSL HTTP tunneling)

  • https:///hostname:port/j2ee//jms (for HTTP over SSL tunneling)

The port number must point to an OC4J website with SSL enabled when using JMS HTTP tunneling over https.

keystore

This attribute includes the name and path of the keystore. The keystore is only used if tunneling through a JMS HTTP tunnel provider servlet with SSL. An absolute path is recommended.

keystore-password

This attribute is the keystore's password. This attribute must be present when the keystore attribute is specified.

truststore

This attribute includes the name and path of the truststore. If you do not specify a truststore, OC4J uses the keystore as the truststore. The trustore is only used if tunneling through a JMS HTTP tunnel provider servlet with SSL. An absolute path is recommended.

truststore-password

This attribute is the truststore password. This attribute must be present when the truststore attribute is specified.

Provider

This attribute is the name of the class which implements java.security.Provider for the Java Security API. If no value is specified, the default provider oracle.security.pki.OraclePKIProvider is used.The Provider attribute is only used when tunneling through a JMS HTTP tunnel provider servlet with SSL.


Connection Factory Configuration Examples

The following example creates an OEMS JMS QueueConnectionFactory that may be looked up at the JNDI location jms/SomeQCF. When used to create a JMS connection, the connection tunnels through the non-SSL HTTP tunnel located on host jmstunnelhost.

<queue-connection-factory         name="jms/SomeQCF"         location="jms/SomeQCF"     host="server1.abc.com" port="9127"    tunnel="http://jmstunnelhost:8888/jms"/>

The following example creates an OEMS JMS XATopicConnectionFactory that may be looked up at JNDI location jms/AnXaTCF. When used to create a JMS connection, the connection tunnels through the SSL HTTPS tunnel located on host server1.xyz.com provided the keystore and keystore-password are valid.

<xa-topic-connection-factory      name="jms/AnXaTCF"         location="jms/AnXaTCF"     host="server1.xyz.com" port="2000"    tunnel="https://server1.xyz.com:4443/jms"          keystore="/location/of/keystore"           keystore-password="keypass"/>

Resolving Host-Name Conflicts

The OEMS JMS In-Memory and File-Based options expect identifiers (such as message IDs) to be unique. The identifiers are constructed, in part, from the machine host names of the JMS server(s) and clients. If two different machines interacting with the same JMS server have the same host name, then IDs may not be unique and the JMS features may not function as expected.

For example, if JMS client A in intranet A uses the JMS HTTP tunnel provider to access a JMS server in intranet B, and JMS client B in intranet B also accesses that JMS server, the machine on which JMS client A is executing must have a different host name than the machine on which JMS client B is running. If JMS HTTP tunneling is used to connect two intranets, the administrators of those intranets must coordinate with each other to avoid host-name conflicts.

Note:

Two or more JMS servers (and/or JMS clients) operating in the same or different JVMs on the same machine (and therefore using a single host name) does not cause any problems since unique IDs are generated across and within the different JVMs. Host name conflicts are only problematic when two different machines have the same host name.

Configuring Logging for JMS

This section provides different options for configuring logging specific to JMS. OEMS utilizes the OC4J logging implementation to log messages that are related to JMS. The messages are typically used to troubleshoot and diagnose problems. OC4J logging is configured to use default settings. However, these settings can be changed specifically for JMS to get more detailed log messages. For more information on the OC4J logging implementation, see the Oracle Containers for J2EE Developer's Guide.

Standard JMS

There are two loggers that can be used to trace standard JMS functionality. These loggers include:

  • oracle.j2ee.jms – Used for basic JMS logging

  • com.evermind.server.jms.JMSServer – Used for advanced JMS server level logging from the main JMS server class

Standard JMS loggers are configured in the J2EE_HOME/config/j2ee-logging.xml file. For example, to configure advanced server-level logging and set the log level to FINEST, add the following logger node:

<loggers>
   ...
   <logger name='com.evermind.jms.JMSServer' level='FINEST'
      useParentHandlers='false'>
      <handler name='oc4j-handler'/>
      <handler name='console-handler'/>
   </logger>
<loggers>

In this example, messages from the logger are sent to the output as specified by the oc4j-handler and console-handler log handlers.

JMS Provider

The com.evermind.server.jms logger is used for obtaining log information for the entire OEMS JMS file persistence provider implementation. The JMS provider logger is configured in the J2EE_HOME/config/j2ee-logging.xml file. For example, to configure the logger and set the log level to FINEST, add the following logger node:

<loggers>
   ...
   <logger name='com.evermind.jms' level='FINEST'
      useParentHandlers='false'>
      <handler name='oc4j-handler'/>
      <handler name='console-handler'/>
   </logger>
<loggers>

In this example, messages from the logger are sent to the output as specified by the oc4j-handler and console-handler log handlers.

JMS Connector

When using the JMS connector, there is an option for setting a logger for all connectors and an option for setting a logger for each connector.

All Connectors

The oracle.j2ee.ra.jms.generic logger is used for all connectors. The logger is configured in the J2EE_HOME/config/j2ee-logging.xml file. For example, to configure the logger and set the log level to FINEST, add the following logger node:

<loggers>
   ...
   <logger name='oracle.j2ee.ra.jms.generic' level='FINEST'
      useParentHandlers='false'>
      <handler name='oc4j-handler'/>
      <handler name='console-handler'/>
   </logger>
<loggers>

In this example, messages from the logger are sent to the output as specified by the oc4j-handler and console-handler log handlers.

Each Connector

A logger can be configured for each connector to provide specific messages about the connector. The loggers are configured in the J2EE_HOME/config/oc4j-connectors.xml file or within the ra.xml file. For example:

<config-property>
   <config-property-name>loggerName</config-property-name>
   <config-property-type>java.lang.String</config-property-type>
   <config-property-value>mylog</config-property-value>
</config-property>
<config-property>
   <config-property-name>logLevel</config-property-name>
   <config-property-type>java.lang.String</config-property-type>
   <config-property-value>FINEST</config-property-value> </config-property>

Message Endpoint

Log levels can be adjusted for a specific message endpoint by using the LogLevel configuration property. This property should not be set in production code. It should only be set temporarily for debugging purposes.

The property is added in the orion-ejb-jar.xml file within a <message-driven-deployment> node. For example:

<enterprise-beans>
   <message-driven-deployment ... >
      ...
      <config-property>
         <config-property-name>LogLevel</config-property-name>
         <config-property-value>FINEST</config-property-value>
      </config-property>
   </message-driven-deploymnet>
</enterprise-beans>

Note:

The LogLevel property can also be set in the ejb-jar.xml file. For more information on using configuration properties, see "Fine Tuning MDB Endpoints". For a complete list of valid log levels that can be set, see the LogLevel entry in Table 4-11, "MDB Configuration Properties".

Using the oracle.j2ee.jms Implementation

This section provides instructions for using the oracle.j2ee.jms implementation. The following topics are included in this section:

Introducing the oracle.j2ee.jms Implementation

The oracle.j2ee.jms implementation is a near-complete redesign and rewrite of OC4J JMS that significantly improves performance. Use of the oracle.j2ee.jms implementation is optional and must be enabled. See "Enabling the oracle.j2ee.jms Implementation" for instructions on enabling the oracle.j2ee.jms implementation.

New Features

The oracle.j2ee.jms implementation provides the following new features:

  • User-Visible Features

    • multiple subscribers on a single subscription (helps applications scale)

    • connection-leak detection

  • Reliability

    • recover without data loss even if power loss causes an in-progress write to make the sector being written unreadable (subsequent read operations fail)

    • detects partial sector writes even if the disk does not

  • Concurrency Performance

    • minimal internal locking

    • does not use a thread-per-task model (i.e., can support many more active JMS operations than there are threads; easily scales to thousands of concurrent operations using only a handful of threads)

    • performance tends to scale with workload concurrency until a resource is saturated

  • Network Performance

    • multiple JMS connections operate over a single TCP connection

    • send batching

    • receive batching

    • transmission interleave to avoid blocking small messages

    • elimination of unnecessary server round trips

    • receivers use registration instead of periodic polling

  • File Performance

    • single persistence file

    • write batching

    • read batching

    • read reordering

    • in high-concurrency scenarios, persistent-messaging performance can meet or exceed OC4J JMS in-memory messaging performance

  • General Performance

    • low footprint messages (in memory, on disk, over network)

    • consumers avoid re-scanning messages that do not match their message selector

    • unnecessary serialization/deserialization of messages is avoided

    • unnecessary copying/duplication of messages is avoided

    • all JMS operations optimized (not just send/receive)

Limitations

The oracle.j2ee.jms implementation has the following limitations:

  • The oracle.j2ee.jms implementation may only be used with JDK 1.5 or higher.

  • JMS Message Router is not available when the oracle.j2ee.jms implementation is enabled.

  • Oracle DMS Metrics are not available for the oracle.j2ee.jms implementation.

Migration of the jms.xml File

The oracle.j2ee.jms implementation uses a new XML schema for the jms.xml file. The first time OC4J is started using the oracle.j2ee.jms implementation, the jms.xml file is automatically migrated from the old format to the new format. There is no automatic migration in the other direction; if you want to go back to running OC4J JMS, you must restore the jms.xml file manually. For this reason, if you are migrating from the OC4J JMS to the oracle.j2ee.jms implementation, it is recommended that you make a backup copy of your jms.xml file before starting OC4J with the oracle.j2ee.jms implementation.

Migration of Messages

While the migration of the jms.xml file will migrate connection factories and destinations, there is no automatic migration feature for messages. The oracle.j2ee.jms implementation is not able to use OC4J JMS persistence files. When configuring the persistence file for the oracle.j2ee.jms implementation, do not use any of the files created by OC4J JMS.

If you need to migrate messages from OC4J JMS to the oracle.j2ee.jms implementation, the JMS Message Router is one option. Configure router jobs where the job-source is a connection factory and destination of OC4J JMS and the job-destination is a connection factory and destination of the oracle.j2ee.jms implementation. Since OC4J can only run one version of OC4J JMS at a time, this technique requires running two OC4J JVMs: one configured to use OC4J JMS (and with OC4J JMS persistence files containing the messages), and one configured to use the oracle.j2ee.jms implementation. The JMS Message Router must be configured on the OC4J instance running OC4J JMS. This technique may not be applicable for migrating topic messages when the topic has more than one subscription as it does not maintain information about which subscriptions have received which messages.

Migration of Durable Subscriptions

Durable subscriptions are not migrated. A durable subscription is created in the oracle.j2ee.jms implementation persistence file when an application first creates a subscriber for that durable subscription (regardless of whether or not the subscription existed in OC4J JMS persistence files). The subscription will not receive any messages that were published before that point in time.

Network Interoperability

The oracle.j2ee.jms implementation is essentially a new JMS provider and is not interoperable with OC4J JMS. That is, a JMS client using the oracle.j2ee.jms implementation can not communicate with OC4J JMS. Likewise, a JMS client using OC4J JMS can not communicate with an oracle.j2ee.jms implementation.

JMS Router Compatibility

The JMS Router depends on internal details of OC4J JMS for the operation of its logging queue. Therefore the JMS Router can not be used in the oracle.j2ee.jms implementation.

However, if the JMS Router is used in an OC4J which is running OC4J JMS, it may be used to route messages to/from the oracle.j2ee.jms implementation's messages in the same way it is used to route messages to/from third party JMS providers such as Tibco and Sonic.

Enabling the oracle.j2ee.jms Implementation

When OC4J is started, it can use either OC4J JMS or the oracle.j2ee.jms implementation. OC4J is not able to use both implementations at the same time.

WARNING:

Running the oracle.j2ee.jms implementation irreversibly modifies the jms.xml file. Before enabling the oracle.j2ee.jms implementation, it is important that you read and understand the "Migration of the jms.xml File" section.

To enable the oracle.j2ee.jms implementation, set the following system property when starting OC4J:

-Doc4j.jms.implementation=oracle.j2ee.jms

This property only needs to be set for the OC4J server JVM. It does not need to be set for client JVMs.

Note:

the code for the oracle.j2ee.jms implementation is located within the oracle.j2ee.jms.* package hierarchy and the code for OC4J JMS is located within the com.evermind.server.jms.* package hierarchy. This can be used to verify which implementation you are using (either by doing a .getClass().getName() on any of the JMS objects [such as connection factories, destinations, connections, sessions, etc.], or by inspection of stack traces in exceptions or thread dumps).

Differences Between OC4J JMS and the oracle.j2ee.jms Implementation

This section outlines the differences between OC4J JMS (as described in the "OEMS JMS In-Memory and File-Based Persistence") and the oracle.j2ee.jms implementation. The subsection names below reference the section names from this chapter and are used to make correlation easier. The quotations are also from the referenced section. The text after each quotation explains how the oracle.j2ee.jms implementation differs.

OEMS JMS In-Memory and File-Based Persistence

"Provides an exception queue for undeliverable messages."

The oracle.j2ee.jms implementation does not provide an exception queue. For MDBs, the JMS Connector exception queue feature may be used. See the MaxDeliveryCnt property that is described in Table 4-11, "MDB Configuration Properties".

Configuring Destination Objects and Connection Factories

"Six default connection factories are created for the different combinations of XA (global transaction enabled), non-XA, and various JMS interfaces."..."The following default connection factories are created, even though they are not explicitly defined in the jms.xml file."...(etc.)The oracle.j2ee.jms implementation does not create any default connection factories. All desired connection factories must be explicitly configured. When migrating the jms.xml file, the explicit configuration for these six connection factories is added to the new jms.xml file.

The oracle.j2ee.jms implementation does not create any default destination stores. All desired destination stores must be explicitly configured. When migrating the jms.xml file, if the above destinations were already defined in the existing jms.xml file, they are migrated to the new jms.xml file- just like any other destination.

Configuring in the Application Server Control Console

Configuration options in the Application Server Control Console for the oracle.j2ee.jms implementation are very limited. Users should use the oracle.j2ee.jms implementation MBeans or configure jms.xml directly when the OC4J server is shutdown. See "Using the oracle.j2ee.jms Implementation MBeans" for detailed documentation on the MBeans.

The limits for using the Application Server Control Console are as follows:

  • The JMS Destinations page can only be used to create or delete a destination. Monitoring destinations is not available. The create destination feature will not allow a user to specify optional attribute available to the new provider. Users should use the new JmsConfigResource MBean to create destinations when optional attributes need to be specified.

  • The JMS Connection Factories page can be used to create, modify, or delete a connection factory; however, the username and password attributes do not apply to the oracle.j2ee.jms implementation.

  • The In-Memory and File Based Persistence page is not available.

  • The OracleAS JMS Router page is not available.

Configuration Using jms.xml

The oracle.j2ee.jms implementation jms.xml schema is comprised of two nodes: and OC4J JMS server elements.

  • <oc4j-jndi-bindings> – This node identifies those OC4J JMS objects which will bound to the OC4J JNDI. There are two types of objects, destination bindings and connection factory bindings. Destination bindings <destination-binding> binds a named destination to a specific JNDI location. This destination must be defined as a <destination> element either on the local OC4J JMS jms.xml or at a remote OC4J JMS server when the Dedicated JMS Server Topology. Factory bindings <factory-bindings> defines a JMS connection factory to a specific JNDI location.

  • <server> – This node controls the behavior of the JMS server (port settings, enabled, etc.) and the definition of JMS destinations. The destinations defined in the server element represent the physical storage for messages and includes several optional attributes to allow actions to override delivery modes, set eviction policies, etc.

An example jms.xml with the elements/attributes noted:

<jms>
   <oc4j-jndi-bindings>
       <!-- destination-binding, location, type, and name are required -->
       <destination-binding
           location="jms/myTopic"
           type="Topic"
           name="myTopic" />
       <!-- factory-binding, location and type are required -->
       <factory-binding
           location="jms/myTopicFactory"
           type="TopicConnectionFactory"
           name="myName"
           url="tcp://host:port"
           clientID="myid" />
   </oc4j-jndi-bindings>
   <server host="host" port="9127">
        <!-- destination, name and type are required -->
        <destination
            name="myTopic"
            type="Topic"
            deliveryModeOverride="PERSISTENT | NON-PERSISTENT"
            trueDeliveryModeVisibleToReceiver="true | false"
            durableSubscriptionsPersistent="true | false" >
   </server>
</jms>

Summary:

<server> attributes:

  • host – The host name defined in a String to which this server should bind. By default, the server binds to 0.0.0.0.

  • port – The port number to which the JMS server should bind. The default value is 9127.

  • enable – When enable is set to false, the JMS server will not start and will not be available for use.

    enablePort – When enablePort is set to true (the default), the JMS client listening port is enabled. When false, no JMS client listener port will be started.

    persistenceLocation – The optional location for the jms.dat persistence file. The path specified for the persistenceLocation attribute is either an absolute path of the file or a path relative to where the OC4J instance was started. When not specified, the persistence directory defined in the OC4J instance's application.xml is used.

    autoCreatePersistenceFile – A false setting will prevent the automatic creation of the persistence file in the case where the file does not already exist. This may be used to prevent the unwanted creation of extra persistence files if the file location is relative and the process in which OC4J JMS is run is accidental started with a different current directory. The default value is true.

<destination-binding> attributes:

  • location – Required attribute which specifies the OC4J JNDI location to bind the JMS destination.

  • type – Required attribute which specifies the JMS destination type, either Queue or Topic.

  • name – Required attribute which specifies the OC4J JMS destination name. This name must correspond to the name attribute for a <destination> defined at a JMS server.

<factory-binding> attributes:

  • location – Required attribute that defines an OC4J JNDI binding for an OC4J JMS connection factory.

  • name – Optional attribute that defines a name for the OC4J JMS connection factory.

  • type – Required attribute which specifies the JMS connection factory type, must be one of ConnectionFactory, QueueConnectionFactory, TopicConnectionFactory, XAConnectionFactory, XAQueueConnectionFactory, or XATopicConnectionFactory.

  • url – Optional attribute which provides the fixed address of the JMS server for this binding. Must be in the form tcp://host:port; where, host and port identify a specific JMS server. If this attribute is not provided, it is assumed to be the local JMS server.

  • clientID – Optional attribute which specifies the administratively configured, fixed JMS clientID for connections created from this connection factory.

<destination> attributes:

  • name – Required attribute that defines the name of the destination

  • type – Required attribute that defines the JMS type of the destination, must be either Queue or Topic.

  • deliveryModeOverride – Optional override for messages enqueued to this destination. When set to PERSISTENT then all message enqueued to the destination are persisted to file. When set to NON-PERSISTENT then all messages enqueued to the destination are not persisted to file. When not set, messages enqueued to the destination will be persisted to file or not based on the programmatic setting of the message's delivery mode.

  • trueDeliveryModeVisibleToReceiver – Optional, default is false. When set to false, the deliveryMode seen by the consumer of the message matches what was set by the message's producer, regardless of the setting of deliveryModeOverride and regardless of the message's actual delivery mode. When true, indicates that the delivery mode seen by the consumer of a message reflects the actual delivery mode of the message, including any change to the delivery mode due to deliveryModeOverride.

  • durableSubscriptionsPersistent – Optional, default is true. When set to true durable subscriptions are disk backed and survive JMS server restarts and accumulate all applicable messages (as per the JMS specification). When set to false, durable subscriptions are memory backed and do not survive JMS server restarts, messages accumulated before a JMS server restart are lost, messages published after a JMS restart and before the application recreates the durable subscription are not accumulated; are different than nondurable subscriber in that they are not destroyed when the corresponding subscribers are closed.

  • evictionPolicy – Optional, when the eviction policy is never, cached messages are never evicted from memory. Such messages will consume memory until they are destroyed (permanently consumed, expired, or subscription destroyed). With this policy, sent messages always remain in memory until they are needed, which in some scenarios results in best performance. However, if the JVM runs low on memory, it will not be able to discard cached messages and may throw OutOfMemoryError, generally causing the server to fail to continue operating. When the eviction policy is softRef, fully persistent cached messages (which are not currently in the process of being sent/transacted/consumed/browsed) are held only via a java.lang.ref.SoftReference, which allows the JVM to reclaim the memory consumed by the cached message. This may decrease performance as any message so evicted will need to be loaded from disk when it is needed, and some JVMs may be more aggressive than others in evicting objects held via soft references. However, if the JVM runs low on memory and there are idle messages cached, the JVM will have the option of discarding such cached messages rather than running out of memory and causing the server to fail

Configuring Ports

In a standalone OC4J instance, you can set the oracle.j2ee.jms implementation port value using the JmsConfigResource MBean's changeServerAttribute operation. Changing the oracle.j2ee.jms implementation server port will force a restart of the JMS server.

In an Oracle Application Server environment (managed), use the Application Server Control Console to configure the port range.

Path to configure the port range in the Application Server Control Console:

OC4J:Home > Administration tab > Task Name: JVM Properties > JMS Ports

Using the JMS Utility

The oracle.j2ee.jms implementation does not provide a command-line utility for runtime configuration. Users should utilize the new JMS MBeans described next.

Using JMS MBeans

The oracle.j2ee.jms implementation provides two JMX MBeans: JmsConfigResource and JmsOperationsMBean. See "Using the oracle.j2ee.jms Implementation MBeans" for detailed documentation on the MBeans' operations.

  • JmsConfigResource MBean – The JmsConfigResource MBean provides operations that manipulate the oracle.j2ee.jms implementation configuration. The JmsConfigResource MBean may be accessed using the Application Server Control Console through the path:

    OC4J:Home >Administration tab > TaskName: JMX.System MBeanBrowser. > Go To Task >Drill down:J2EEDomain:oc4j,J2EEServer:standalone,JmsConfigResource, "JmsConfig" >Operations tab

  • JmsOperationsResource MBean – Bean provides runtime operations for creating, removing, and monitoring topic subscriptions. The JmsOperationsResource MBean may be accessed using the Application Server Control Console through the path:

    OC4J:Home >Administration tab > TaskName: JMX.System MBeanBrowser. > Go To Task >Drill down:J2EEDomain:oc4j,J2EEServer:standalone,J msOperationsResource,"JmsOperations" >Operations tab

Configuring File-Based Persistence

"If OC4J is not active, then deleting a persistence file is equivalent to deleting all messages and durable subscriptions in the destination associated with that persistence file."

For the oracle.j2ee.jms implementation, all destinations are stored in a single persistence file, so deleting that file is equivalent to deleting all messages and durable subscriptions in all destinations.

"Each destination can be associated with a relative or absolute path name that points to a file that stores the messages sent to the destination object."

For the oracle.j2ee.jms implementation, all destinations are stored in a single persistence file - there is only one persistence file per JMS server.

Path to specify persistence files for destinations in the Application Server Control Console:"

For the oracle.j2ee.jms implementation, the path for the persistence file may be specified by utilizing the JmsConfigResource MBean's changeServer attribute operation.

"The path for the persistence-file attribute is either an absolute path of the file or a path relative to the persistence directory defined in application.xml."

For the oracle.j2ee.jms implementation, the path to the persistence file is determined by the server's persistenceLocation attribute.

Scope of Recoverability

"A java.io.FileDescriptor.sync() failure"

The oracle.j2ee.jms implementation uses java.nio.channels.FileChannel.force(true) (if persistence file size changed) or java.nio.channels.FileChannel.force(false) (if persistence file size did not change) rather than java.io.FileDescriptor.sync(), but the principle remains the same. Specifically, the call to force must not return until after data written to the file before the force reaches the physical media (if the disk does not have a battery-backed write cache) or the disk's cache (if the disk has a battery-backed write cache).

The following information is specific to the oracle.j2ee.jms implementation:

  • All writes are 512-byte aligned and consist of a whole number of sequential 512-byte blocks. Most spinning disks have sectors of 512 bytes. The remainder of this section will use the term sector to mean "512-byte block that is 512-byte aligned" and use the term physical sector to refer to raw device block size.

  • The following are not required for data integrity:

    • The file system and disk do not need to write sectors either in the order the write operations were issued or in the order of the sectors within the individual writes. That is, the file system and disk are free to reorder sector writes (and intersperse them with reads) in order to increase performance. The only ordering required is with respect to force, as described previously.

    • When the file is grown, the file system does not need to zero-fill the new file space (though it may choose to do so for security reasons).

    • When the file is shrunk, the file system does not need to zero-fill the released sectors. (It may choose to do so for security reasons, though it will be redundant.) In order to prevent message data being leaked to unauthorized users, the new OC4J JMS always zero-fills sectors to be released before shrinking the file.

  • In order to ensure data integrity, the oracle.j2ee.jms implementation must be able to detect partial sector writes (For example, if power is lost during a write operation). In order to achieve this, the disk must provide at least one of the following guarantees:

    • Guarantee Option #1: Byte Ordering

      Any given write of a sector is performed either in a first-byte-to-last or a last-byte-to-first order.

      This ordering guarantee allows headers/footers embedded in each sector by the oracle.j2ee.jms implementation to be used to detect partial sector writes. Spinning disks (with a physical sector size >= 512 bytes) generally provide this ordering guarantee.

    • Guarantee Option #2: Write Failure Detection

      Any given write of a sector during a failure is guaranteed to have one of the following three results:

      • The write is not reflected at all.

      • The write completes successfully.

      • The write starts and does not fully complete, but the drive is able to detect this and fails any attempts to read this sector (i.e., java.nio.channels.FileChannel.read throws an exception).

      This write-failure-detection guarantee allows thrown exceptions to be used by the oracle.j2ee.jms implementation to detect partial sector writes.

    • Guarantee Option #3: Atomic Sector Writes

      Any given write of a sector during a failure is guaranteed to have one of the following two results:

      • The write is not reflected at all.

      • The write completes successfully.

      This atomic-sector-write guarantee means that there are never any partial sectors which need to be detected by the oracle.j2ee.jms implementation. Disks with batteries (or capacitors) used to either maintain the write-cache contents until power is restored or to complete pending writes without waiting for power to be restored generally provide the atomic-sector-write guarantee.

  • Solid state disks (SSDs) do not provide the byte-ordering guarantee. An SSD without one of the battery/capacitor features described above may provide either the write-failure-detection or atomic-sector-write guarantee. Currently such SSDs generally only provide these guarantees in a probabilistic sense (for example, using ECC checks that only have a certain percent chance of detecting errors). Furthermore, ECC reliability numbers typically are only provided for the "small number of bit errors" case and are not valid for the "large number of bit errors due to partial sector write" case (where the chance of detection-failure will be many orders of magnitude greater).

  • The oracle.j2ee.jms implementation grows the persistence file as required and (very lazily) shrinks the persistence file as circumstances allow. In order to ensure data integrity, the file system metadata used to record the existence of files along with what disk space is allocated to those files must be resilient to failure (for example, power loss), even if the failure occurs during a metadata update.

  • The oracle.j2ee.jms implementation never rewrites sectors that contain live data. For example, when a message's JMSXDeliveryCount is updated, the sector containing the current JMSXDeliveryCount is not rewritten. Instead a new sector is written that (possibly among other things) notes the new value of JMSXDeliveryCount for the given message. One very important reason for this is that rewriting a sector would put all of the data in that sector in jeopardy. For example, if the send of a message was already committed, and during a receive the sector containing the message is rewritten to update its JMSXDeliveryCount (hypothetically speaking - the oracle.j2ee.jms implementation never writes over live data), and during that rewrite power is lost, the entire message (along with any other data in that sector) could become permanently corrupted and unretrievable.

    In addition to the oracle.j2ee.jms implementation not rewriting sectors that contain live data, it's equally important that no one else rewrite sectors that contain live data. In particular, some file systems will rewrite sectors to the disk even when those sectors were not rewritten to the file system. This is typically called "read-modify-write". For example, if the oracle.j2ee.jms implementation writes sector #N, such a file system may read sectors #N-3 through #N+4, and then when force is called the file system may write all of the sectors (N-3 through N+4) even though most of those sectors were not written by the oracle.j2ee.jms implementation. Besides wasting disk bandwidth and decreasing performance by reading and writing sectors the oracle.j2ee.jms implementation did not attempt to access, this potentially places live data at risk.

    In order to ensure data integrity, such file systems should be avoided. (If such a file system can not be avoided, the risk that read-modify-write poses can be reduced, though not necessarily eliminated, with the use of a battery-backed disk. If the file system block size can be reduced to be closer to 512 bytes, that too will reduce the risk posed, as well as reduce the performance impact caused by read-modify-write.)

    Additionally, disks with physical sector sizes larger than 512 bytes will generally have to perform read-modify-write operations. In order to ensure data integrity, such disks should be battery-backed.

    RAID systems with parity will also generally have to perform read-modify-write operations, but depending on the specifics of the system and how it is operated, these read-modify-writes may or may not have an impact on data integrity and are considered beyond the scope of this document.

Persistence File Management

"copy - An existing persistence file can be copied for archival or backup purposes. If an existing persistence file becomes corrupted, an earlier version can be used (as long as the association between the OEMS JMS destination name and the file is maintained), pointed to by any suitable path name, to go back to the previous contents of the JMS destination."

This is also true for the oracle.j2ee.jms implementation except that there is no association between destination and file as there is only one persistence file per JMS server. However, it should be noted that if you restore the oracle.j2ee.jms implementation's persistence file to a previous version without restoring the transaction manager's data (and the data of every other resource involved in an XA transaction) to the same point in time, then XA transaction inconsistencies may exist. If only the JMS persistence file is restored, then the transaction manager will likely rollback any transactions it recovers from JMS about which it no longer has any information, even if those transactions were originally committed (and for other, non-JMS resources are still committed).

"In addition to persistence files specified by a user and lock files, the OEMS JMS In-Memory and File-Based options use a special file, jms.state, for internal configuration and transaction state management. The OEMS JMS server cleans up this file and its contents during normal operations. You must never delete, move, copy, or otherwise modify this file, even for archival purposes. Attempting to manipulate the jms.state file can lead to message and transaction loss."

For the oracle.j2ee.jms implementation, there is no distinct jms.state file. There is only the single persistence file.

Abnormal Termination

If OC4J terminates normally, then the lock files are cleaned up automatically. However, if OC4J terminates abnormally, for example, a kill -9 command, then the lock files remain in the file system."

The oracle.j2ee.jms implementation does not use .lock files and instead uses a file system lock. Therefore, there are never any .lock files to clean up.

Recovery Steps

"The server must be shut down or restarted repeatedly to give recovery another chance, until recovery is successful."

The oracle.j2ee.jms implementation generally does not require repeated restarts. If the file is recoverable, the oracle.j2ee.jms implementation will recover it on the first attempt. (The only exception is if successful start up requires more heap memory than is available, resulting in an OutOfMemoryError. In that case, the JVM should be configured to have a larger heap before trying again.)

"If messaging activity was in progress during abnormal termination, then OEMS JMS tries to recover its persistence files. Any data corruption (of the types mentioned earlier) is handled by clearing out the corrupted data; this may lead to a loss of messages and transactions."

The oracle.j2ee.jms implementation never clears out live data that was successfully committed (or successfully prepared and not rolled back). If an operation is in progress at the time of abnormal termination and that operation is not fully written to disk, then that operation will be automatically rolled back during the next startup. (For example, if a receive of a persistent message is in an XA transaction, and the transaction has been successfully prepared but not committed, and during the commit operation power is lost and the commit record is not fully written to disk, then during the next startup the partial commit record will be dropped and the XA transaction returns to its prepared state. The transaction will then be committed when the Transaction Manager reissues the commit. If on the other hand the power had been lost during the prepare operation such that the prepare record was not fully written to disk, then the entire transaction would be automatically rolled back during the next startup and the message would become once again ready to be received.)

"If the headers of a persistence file are corrupted, OEMS JMS may not be able to recover the file, because such a corrupted file is often indistinguishable from user configuration errors. The oc4j.jms.forceRecovery administration property (described in Table 4-6, " System Properties" on page 4-40) instructs the JMS server to proceed with recovery, clearing out all invalid data at the cost of losing messages or masking user configuration errors."

The oracle.j2ee.jms implementation never confuses persistence file corruption with configuration errors (with the one exception of the jms.xml pointing somewhere else other than the actual persistence file). If the file corruption is recoverable (e.g., a partially written, possibly even unreadable sector due to a power loss while writing that sector) then the file is automatically recovered (e.g., the partially written operation is rolled back and the unreadable sector is rewritten with zeros to allow the disk drive to correct the sector's ECC and return the sector to being readable to avoid the potential for "false alarms" during future restarts). If the file corruption is not recoverable (e.g., OC4J JMS detects that parts of the file potentially containing data that was previously successfully written are now missing/corrupted) then startup will abort with an error message and the persistence file will not be modified. There is no way to force recovery with the oracle.j2ee.jms implementation (short of deleting the entire persistence file and all of the messages/subscriptions/transactions it contains).

Predefined Exception Queue

The oracle.j2ee.jms implementation does not provide an exception queue. For MDBs, the JMS Connector exception queue feature may be used. See the MaxDeliveryCnt property that is described in Table 4-11, "MDB Configuration Properties".

Message Paging

The oracle.j2ee.jms implementation does not provide an oc4j.jms.pagingThreshold setting. By default the oracle.j2ee.jms implementation uses soft references for caching persistent messages. This allows the JVM to automatically evict such cached messages from memory as needed. If a message has been evicted by the JVM and the application attempts to receive or browse the message, then OC4J JMS automatically reloads the message from disk.

Soft references provide some advantage over oc4j.jms.pagingThreshold in that the JVM's garbage collector is in control and can evict in-memory copies of messages to make room for new allocations on the heap, avoiding OutOfMemoryErrors. This is especially true given that oc4j.jms.pagingThreshold only evicts messages periodically, and a rapid allocation of memory between two such runs could cause memory to be exhausted even when there were enough evictable messages that sufficient memory could have been made available.

Soft references may also have some disadvantage compared to oc4j.jms.pagingThreshold if the JVM's garbage collector is too aggressive at evicting in-memory copies of messages, performance may suffer as messages then have to be read from disk rather than having remained cached. If you know that certain destinations will never contain too many messages (i.e., will not cause OutOfMemoryErrors), then you can set the eviction policy for those destinations to never rather than softRef. Then the messages in those destinations will never be evicted from memory and (unless the server is restarted) will not need to be read from disk.

"Only message bodies are paged. Message headers and properties are never paged."

The oracle.j2ee.jms implementation is able to evict headers and properties for topic messages (but not for queue messages).

JMS Configuration Properties

"The primary tool for editing configuration properties at runtime is the JMSAdministrator MBean."

...

"As a secondary method, in standalone, you can pass the configuration properties in as a command line argument as follows"

...

"These property settings are persisted in the jms.xml file."

...

"Setting JMS Configuration Properties in the jms.xml File"

The oracle.j2ee.jms implementation only supports setting properties as system properties. The oracle.j2ee.jms implementation does not support setting properties in the jms.xml file.

Pre-Existing System Properties:

  • oc4j.jms.messagePoll – The oracle.j2ee.jms implementation does not provide this property as it is not needed. The oracle.j2ee.jms implementation does not poll for messages as polling wastes server and network resources and provides poor response times.

  • oc4j.jms.listenerAttempts – The oracle.j2ee.jms implementation does not provide this property. For MDBs, the JMS Connector exception queue feature may be used. See the MaxDeliveryCnt property that is described in Table 4-11, "MDB Configuration Properties".

  • oc4j.jms.maxOpenFiles – The oracle.j2ee.jms implementation does not provide this property as it is not needed. The oracle.j2ee.jms implementation uses a single persistence file rather than one file per destination. That means there is neither any need nor any possibility of reducing the number of concurrently open files during JMS server operation.

  • oc4j.jms.forceRecovery – The oracle.j2ee.jms implementation does not provide this property as any corruption which can be corrected is corrected automatically and any corruption which can not be corrected can not be corrected. There is no way to force recovery with the oracle.j2ee.jms implementation (short of deleting the entire persistence file and all of the messages/subscriptions/transactions it contains).

  • oc4j.jms.noDms – The oracle.j2ee.jms implementation does not provide this property as it does not generate DMS events.

  • oc4j.jms.pagingThreshold – The oracle.j2ee.jms implementation does not provide this property as it implements a SoftReference-based eviction policy instead. See "Message Paging". Also, see the evictionPolicy property in the "Configuration Using jms.xml".)

  • oc4j.jms.pseudoTransactionEnlistment – The "pseudo transaction enlistment" feature was previously deprecated and is not available with the oracle.j2ee.jms implementation.

  • oc4j.jms.debug – The oracle.j2ee.jms implementation does not provide this property. However, see oracle.j2ee.jms.v1.unsupportedOptions.enableMessageTracing and oracle.j2ee.jms.v1.unsupportedOptions.debug below.

  • oc4j.jms.serverPoll, oc4j.jms.saveAllExpired, oc4j.jms.socketBufsize – The oracle.j2ee.jms implementation does not provide these properties.

New System Properties - Supported For Production Use:

  • oc4j.jms.implementation – This property is used to select the implementation of OC4J JMS to use. It is used to enable the oracle.j2ee.jms implementation. See "Enabling the oracle.j2ee.jms Implementation".

    type: Stringdefault: com.evermind.server.jms (OC4J JMS) JVM: server

  • oc4j.jms.suppressExceptions.Message.setJMSReplyTo – Normally when javax.jms.Message.setJMSReplyTo is called with a foreign destination (i.e., an implementation of javax.jms.Destination from some JMS provider other than the oracle.j2ee.jms implementation) a ClassCastException is thrown. If you try to send an OC4J JMS message using another JMS provider, the other JMS provider may call setJMSReplyTo. For some JMS providers, the entire send operation will fail if the ClassCastException is thrown by SetJMSReplyTo. If you need to make OC4J JMS interoperable with such a JMS provider, you can set oc4j.jms.suppressExceptions.Message.setJMSReplyTo to true and then the call to setJMSReplyTo will silently fail (not set the JMSReplyTo) rather than throw ClassCastException.

    type: booleandefault: falseJVM: client

  • oc4j.jms.suppressExceptions.Message.setJMSType – Per the JMS specification, the valid type names for JMSType are provider-specific. For the oracle.j2ee.jms implementation, the only valid type name is null. Normally, calling javax.jms.Message.setJMSType with any other type name than null will result in setJMSType throwing a JMSException. If you try to send an OC4J JMS message using another JMS provider, the other JMS provider may call setJMSType with values other than null. For some JMS providers, the entire send operation will fail if the JMSException is thrown by setJMSType. If you need to make OC4J JMS interoperate with such a JMS provider, you can set oc4j.jms.suppressExceptions.Message.setJMSType to true and then the call to setJMSType will silently fail (not set the JMSType) rather than throw JMSException.

    type: booleandefault: falseJVM: client

New System Properties - Not Supported For Production:

These properties are not supported for production use, must not be used in production, and must not be used against an OC4J JMS persistence file that will be used in production. Also, these properties may not exist or may behave differently in future versions of the product. However these properties are documented as they may be useful during development/debugging.

  • oracle.j2ee.jms.v1.unsupportedOptions.enableMessageTracing – See "Using Message Tracing" for documentation on the message tracing feature.

    type: booleandefault: falseJVM: server and client

  • oracle.j2ee.jms.v1.unsupportedOptions.protocolDebug – Even during normal operation, the client and server always verify that all communications correctly follow protocol. Any detected protocol failures typically result in an exception being thrown (if the client detects the failure) or a JMS connection being immediately closed (if the server detects the failure). If connections are being mysteriously dropped or other unexplainable problems occur, you may want to set oracle.j2ee.jms.v1.unsupportedOptions.protocolDebug to true to see if protocol errors are being detected. Protocol errors might be caused by having one version of a client talk to a different version of the server, by having a oracle.j2ee.jms implementation client or server talking with some unrelated TCP client/server, or due to network problems which corrupt the TCP data stream.

    type: booleandefault: falseJVM: server and client

  • oracle.j2ee.jms.v1.unsupportedOptions.debug – Setting this property to true causes some verbose debug output being generated about calls to send/receive and XA methods. The message tracing feature is generally more useful as it is more targeted and provides better tracking of a message moving through the system. This property may be used as a way to get some information without modifying the code to enable proper message tracing.

    This property only works with local connections (connections between a client and server where the client and server are running in the same JVM).

    type: booleandefault: falseJVM: server

  • oracle.j2ee.jms.v1.unsupportedOptions.all.debugSetClientID – Per the JMS specification, javax.jms.Connection.setClientID must be the first operation on any given connection. If setClientID is failing due to a prior operation on the connection (generating a "clientID may not be set at this time" exception message) and you do not know what operation was performed on the connection, then the above property may help. When oracle.j2ee.jms.v1.unsupportedOptions.all.debugSetClientID is set to true, the stack trace of the operation which preceded the setClientID call is recorded. (The operation will be the constructor if the clientID is set administratively via the jms.xml file.) If setClientID is then called, the stack trace of the prior operation is sent to System.out.

    This property only works with remote connections (connections between a client and server where the client and server are not running in the same JVM).

    type: booleandefault: falseJVM: client

  • oracle.j2ee.jms.v1.unsupportedOptions.enableTempDestTracing – Setting this property to true causes a stack trace to be displayed whenever a temporary destination is created or destroyed.

    type: booleandefault: falseJVM: server

Required Class Path for Application Clients Using Direct OEMS JMS In-Memory and File-Based Lookup

For pure JMS use, clients of the oracle.j2ee.jms implementation only needs two JAR files: oc4j-jms-client.jar and jms.jar

If the JMS client creates connection factories rather than looking them up in JNDI, and the client uses the javax.jms.Session createQueue and createTopic methods rather than looking up destinations in JNDI, then no other classes are required.

If the JMS client uses OC4J's JNDI service to look up connection factories and/or destinations, then the class libraries listed in the referenced section are required.

Directly Creating Connection Factories

The oracle.j2ee.jms implementation connection factories are implemented as Java beans. You can create them directly using no-arg constructors:

oracle.j2ee.jms Implementation Class Interface Implemented
oracle.j2ee.jms.v1. ConnectionFactoryImpl javax.jms.ConnectionFactory
oracle.j2ee.jms.v1. QueueConnectionFactoryImpl javax.jms.QueueConnectionFactory
oracle.j2ee.jms.v1. TopicConnectionFactoryImpl javax.jms.TopicConnectionFactory
oracle.j2ee.jms.v1. XAConnectionFactoryImpl javax.jms.XAConnectionFactory
oracle.j2ee.jms.v1. XAQueueConnectionFactoryImpl javax.jms.XAQueueConnectionFactory
oracle.j2ee.jms.v1. XATopicConnectionFactoryImpl javax.jms.XATopicConnectionFactory

Once instantiated, set methods may be used to set the same connection factory properties that are supported in the jms.xml file:

set method connection factory property
setUrl(String) url - The URL is of the form tcp://<host>:<port> where <host> is either a hostname or literal IP address and <port> is an integer in the range of 1 to 65535. For to-same-JVM-as-server connection factories, the URL does not need to be set.
setClientID(String) clientID
setName(String) name
setLeakDetect(String) leakDetect (see below)
setEnableJMSXConsumerTXID(boolean) enableJMSXConsumerTXID (see below)
setEnableJMSXRcvTimestamp(boolean) enableJMSXRcvTimestamp (see below)

The connection factory Java beans also implement the corresponding get methods. This approach introduces three additional connection factory properties that cannot be configured through the JMX Mbeans or the jms.xml configuration file.

  • leakDetect

    The settings are: none: This is the default setting. No leak detection is done, and there is essentially no performance impact. silent: With this setting (and the log/track settings) a class with a finalizer is used to wrap every connection created using this connection factory. The finalizer determines if the connection has not been closed yet, and if not, closes it. This is an "emergency" setting - a temporary stop-gap measure that should be used only while an application is being repaired. It should not be considered (and is not) a suitable replacement for closing connections. log: With this setting (and the track setting), in addition to auto-closing the connection, the fact that there was a leak is logged along with the name of the factory used to create the connection (if one was set - see 'name' property). track: This setting is like log, but also provides the stack trace recorded during connection creation.

    This property must not be set more than once in any given context.

    Type: String

    Values: none, silent, log, track

  • enableJMSXConsumerTXID

    When JMSXConsumerTXID is enabled and a message is received inside an XA transaction, the transactions ID is automatically stored in the message as the JMSXConsumerTXID property. When JMSXConsumerTXID is not enabled, applications are still able to set/get the JMSXConsumerTXID property, but freshly received messages will never have JMSXConsumerTXID set, even if the property was set by the sender. An application can determine whether or not JMSXConsumerTXID is enabled by inspecting the connection's metadata (see javax.jms.ConnectionMetaData.getJMSXPropertyNames).

    This property must not be set more than once in any given context.

    Type: boolean

  • enableJMSXRcvTimestamp

    When JMSXRcvTimestamp is enabled and a message is received, the current time is automatically stored in the message as the JMSXRcvTimestamp property. When JMSXRcvTimestamp is not enabled, applications are still able to set/get the JMSXRcvTimestamp property, but freshly received messages will never have JMSXRcvTimestamp set, even if the property was set by the sender. An application can determine whether or not JMSXRcvTimestamp is enabled by inspecting the connection's metadata (see javax.jms.ConnectionMetaData.getJMSXPropertyNames).

    This property must not be set more than once in any given context.

    Type: boolean

Using the oracle.j2ee.jms Implementation MBeans

The oracle.j2ee.jms implementation includes the JmsConfigResource MBean and the JmsOperationsResource MBean. These MBeans provide various operations for configuring and administering the oracle.j2ee.jms implementation. This section describes the operations that are available for each MBean.

JmsConfigResource MBean

The JmsConfigResource MBean provides operations that manipulate the oracle.j2ee.jms implementation configuration. The JmsConfigResource MBean may be accessed using the Application Server Control Console through the path:

OC4J:Home >Administration tab > TaskName: JMX.System MBeanBrowser. > Go To Task >Drill down:J2EEDomain:oc4j,J2EEServer:standalone,JmsConfigResource, "JmsConfig" >Operations tab

Table 4-21 JmsConfigResource MBean Operations

Operations Group Operation Operation Description

destination-binding

showDestinationBinding

Given a location, show one destination-binding.

 

showDestinationBindings

Return a list of all destination-bindings.

 

addDestinationBinding

Add a new destination-binding.

 

removeDestinationBinding

Remove an existing destination-binding.

factory-binding

showFactoryBinding

Given a location, show one factory-binding.

 

showFactoryBindings

Return a list of all factory-bindings.

 

addFactoryBinding

Add a new factory-binding.

 

removeFactoryBinding

Remove an existing factory-binding.

destination

showDestination

Given the destination type and name, show it's attributes.

 

showDestinations

Return a list of all destinations.

 

addDestination

Add a new destination.

 

removeDestination

Remove an existing destination.

same-jvm-client-properties

showSameJvmClientProperty

Show the value of a same-jvm-client-property.

 

showSameJvmClientProperties

Return a list of all same-jvm-client-properties.

 

addSameJvmClientProperty

Add a new same-jvm-client-property.

 

removeSameJvmClientProperty

Remove a same-jvm-client-property.

server property

showServerProperty

Show the value of a server property.

 

showServerProperties

Return a list of all server properties.

 

addServerProperty

Add a new server property.

 

removeServerProperty

remove a server property.

server attribute

showServerAttribute

Show the value of a server attribute.

 

changeServerAttribute

Change (or add) a server attribute.

 

removeServerAttribute

Remove a server attribute.


JmsOperationsResource MBean

The JmsOperationsResource MBean provides runtime operations for creating, removing, and monitoring topic subscriptions. The JmsOperationsResource MBean may be accessed using the Application Server Control Console through the path:

OC4J:Home >Administration tab > TaskName: JMX.System MBeanBrowser. > Go To Task >Drill down:J2EEDomain:oc4j,J2EEServer:standalone, JmsOperationsResource,"JmsOperations" >Operations tab

Table 4-22 JmsOperationsResource MBean Operations

Operations Group Operations Description

Manage Subscriptions

subscribe

Create a new subscription for a topic.

 

unsubscribe

Unsubscribe an existing subscription.

 

drainSubscription

Drain undelivered messages for a subscription.

Provider Specific Extentions

showSubscriptionMessageHeaders

Return a list of JMS headers for undelivered messages for a subscription.

 

browseSubscription

Return a XML formatted string who's content is the undelivered messages for a subscription.

Subscription Summaries

showSubscriptionSummaries

Return a list of subscriptions for one or all JMS topics.

 

showSubscriptionSummary

Return the subscription summary for a specific subscription.


Using Message Tracing

Message tracing is an unsupported feature used for debugging JMS applications. It allows an application developer to tag a message, and then watch as the message moves through the oracle.j2ee.jms implementation. This allows the developer to see where things are going wrong (i.e., where the message gets discarded or stuck). It can also be used to verify that things are going right (i.e., see messages being persisted, messages moving through transactions, messages expiring, delivery counts being updated, etc.).

How to Enable Message Tracing

Start the JVM with the following option:

-Doracle.j2ee.jms.v1.unsupportedOptions.enableMessageTracing=true

The property must be set for the JVM which will be tagging the message to trace and must also be set for every JVM in which tracing output is desired. Most tracing output is generated by the JVM containing the JMS server, but any JVM containing a JMS client which impacts/accesses the message (e.g., send, receive, browse, commit, rollback) will also generate tracing output (if tracing is enabled).

You can tell that message tracing is enabled in a given JVM if it outputs the following message:

message tracing is enabled

Client JVMs may not output the message until JMS operations are performed. (The output is generated during oracle.j2ee.jms.v1.MessageImpl class initialization, which won't happen until the class loader decides to load and initialize the MessageImpl class.)

How to Tag a Message for Tracing

Place the following in your code to tag a message before it is sent:

message.setBooleanProperty("JMS_OC4J_TraceMe", true);

The above will result in the output:

JMS_OC4J_TraceMe = true; tracing message

You can also set the property to false, but that will not stop tracing for copies of the message that were already sent. It will only prevent additional tracing if the message is sent again.

Message tagging is persistent. (You can stop/start the server, and if the message was persisted on disk, it will still be tagged when the server restarts. In fact, in that case tracing output will be generated at startup when the server places the message in the appropriate queue or subscription.)

Note:

If tracing is not enabled:
  • Attempting to tag a message results in an exception. (The code to recognize JMS_OC4J_TraceMe doesn't exist when the feature is disabled, so JMS_OC4J_TraceMe is considered an invalid message property, just as any random JMS property name such as JMSasdf would be.

  • Messages tagged when tracing was enabled remain tagged. Tracing of such messages can be resumed by restarting the JVM with tracing enabled.

Recommended Practices

Message tracing is intended to be a very targeted tool. Instead of turning some logger to FINEST and getting drowned in output, you tag a single message and get complete information about what happens to that one message. Because of this intended use, including message IDs in the output was not a high priority and message IDs are currently not included in the trace output.

Note that it is still possible for there to be a lot of output. When a traced message is sent to a topic, one "message reference" is created for each subscription that is to receive the message. (I.e., the subscriptions all share the message, and each subscription has its own reference to the shared message.) Each message reference (or "message ref" as they are referred to in the trace output) is traced. So if you have a lot of subscriptions, there can be a lot of output.

To avoid confusion:

  • Only tag one message.

  • Complete your test run (possibly including server restarts if testing persistence/recovery scenarios).

  • Once done, delete the jms.dat file to make sure a traced message from the last test run does not accidentally get into the next test run.

Tagging multiple messages works (and may be useful in some cases), but the output may be a bit confusing.

Consuming a tagged message gets rid of it just like any other message, so deleting the jms.dat file between runs is not strictly necessary. But again, things may get confusing if your application has an error that unexpectedly leaves a tagged message behind.

Traced Scenarios

The following scenarios are traced:

  • message operations involving the tagged message - examples include:

    • the message is sent from server to client or vice-versa

    • the message goes to/from disk

    • the message is given to a transaction, queue broker, or subscription

    • the message is locked (due to a receive) or unlocked (due to a rollback or recover)

    • the message is deleted (from disk or from memory)

    • the message expires

    • the message is destroyed when its queue/subscription is destroyed

    • a transaction (explicit or implicit) containing the message is acknowledged/prepared/committed/recovered/rolled-back

  • near misses:

    • if a subscription, queue receiver or queue browser would get the message except for message selector considerations

    • if a subscription would get the message except for noLocal considerations

The following scenarios are not traced:

  • low-level protocol violations: These result in the immediate closing of the TCP connection (and all JMS connections on it). The user can set oracle.j2ee.jms.v1.unsupportedOptions.protocolDebug to true for the server's JVM to get output about these events.

  • exception cases: When the JMS provider throws JMSException (or XAException, etc.), ideally the application should not be eating the exception, and the application developer would notice the exception. However applications have bugs (thus the point of the tracing feature), so it would be nice if we had some way to trace all of these. For the time being the user can use oracle.j2ee.jms.v1.unsupportedOptions.debug to see exceptions in send/receive/XA-method cases, but a number of methods (for example, Session.commit) do not output anything at this time. Note that oracle.j2ee.jms.v1.unsupportedOptions.debug is extremely verbose and, unlike message tracing, is not targeted.

  • complete misses:

    • If you attempt to receive the message using a stopped connection, the attempted receive will not be traced.

    • If you send a tagged message on one destination and try to receive it on another, the attempted receive will not be traced.

    • If you attempt to receive the message from the wrong OC4J JMS server, the attempted receive will not be traced.

Trace Output Conventions

Connections are identified as: <connection-id>

Sessions are identified as: <connection-id>:<session-id>

Session children (such as consumers and browsers) are identified as: <connection-id>:<session-id>:<child-id>

That convention (sometimes, see below) makes it easy to see to what session a consumer/browser belongs and to what connection a session belongs.Currently remote sessions do not have an ID that is common to both the server and the remote client (that is, a useful ID), so it is left blank. In that case session children are identified as: <connection-id>::<child-id>

The IDs of remote session children are only unique at a given instant in time and are not unique over time if session children are closed and created. For example, if a consumer is closed and a browser is later created, the ID the consumer had may be reused for the browser.

Also, local sessions and session children do not have a "nice" ID assigned to them, and instead their Object.hashCode() (which is never guaranteed to be unique) is used for their respective parts of an ID.