5 Understanding Message Consumption

This chapter describes how to configure the JMS RAs ra.xml file to configure MDBs to asynchronously consume WebLogic JMS messages in a foreign application server as inbound messages.

Configuring MDBs to Consume Inbound Messages

Applications which require MDBs to asynchronously consumes messages from a WebLogic destination use the JMS RAs inbound implementation. The behavior of the MDBs is determined by configuring property values in the following files before deploying your application:

Configuring inbound-resourceadapter Properties in the ra.xml File

The following sections provide information on how to define inbound-resourceadapter properties for the inbound configuration in the ra.xml file:

Required activation-config Properties

The required inbound-resourceadapter properties are specified in the WebLogic JMS Resource-Adapter's ra.xml file located in your WebLogic Server distribution, see Location of the JMS RA in the WebLogic Server Distribution.

Required JMS properties include:

  • ConnectionFactory

  • destination

  • destinationType

The values for ConnectionFactory, destination, and destinationType are defined as activation-config properties in the ejb-jar.xml file. The JNDI names configured in the ejb-jar.xml must also map to the JNDI names assigned to the JMS RA values of the connection-definition and adminobject elements. See:

Optional activation-config Properties

The JMS RA supports a number of additional activation-config properties. For more information, see Configuring activation-config Properties in the ejb-jar.xml File and JMS RA Inbound Properties.

Example inbound-resourceadapter Configuration

The following code example shows an inbound-resourceadapter configuration.

Example 5-1 Example inbound-resourceadapter Configuration

. . .
<inbound-resourceadapter>
      <messageadapter>
        <messagelistener>
          <messagelistener-type>
            javax.jms.MessageListener
          </messagelistener-type>
          <activationspec>
            <activationspec-class>
              weblogic.jms.ra.ActivationSpecImpl
            </activationspec-class>
            <required-config-property>
              <config-property-name>ConnectionFactory</config-property-name>
            </required-config-property>
            <required-config-property>
              <config-property-name>Destination</config-property-name>
            </required-config-property>
            <required-config-property>
              <config-property-name>DestinationType</config-property-name>
            </required-config-property>
          </activationspec>
        </messagelistener>
      </messageadapter>
</inbound-resourceadapter>
. . .

Configuring activation-config Properties in the ejb-jar.xml File

The following sections provide information on how to configure activation-config properties in the ejb-jar.xml file:

The ejb-jar.xml file and Annotations

For elements in ejb-jar.xml, see the schema at http://java.sun.com/xml/ns/javaee/ejb-jar_3_0.xsd.

The ejb-jar.xml is optional starting from EJB 3.0. Annotations can be used to declare metadata in place of descriptor elements. See "Using EJB 3.1 Compliant MDBs" in Developing Message-Driven Beans for Oracle WebLogic Server.

Configuring Required activation-config Properties in the ejb-jar.xml File

You must configure an activation-config-property property for every required-config-property property in the inbound-resourceadapter of the ra.xml.

Typical required JMS properties include:

  • ConnectionFactory: The JNDI location of a JMS Connector connection factory.

  • destination: The JNDI location of a JMS Connector destination.

  • destinationType where the type is one of the following:

    • javax.jms.Topic

    • javax.jms.Queue

    • javax.jms.Destination

In addition, If your MDB application utilizes optional activation-config properties, the foreign application server may require these optional activation-config properties be defined in ra.xml as required-config-property elements. Please refer to documentation provided by the vendor of your application server.

Example Queue Configuration

The following example shows activation-config properties for a queue configuration. In this example, the MDB that dequeues messages from a queue with the JNDI name wljmsra/queue using a connection from the connection factory with the JNDI name wljmsra/xacf.

. . .
<activation-config-property>
  <activation-config-property-name>
    ConnectionFactory
  </activation-config-property-name>
  <activation-config-property-value>
    wljmsra/xacf
  </activation-config-property-value>
</activation-config-property>
<activation-config-property>
  <activation-config-property-name>
    Destination
  </activation-config-property-name>
  <activation-config-property-value>
    wljmsra/queue
  </activation-config-property-value>
</activation-config-property>
<activation-config-property>
  <activation-config-property-name>
    DestinationType
  </activation-config-property-name>
  <activation-config-property-value>
    javax.jms.Queue
  </activation-config-property-value>
</activation-config-property>
. . .
Example Topic Configuration

The following example shows activation-config properties for a topic configuration. In this example, the MDB that dequeues messages from a topic with the JNDI name wljmsra/pdtopic1 using a connection from the connection factory with the JNDI name wljmsra/txacf1.

. . .
<activation-config-property>
  <activation-config-property-name>
    ConnectionFactory
  </activation-config-property-name>
  <activation-config-property-value>
    wljmsra/txacf1
  </activation-config-property-value>
</activation-config-property>
<activation-config-property>
  <activation-config-property-name>
    Destination
  </activation-config-property-name>
  <activation-config-property-value>
    wljmsra/pdtopic1
  </activation-config-property-value>
</activation-config-property>
<activation-config-property>
  <activation-config-property-name>
    DestinationType
  </activation-config-property-name>
  <activation-config-property-value>
    javax.jms.Topic
  </activation-config-property-value>
</activation-config-property>
. . .

Configuring Optional activation-config Properties in the ejb-jar.xml File

Configure any additional properties needed to achieve the appropriate MDB behavior for your environment. See JMS RA Inbound Properties.

Example ejb-jar.xml File with JMS RA activation-config Properties

The following example shows an ejb-jar.xml file with JMS RA activation-config properties.

Example 5-2 ejb-jar.xml file with JMS RA activation-config Properties

<?xml version="1.0" encoding="UTF-8"?>
<ejb-jar xmlns="http://java.sun.com/xml/ns/javaee">
    <display-name>WebLogic RA Demo</display-name>
    <enterprise-beans>
        <message-driven>
            <display-name>My queue MDB</display-name>
            <ejb-name>queueMDB</ejb-name>
            <ejb-class>jms.ra.DisQueueMDB</ejb-class>
            <messaging-type>javax.jms.MessageListener</messaging-type>
            <transaction-type>Container</transaction-type>
            <activation-config>
                <activation-config-property>
                    <activation-config-property-name>
                            ConnectionFactory
                    </activation-config-property-name>
                    <activation-config-property-value>
                            java:sample/factory
                    </activation-config-property-value>
                </activation-config-property>
                <activation-config-property>
                    <activation-config-property-name>
                            Destination
                    </activation-config-property-name>
                    <activation-config-property-value>
                            java:sample/destination/queue
                    </activation-config-property-value>
                </activation-config-property>
                <activation-config-property>
                    <activation-config-property-name>
                            DestinationType
                    </activation-config-property-name>
                    <activation-config-property-value>
                            javax.jms.Queue
                    </activation-config-property-value>
                </activation-config-property>
                <activation-config-property>
                    <activation-config-property-name>UserName</activation-config-property-name>
                    <activation-config-property-value></activation-config-property-value>                </activation-config-property>
                <activation-config-property>
                    <activation-config-property-name>Password</activation-config-property-name>
                    <activation-config-property-value></activation-config-property-value>
                </activation-config-property>
                <activation-config-property>
                    <activation-config-property-name>ClientId</activation-config-property-name>
                    <activation-config-property-value>queueMDB</activation-config-property-value>
                </activation-config-property>
                <activation-config-property>
                    <activation-config-property-name>MessageSelector</activation-config-property-name>
                    <activation-config-property-value></activation-config-property-value>
                </activation-config-property>
            </activation-config>
        </message-driven>
       . . .           
      </message-driven>
    </enterprise-beans>
   . . .
</ejb-jar>

For additional ejb-xml.jar file examples, review the Resource Adapter example in your WebLogic Server distribution.

Thread Management

The JMS RA provides three properties to manage the threads in destinations used by MDBs consuming inbound messages.

  • minListenerThreads: The minimum number of listener threads created for an individual physical destination. See minListenerThreads.

  • maxTotalListenerThreads: The maximum number of listener threads available for a destination. See maxTotalListenerThreads.

  • maxListenerThreads: The maximum number of listener threads created for an individual physical destination within a destination. See maxListenerThreads.

Setting the Maximum Threads for a Physical Destination

This section provides information on how to configure the maximum number of threads (maxListenerThreads) for a destination:

  • Queues: Using more than one thread may be useful in increasing the rate at which messages are consumed.

  • Topics: This value should always be 1. Each listener thread gets its own session and TopicSubscriber.

    • Durable subscribers: It is an error to have more than one subscriber with the same subscription name.

    • Nondurable subscribers: This value should always be 1. Creating more threads creates more subscribers which translates into more copies of each message to process.

Setting the Maximum Threads for a Distributed Destination

The maxTotalListenerThreads property allows you to limit or to provide addition processing threads for a distributed destination.

  • If the value of maxTotalListenerThreads is less than the number of physical destinations in the associated distributed destination, the JMS RA uses a value equal to the number of physical destinations in the distributed destination and logs a warning message.

  • If the Foreign application server cannot provide threads equal to or more than the number of physical destinations in the distributed destination, the JMS RA logs a warning message.

  • The JMS RA implements a fairness policy for allocating threads whereby any individual physical destination which currently being serviced by less than maxListenerThreads and needs more threads can reallocate threads from any other physical destination in the same distributed destination which has at least 2 more threads that it does. This fairness policy is independent of the foreign application server's WorkManager which may not grant the JMS RA's requests for additional maxTotalListenerThreads new threads.

    The process of reallocating threads from one destination to another takes some time, as both the determination of the thread deficiency and the transfer of the existing thread only take place between the processing of messages (between calls to onMessage). Since two threads are involved, the transfer process take up to two onMessage processing times.

Using an Exception Queue

The JMS RA allows users to configure an exception queue for inbound communications to handle poison messages from the inbound MDB queue. When UseExceptionQueue=true, messages that would otherwise be discarded are sent to the exception queue. Messages are normally sent to an exception queue when the maxDeliveryCount value is exceeded. See maxDeliveryCount.

Messages are processed to the exception queue using the following rules:

  • Messages are not set directly to the exception queue.

  • A new message of the same type is created.

    • The properties and body from the original message are copied to the new message.

      To prevent the original headers from being overwritten by the resource provider, each is copied to a GJRA_CopyOfJMS{Header} property. As javax.jms.Destination is not a valid property type, each destination header is translated into a descriptive message. Note: JMSX* properties are not converted. For example, JMSXDeliveryCount.

      Note:

      If any part of the copy process fails, processing continue with the next rule. For Bytes/Map/Stream message types, this may result in part of the message body is copied and part of the message body is not.

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

    • A string property called GJRA_DeliveryFailureReason is added which contains the description of why the message was not delivered.

    • If the MDB onMessage method generated an exception immediately prior to the delivery failure, a string property called GJRA_onMessageExceptions is added which contains the exception information.

  • The copy of the original message is sent to the exception queue.

    Note:

    Only one attempt is made to send the copy of the original message to the exception queue. If this attempt fails, the message is discarded without being placed in the exception queue. See includeBodiesInExceptionQueue for more information.

The connection factory used for the primary destination is also used for the exception queue. If the primary destination (specified by the Destination property) is a topic, then the connection factory must support both queues and topics. For example, the <connectionfactory-interface> element must be either javax.jms.ConnectionFactory or javax.jms.XAConnectionFactory.

Setting userName/password

The userName/password properties allow you to pass authentication parameters to the resource provider. When neither of these properties are set, connections used for the MDB's inbound message handling are created using the no-argument version of the createConnection method. When one or both are set, the userName/password properties are passed to the createConnection method as the user/password arguments. If only one of the properties is not set, null is used to replace that property value in the createConnection argument list.)

Configuring Advanced WebLogic JMS Resources

The following sections provide information on how to configure advanced message processing for inbound messages:

The JMS RA and Sharable Subscriptions

The JMS RA uses a SHARABLE Subscription Sharing Policy and UNRESTRICTED Client ID Policy when processing inbound messages, overriding any configured connection factory settings. A subscriptionName must be provided for durable subscriptions as the JMS RA's MDBs do not generate subscription names. Subscriptions are shared when:

  • Non-durable: Consumers on the same distributed topic can share a non-durable subscriptions only if they have the same clientID and messageSelector.

  • Durable: Consumers on the same distributed topic can share a durable subscriptions only they have the same clientID, message selector, and subscriptionName.

Always configure a clientId to ensure the MDB consumes incoming messages. For example:

. . .
<activation-config>
  <activation-config-property>
    
<activation-config-property-name>clientId</activation-config-property-name>
    <activation-config-property-value>myMDB</activation-config-property-value>
  </activation-config-property>
</activation-config> 
. . .

See "Configure Shared Subscriptions" in Administering JMS Resources for Oracle WebLogic Server.

Using Ordered Message Processing

If your application requires single-threaded processing of subscription messaging, configure your application to use WebLogic JMS Unit-of-Ordering (UOO) processing. See "Using Message Unit-of-Order" in Developing JMS Applications for Oracle WebLogic Server.

Design Strategies when Consuming from DistributedTopics

The following sections provide information on design strategies that can be used to develop high availability applications using distributed topics:

Replicated vs Partitioned Distributed Topics

This section provides an overview of replicated and partitioned distributed topics, both are supported for inbound message consumption.

  • Replicated Distributed Topics: All physical topic members receive each message sent. When a message arrives at one of the physical topic members, a copy of the message is automatically internally forwarded to the other members of the topic.

  • Partitioned Distributed Topics: The distributed topic member receiving the message is the only member that is aware of the message. The message is not forwarded to other members, and subscribers on other members do not get a copy of the message. Incoming messages can be load balanced among the distributed topic members using the JMS Affinity and Load Balance attributes. See "Load Balancing Partitioned Distributed Topics" in Administering JMS Resources for Oracle WebLogic Server.

One-Copy-Per-Application Design Strategy for Distributed Topics

One-Copy-Per-Application is the default design pattern available and has the following characteristics:

  • Each application as a whole (that is all instances of the application together) receives one copy of each message that is published to the DT. That is each instance only receives a subset of the messages that are sent to the DT.

  • An UNRESTRICTED Client ID Policy

  • An SHARABLE Subscription Sharing Policy

  • Uses the same subscription name if the subscribers are durable

  • All consumers subscribe to the same topic instance (or member of a DT)

Implementing One-Copy-Per-Application

To implement the One-Copy-Per-Application design strategy, you must specify the ProviderProperties property in your EJB with a value of TopicMessageDistributionMode=One-Copy-Per-Application in the activation-config element as shown in Example One-Copy-Per-Application EJB Configuration.

Note:

If you do not specify TopicMessageDistributionMode=One-Copy-Per-Server , the JMS RA defaults to TopicMessageDistributionMode=One-Copy-Per-Application to avoid message duplication.

Example One-Copy-Per-Application EJB Configuration

The following code snippet from an ejb-jar.xml file implements One-Copy-Per-Application message processing:

. . .
<mdb-resource-adapter>
  <resource-adapter-mid>wljmsra</resource-adapter-mid>
    <activation-config>
      <activation-config-property>
        <activation-config-property-name>ClientId</activation-config-property-name>
        <activation-config-property-value>RDT2MDB</activation-config-property-value>
      </activation-config-property>
      <activation-config-property>
        <activation-config-property-name>ProviderProperties</activation-config-property-name>
        <activation-config-property-value>TopicMessageDistributionMode=One-Copy-Per-Application</activation-config-property-value>
      </activation-config-property>
    </activation-config>
</mdb-resource-adapter>
 
<!-- Mapping a Queue admin-object to the Resource-Adapter name -->
  <resource-env-ref>
    <resource-env-ref-name>jms/ResultTopic</resource-env-ref-name>
    <jndi-name>wljmsra/rtopic1</jndi-name>
  </resource-env-ref>
 
<!-- Mapping a Connection Factory to the Resource-Adapter name -->
  <resource-ref>
    <res-ref-name>jms/ResultXACFFactory</res-ref-name>
    <jndi-name>wljmsra/xacf</jndi-name>
  </resource-ref>
. . .

One-Copy-Per-Server Design Strategy for Distributed Topics

One-Copy-Per-Server is a design pattern where each instance of an application gets one copy of each message that is published to the Topic.

Implementing One-Copy-Per-Server

To implement the One-Copy-Per-Server design strategy, you must:

  • Specify the weblogic.jms.ra.providers.wl.ServerID property when starting the foreign server instance. For example: -Dweblogic.jms.ra.providers.wl.ServerID=aUniqueIdForTheServer

    where aUniqueIdForTheServer is a unique identifyier for your foreign server.

    For Oracle Glassfish, you can configure this property using the asadmin command:

    asadmin> create-jvm-options --user myUsername --password myPassword --host localhost --port 4848 -Dweblogic.jms.ra.providers.wl.ServerID="aUniqueIdForTheServer"

  • Specify the ProviderProperties property in your EJB with a value of TopicMessageDistributionMode=One-Copy-Per-Server in the activation-config element as shown in Example One-Copy-Per-Application EJB Configuration.

Example One-Copy-Per-Server

The following code snippet from an ejb-jar.xml file implements One-Copy-Per-Server message processing:

. . .
<mdb-resource-adapter>
  <resource-adapter-mid>wljmsra</resource-adapter-mid>
    <activation-config>
      <activation-config-property>
        <activation-config-property-name>ClientId</activation-config-property-name>
        <activation-config-property-value>RDTMDB</activation-config-property-value>
      </activation-config-property>
      <activation-config-property>
        <activation-config-property-name>ProviderProperties</activation-config-property-name>
        <activation-config-property-value>TopicMessageDistributionMode=One-Copy-Per-Server</activation-config-property-value>
      </activation-config-property>
    </activation-config>
</mdb-resource-adapter>
<!-- Mapping a Queue admin-object to the Resource-Adapter name -->
  <resource-env-ref>
    <resource-env-ref-name>jms/ResultTopic</resource-env-ref-name>
    <jndi-name>wljmsra/rtopic1</jndi-name>
  </resource-env-ref>
<!-- Mapping a Connection Factory to the Resource-Adapter name -->
  <resource-ref>
    <res-ref-name>jms/ResultXACFFactory</res-ref-name>
    <jndi-name>wljmsra/xacf</jndi-name>
  </resource-ref>
. . .

Consuming from Stand-alone (Non-distributed) Topics

On each foreign application server instance that hosts the MDB application, an MDB pool is created for the topic, whether the topic is running in the same cluster or in a different cluster. For an MDB cluster of N nodes, N MDB pools are created. Each MDB pool creates an individual subscription on the topic, and subscribers from different MDB pools do not share the same subscription. See Implementing One-Copy-Per-Server.

Best Practices for Inbound Communication

This section provides information on tuning and best practices for JMS RA for inbound communication:

  • Ensure that the JMS RA allocates more threads than distributed destination members.

  • Always configure a clientID when using topics. The JMS RA uses a SHARABLE Subscription Sharing Policy when processing inbound messages which requires a configured clientId for either durable or non-durable subscribers.

    If no clientID is set, the MDB will not receive the message and the error condition logged in the foreign application server log. See The JMS RA and Sharable Subscriptions.

  • For queues, increasing the value of maxListenerThreads to more than one thread may increase the rate at which messages are consumed.

  • The JMS RA does not support sharable connections. If you use the <resource-ref> element in your application's JEE descriptors (web.xml, ejb-jar.xml) to identify the JMS Connection Factories that are looked up and used in that application, you must set the <res-sharing-scope> child-element to unsharable. The default value for this element is sharable. For example:

    . . .
    <resource-ref>
       <res-ref-name>jms/ReplyFactory</res-ref-name>
       <res-type>javax.jms.ConnectionFactory</res-type>
       <res-auth>Application</res-auth>
       <res-sharing-scope>unsharable</res-sharing-scope>
    </resource-ref>
    

    If your application uses @Resource injection, see http://docs.oracle.com/javaee/6/api/javax/annotation/Resource.html#shareable%28%29