<?xml version="1.0" encoding="UTF-8"?>
<section version="5.0" xml:lang="en" xmlns="http://docbook.org/ns/docbook"
         xmlns:xlink="http://www.w3.org/1999/xlink"
         xmlns:xi="http://www.w3.org/2001/XInclude"
         xmlns:svg="http://www.w3.org/2000/svg"
         xmlns:mml="http://www.w3.org/1998/Math/MathML"
         xmlns:html="http://www.w3.org/1999/xhtml"
         xmlns:db="http://docbook.org/ns/docbook">
  <info>
    <title>JMS cluster with JORAM</title>
  </info>
  <section xml:id="configure.jms.intro"><info><title>Introduction</title></info>

    <section><info><title>Generalities about Clustering JMS</title></info>

      <para>
        The JMS API provides a separate domain for each messaging approach, point-to-point or publish/subscribe.
        The point-to-point domain is built around the concept of queues, senders and receivers.
        The publish/subscribe domain is built around the concept of topic, publisher and subscriber.
        Additionally it provides a unified domain with common interfaces that enable the use of queue and topic.
        This domain defines the concept of producers and consumers.
        The classic sample provided with JOnAS ($JONAS_ROOT/examples/javaee5-earsample) uses a very simple configuration (centralized)
        made of one server hosting a queue and/or a topic.
        The server is administratively configured for accepting connection requests from the anonymous user.
      </para>
      <para>
        JMS clustering aims to offer a solution for both the scalability and the high availability for the JMS accesses.
        This chapter gives an overview of the JORAM capabilities for clustering a JMS application in
        the  <xi:include href="../../variables.xml" xpointer="element(j2ee)" /> context.
        The load-balancing and fail-over mechanisms are described and a user guide describing how to build such a configuration is provided.
        Further information is available in the JORAM documentation
        <link xlink:href="http://joram.ow2.org/doc/index.html">
          here
        </link>
        .
      </para>
    </section>
    <section><info><title>Objectives</title></info>

      <para>
        The following information will be presented:
      </para>
      <itemizedlist>
        <listitem><para>
          first, section <xref linkend="configure.jms.example" /> presents the example that will be used in this section about JMS cluster.
        </para></listitem>
        <listitem><para>
          then, <xref linkend="configure.jms.lb" /> details load balancing throw cluster topic and cluster queue.
          The distributed capabilities of JORAM will be detailed as well.
        </para></listitem>
        <listitem><para>
          <xref linkend="configure.jms.ha" /> describes how to configure the JORAM HA enabling to ensure the high availability of the JORAM server.
        </para></listitem>
        <listitem><para>
          <xref linkend="configure.jms.mdbcluster" /> introduces how to build an MDB clustering architecture
          with both JOnAS and JORAM.
        </para></listitem>
      </itemizedlist>
    </section>
  </section>

  <section xml:id="configure.jms.example"><info><title>Example</title></info>

      <para>
        The documentation provides an example of JMS cluster with 2 members and a MDB application.
      </para>

      <section><info><title>Getting started</title></info>
        <para>
          Install and configure two JOnAS instances (see
          <link xlink:href="http://jonas.ow2.org/current/doc/doc-en/integrated/getting_started_guide.html">
            here
          </link>
          ). The newjc tool may be used for generating the initial configuration of the JMS cluster.
          The tool may be run with the default inputs except for the architecture (bothWebEjb) and number of nodes (2).
          Refer to <xref linkend="commands.newjc" /> for further information about the newjc tool.
        </para>
      </section>
      <section><info><title>MDB application</title></info>

        <para>
          The MDB application is based on an example from the EasyBeans project. You can download the full source code of the application in the
          <link xlink:href="http://jonas.ow2.org/current/doc/doc-en/integrated/getting_started_guide.html">
            EasyBeans
          </link>
          project under the <literal>example/messagedrivenbean</literal> directory.
          A user guide for compiling the example is given
          <link xlink:href="http://www.easybeans.org/doc/userguide/en/integrated/userguide.html#using_examples">
            here
          </link>
        </para>
        <para>

          By default, The <literal>messagedrivenbean</literal> is bound to a JMS Queue and later in the documentation we
          will see how to change it for using a Topic instead. The implementation is :
          <screen>
package org.ow2.easybeans.examples.messagedrivenbean;

import javax.ejb.ActivationConfigProperty;
import javax.ejb.MessageDriven;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageListener;
import javax.jms.TextMessage;

@MessageDriven(activationConfig = {
        @ActivationConfigProperty(propertyName = "destination", propertyValue = "SampleQueue"),
        @ActivationConfigProperty(propertyName = "destinationType", propertyValue = "javax.jms.Queue")
        }
)
public class MessageDrivenBean implements MessageListener {

    public void onMessage(final Message message) {
        String txt = "Receiving a message named '" + message + "'.";
        if (message instanceof TextMessage) {
            try {
                txt += " with the content '" + ((TextMessage) message).getText();
            } catch (JMSException e) {
                e.printStackTrace();
            }
        }
        System.out.println(txt);
    }

}
          </screen>
        </para>
      </section>
      <section><info><title>Client application for a Queue destination</title></info>
       <para>
          Here the client application is extracted from the EasyBeans project as well.
          The <literal>client</literal> code sends a few messages towards the JMS object. The code is:
          <screen>
package org.ow2.easybeans.examples.messagedrivenbean;

import java.util.Hashtable;

import javax.jms.Queue;
import javax.jms.QueueConnection;
import javax.jms.QueueConnectionFactory;
import javax.jms.QueueSender;
import javax.jms.QueueSession;
import javax.jms.Session;
import javax.jms.TextMessage;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;

public final class ClientMessageDriven {

    private static final String QUEUE_CONNECTION_FACTORY = "JQCF";
    private static final String SAMPLE_QUEUE = "SampleQueue";
    private static final int NUMBER_MESSAGES = 5;
    private static final String
            DEFAULT_INITIAL_CONTEXT_FACTORY = "org.objectweb.carol.jndi.spi.MultiOrbInitialContextFactory";

    private ClientMessageDriven() {

    }

    public static void main(final String[] args) throws Exception {

        Context initialContext = getInitialContext();

        QueueConnectionFactory queueConnectionFactory = (QueueConnectionFactory) initialContext
                .lookup(QUEUE_CONNECTION_FACTORY);

        // Lookup the Queue through its JNDI name
        Queue queue = (Queue) initialContext.lookup(SAMPLE_QUEUE);

        // Create connection
        QueueConnection queueConnection = queueConnectionFactory.createQueueConnection();

        // Create session
        QueueSession queueSession = queueConnection.createQueueSession(false, Session.AUTO_ACKNOWLEDGE);

        // Create sender
        QueueSender queueSender = queueSession.createSender(queue);

        // Send messages
        TextMessage message = null;
        for (int i = 0; i &lt; NUMBER_MESSAGES; i++) {
            message = queueSession.createTextMessage();
            String text = "Message_" + i;
            message.setText(text);
            queueSender.send(message);
            System.out.println("Message [" + message.getJMSMessageID() + ", text:" + text + "] sent");

        }

        // Close JMS objects
        queueSender.close();
        queueSession.close();
        queueConnection.close();

    }

    private static Context getInitialContext() throws NamingException {

        Hashtable&lt;String, Object&gt; env = new Hashtable&lt;String, Object&gt;();
        env.put(Context.INITIAL_CONTEXT_FACTORY, DEFAULT_INITIAL_CONTEXT_FACTORY);
        return new InitialContext(env);
    }
}
          </screen>
        </para>
      </section>
     <section><info><title>Client application for a topic destination</title></info>
       <para>
          In this case, the client application must be adapted for publishing a message to a topic. Only the touched lines are shown:
          <screen>
...
import javax.jms.Topic;
import javax.jms.TopicConnection;
import javax.jms.TopicConnectionFactory;
import javax.jms.TopicPublisher;
import javax.jms.TopicSession;

...
    private static final String TOPIC_CONNECTION_FACTORY = "JTCF";
    private static final String SAMPLE_TOPIC = "sampleTopic";
...

        // Get factory
        TopicConnectionFactory topicConnectionFactory = (TopicConnectionFactory) initialContext
                .lookup(TOPIC_CONNECTION_FACTORY);

        // Lookup the Topic through its JNDI name
        Topic topic = (Topic) initialContext.lookup(SAMPLE_TOPIC);

        // Create connection
        TopicConnection topicConnection = topicConnectionFactory.createTopicConnection();

        // Create session
        TopicSession topicSession = topicConnection.createTopicSession(false, Session.AUTO_ACKNOWLEDGE);

        // Create publisher
        TopicPublisher topicPublisher = topicSession.createPublisher(topic);

        // Send messages
        TextMessage message = null;
        for (int i = 0; i &lt; NUMBER_MESSAGES; i++) {
            message = topicSession.createTextMessage();
            String text = "Message_" + i;
            message.setText(text);
            topicPublisher.publish(message);
            System.out.println("Message [" + message.getJMSMessageID() + ", text:" + text + "] sent");

        }

        // Close JMS objects
        topicPublisher.close();
        topicSession.close();
        topicConnection.close();

    }
...
          </screen>
        </para>
      </section>
      <section><info><title>Run the sample</title></info>
        <para>

      <itemizedlist>
        <listitem><para>
          For deploying the application, you can put the <literal>mdb.jar</literal> archive in the <literal>$JONAS_BASE/deploy</literal> directory.
        </para></listitem>
        <listitem><para>
          And then you can run the client with the jclient command and you get the following output:
          <screen>
jclient ./clients/client-mdb.jar
ClientContainer.info : Starting client...
Message [ID:0.0.1026c4m0, text:Message_0] sent
Message [ID:0.0.1026c4m1, text:Message_1] sent
Message [ID:0.0.1026c4m2, text:Message_2] sent
Message [ID:0.0.1026c4m3, text:Message_3] sent
Message [ID:0.0.1026c4m4, text:Message_4] sent
          </screen>
        </para></listitem>
        <listitem><para>
          At the server side, you get the following messages:
          <screen>
Receiving a message named '(org.objectweb.joram.client.jms.TextMessage@812517,JMSMessageID=ID:0.0.1026c4m1,
  JMSDestination=queue#0.0.1038,JMSCorrelationID=null,JMSDeliveryMode=2,JMSExpiration=0,JMSPriority=4,
  JMSRedelivered=false,JMSReplyTo=null,JMSTimestamp=1222962742969,JMSType=null)'. with the content 'Message_1
Receiving a message named '(org.objectweb.joram.client.jms.TextMessage@f42d53,JMSMessageID=ID:0.0.1026c4m3,
  JMSDestination=queue#0.0.1038,JMSCorrelationID=null,JMSDeliveryMode=2,JMSExpiration=0,JMSPriority=4,
  JMSRedelivered=false,JMSReplyTo=null,JMSTimestamp=1222962742978,JMSType=null)'. with the content 'Message_3
Receiving a message named '(org.objectweb.joram.client.jms.TextMessage@cbb612,JMSMessageID=ID:0.0.1026c4m2,
  JMSDestination=queue#0.0.1038,JMSCorrelationID=null,JMSDeliveryMode=2,JMSExpiration=0,JMSPriority=4,
  JMSRedelivered=false,JMSReplyTo=null,JMSTimestamp=1222962742977,JMSType=null)'. with the content 'Message_2
Receiving a message named '(org.objectweb.joram.client.jms.TextMessage@1e7f21,JMSMessageID=ID:0.0.1026c4m0,
  JMSDestination=queue#0.0.1038,JMSCorrelationID=null,JMSDeliveryMode=2,JMSExpiration=0,JMSPriority=4,
  JMSRedelivered=false,JMSReplyTo=null,JMSTimestamp=1222962742965,JMSType=null)'. with the content 'Message_0
Receiving a message named '(org.objectweb.joram.client.jms.TextMessage@2c79a5,JMSMessageID=ID:0.0.1026c4m4,
  JMSDestination=queue#0.0.1038,JMSCorrelationID=null,JMSDeliveryMode=2,JMSExpiration=0,JMSPriority=4,
  JMSRedelivered=false,JMSReplyTo=null,JMSTimestamp=1222962742979,JMSType=null)'. with the content 'Message_4
          </screen>
        </para></listitem>
      </itemizedlist>

        </para>
        <para>When using jclient container, the client will connect to the server which is pointed by $JONAS_BASE/conf/carol.properties. You can specify another
        one with the <literal>-carolFile</literal> option.
        </para>
          <screen>
jclient ./clients/client-mdb.jar -carolFile ./carol.properties
          </screen>
      </section>
  </section>
  <section xml:id="configure.jms.lb"><info><title>Load balancing</title></info>

    <section xml:id="toc_lb_joramcfg"><info><title>JORAM distributed configuration</title></info>

      <para>
        Two instances of JOnAS are configured ("J1" and "J2"). Each JOnAS instance has a dedicated collocated JORAM server:
        server     "S1" for JOnAS "J1", "S2" for "J2". These two servers are aware of each other.
      </para>
      <para>
        Set a JORAM distributed configuration:
      </para>
      <orderedlist>
        <listitem><para>
          Go to $JONAS_BASE/conf and edit the a3servers.xml file (same for the 2 instances).
          2 instances are defined in the same domain network. The persistent mode is enabled through the <literal>Transaction</literal>
          property in the <literal>a3servers.xml</literal> file and through the <literal>PersistentPlatform</literal> configuration property
          in the JORAM RA.
  <example>
     <title>JORAM distributed configuration</title>

          <screen>

&lt;?xml version="1.0"?&gt;
&lt;config
  &lt;domain name="D1"/&gt;
  &lt;property name="Transaction" value="fr.dyade.aaa.util.NTransaction"/&gt;
  &lt;server id="1" name="S1" hostname="localhost"&gt;
    &lt;network domain="D1" port="16301"/&gt;
    &lt;service class="org.objectweb.joram.mom.proxies.ConnectionManager"
             args="root root"/&gt;
    &lt;service class="org.objectweb.joram.mom.proxies.tcp.TcpProxyService"
             args="16010"/&gt;
  &lt;/server&gt;
  &lt;server id="2" name="S2" hostname="localhost"&gt;
    &lt;network domain="D1" port="16302"/&gt;
    &lt;service class="org.objectweb.joram.mom.proxies.ConnectionManager"
             args="root root"/&gt;
    &lt;service class="org.objectweb.joram.mom.proxies.tcp.TcpProxyService"
             args="16020"/&gt;
  &lt;/server&gt;
&lt;/config&gt;
                  </screen>
                  </example>
        </para></listitem>
        <listitem><para>
          For each instance, edit the ra.xml embedded in the joram_for_jonas_ra.rar (by using unjar command manually or with the jonasAdmin's RA editor) and check the following element according to the a3servers.xml content
          <itemizedlist>
            <listitem><para>
              server id (1 or 2)
              <screen>

      &lt;config-property&gt;
         &lt;config-property-name&gt;ServerId&lt;/config-property-name&gt;
         &lt;config-property-type&gt;java.lang.Short&lt;/config-property-type&gt;
         &lt;config-property-value&gt;1&lt;/config-property-value&gt;
      &lt;/config-property&gt;
                          </screen>
            </para></listitem>
            <listitem><para>
              server name (S1 or S2)
              <screen>

      &lt;config-property&gt;
         &lt;config-property-name&gt;ServerName&lt;/config-property-name&gt;
         &lt;config-property-type&gt;java.lang.String&lt;/config-property-type&gt;
         &lt;config-property-value&gt;s1&lt;/config-property-value&gt;
      &lt;/config-property&gt;
                          </screen>
            </para></listitem>
            <listitem><para>
              hostname
              <screen>

      &lt;config-property&gt;
         &lt;config-property-name&gt;HostName&lt;/config-property-name&gt;
         &lt;config-property-type&gt;java.lang.String&lt;/config-property-type&gt;
         &lt;config-property-value&gt;localhost&lt;/config-property-value&gt;
      &lt;/config-property&gt;
                          </screen>
            </para></listitem>
            <listitem><para>
              network port (16010 or 16020)
              <screen>

      &lt;config-property&gt;
         &lt;config-property-name&gt;ServerPort&lt;/config-property-name&gt;
         &lt;config-property-type&gt;java.lang.Integer&lt;/config-property-type&gt;
         &lt;config-property-value&gt;16010&lt;/config-property-value&gt;
      &lt;/config-property&gt;
                          </screen>
            </para></listitem>
            <listitem><para>
              persistent mode
              <screen>

      &lt;config-property&gt;
         &lt;config-property-name&gt;PersistentPlatform&lt;/config-property-name&gt;
         &lt;config-property-type&gt;java.lang.Boolean&lt;/config-property-type&gt;
         &lt;config-property-value&gt;true&lt;/config-property-value&gt;
      &lt;/config-property&gt;
                           </screen>
            </para></listitem>
          </itemizedlist>
        </para></listitem>
        <listitem><para>
          For each instance, edit the joramAdmin.xml, update the connection factories definition, the user definition according to the local JORAM server configuration
          <itemizedlist>
            <listitem><para>
              server id (1 or 2)
              <screen>

    &lt;User name="anonymous"
             password="anonymous"
             serverId="1"/&gt;
                          </screen>
            </para></listitem>
            <listitem><para>
              server port number (16010 or 16020)
              <screen>

    &lt;ConnectionFactory className="org.objectweb.joram.client.jms.tcp.TcpConnectionFactory"&gt;
       &lt;tcp host="localhost"
            port="16010"/&gt;
       &lt;jndi name="JCF"/&gt;
    &lt;/ConnectionFactory&gt;

    &lt;ConnectionFactory className="org.objectweb.joram.client.jms.tcp.QueueTcpConnectionFactory"&gt;
       &lt;tcp host="localhost"
            port="16010"/&gt;
       &lt;jndi name="JQCF"/&gt;
    &lt;/ConnectionFactory&gt;

    &lt;ConnectionFactory className="org.objectweb.joram.client.jms.tcp.TopicTcpConnectionFactory"&gt;
       &lt;tcp host="localhost"
            port="16010"/&gt;
       &lt;jndi name="JTCF"/&gt;
    &lt;/ConnectionFactory&gt;
                          </screen>
            </para></listitem>
          </itemizedlist>
        </para></listitem>
      </orderedlist>
      <para>
        See
        <link xlink:href="howto_distributed_joram.html">
          here
        </link>
         for more information about a JORAM distributed configuration.
      </para>
    </section>
    <section xml:id="toc_lb_topic_intro"><info><title>Clustered Topic</title></info>

      <para>
        A non hierarchical topic might be distributed among many servers.
        Such a topic, to be considered as a single logical topic, is made of topic representatives, one per server.
        Such an architecture allows a publisher to publish messages on a representative of the topic.
        In the example, the publisher works with the representative on server 1.
        If a subscriber subscribed to any other representative (on server 2 in the example), it will get the messages produced by the publisher.
      </para>
      <para>
        Load balancing of topics is very useful because it allows distributed topic subscriptions across the cluster.
      </para>
      <para>
        <mediaobject>
          <imageobject>
            <imagedata align="center"
                       fileref="../../../../resources/images/jmsclustering/topic.jpg"
                       width="70%" scalefit="1"/>
           </imageobject>
        </mediaobject>
      </para>
    </section>

      <para>
        The following scenario and general settings are proposed:
      </para>
      <itemizedlist>
        <listitem><para>
          The cluster topic is composed of two elements : mdbTopic1 defined hosted by JORAM server S1 and mdbTopic2 hosted by JORAM server S2.
        </para></listitem>
        <listitem><para>
          The jndi name 'mdbTopic' is set for the local representative, ie mdbTopic1 for S1 et mdbTopic2 for S2.
        </para></listitem>
        <listitem><para>
          At the server side, a MDB is listening the local representative 'mdbTopic'.
        </para></listitem>
        <listitem><para>
          A client connects to the J1 or J2 server and sends 10 messages to the topic 'mdbTopic'.
        </para></listitem>
        <listitem><para>
          Each message is received twice, one per cluster element.
        </para></listitem>
      </itemizedlist>
      <para>
        <mediaobject>
          <imageobject>
            <imagedata align="center"
                       fileref="../../../../resources/images/jmsclustering/JmsClustering-topics.jpg"
                       width="70%" scalefit="1"/>
           </imageobject>
        </mediaobject>

      </para>

      <section><info><title>Topic cluster definition in joramAdmin.xml</title></info>

        <para>
           The cluster definition with the topics must be added in $JONAS_BASE/conf/joramAdmin.xml file. The connection factories and the anonymous user must be defined with the local server id and the local server port number according to the a3servers.xml content. Here only the cluster related elements are shown:
        </para>
        <itemizedlist>
          <listitem><para>
            For the server id 1 :
  <example>
     <title>Cluster topic with JORAM</title>
            <screen>

  &lt;Topic name="mdbTopic1" serverId="1"&gt;
    &lt;freeReader/&gt;
    &lt;freeWriter/&gt;
    &lt;jndi name="mdbTopic"/&gt;
  &lt;/Topic&gt;

  &lt;Topic name="mdbTopic2" serverId="2"&gt;
    &lt;freeReader/&gt;
    &lt;freeWriter/&gt;
    &lt;jndi name="mdbTopic2"/&gt;
  &lt;/Topic&gt;

  &lt;ClusterTopic&gt;
      &lt;ClusterElement name="mdbTopic1" location="s1"/&gt;
      &lt;ClusterElement name="mdbTopic2" location="s2"/&gt;
      &lt;jndi name="clusterMdbTopic"/&gt;
  &lt;/ClusterTopic&gt;
              </screen></example>
          </para></listitem>
          <listitem><para>
            For the server id 2 :
            <screen>

  &lt;Topic name="mdbTopic1" serverId="1"&gt;
    &lt;freeReader/&gt;
    &lt;freeWriter/&gt;
    &lt;jndi name="mdbTopic1"/&gt;
  &lt;/Topic&gt;

  &lt;Topic name="mdbTopic2" serverId="2"&gt;
    &lt;freeReader/&gt;
    &lt;freeWriter/&gt;
    &lt;jndi name="mdbTopic"/&gt;
  &lt;/Topic&gt;

  &lt;ClusterTopic&gt;
    &lt;ClusterElement name="mdbTopic1" location="s1"/&gt;
    &lt;ClusterElement name="mdbTopic2" location="s2"/&gt;
    &lt;jndi name="clusterMdbTopic"/&gt;
  &lt;/ClusterTopic&gt;
             </screen>
          </para></listitem>
        </itemizedlist>
        <note>
          <para>
            The <emphasis>mdbTopic</emphasis> jndi name is bound in the local JOnAS registry with the local cluster element,
            i.e. <emphasis>mdbTopic1</emphasis> for server id 1 and <emphasis>mdbTopic2</emphasis> for server id 2.
          </para>
        </note>
        <note>
          <para>
            The joramAdmin.xml file has to be loaded when all cluster members are started since some remote cluster elements are defined.
            An alternative consists in splitting the configuration into two different files    joramAdmin-local.xml and joramAdmin-cluster.xml,
            the first one containing only the local elements and the    second one, both local and remote elements.
            At the JOnAS starting, a script could copy the right file    to joramAdmin.xml according to the others members presence (joramAdmin-local.xml
            if it's the first member    which starts and joramAdmin-cluster.xml if all the cluster members are started).
          </para>
        </note>

      </section>

      <section><info><title>Changes in the example</title></info>
        <para>The <literal>@MessageDriven</literal> annotation is updated in the source code for binding the MDB with the clustered topic. That could be done
        through the optional deployment descriptor as well.
        </para>
        <screen>
@MessageDriven(activationConfig = {
        @ActivationConfigProperty(propertyName ="destination", propertyValue ="mdbTopic"),
        @ActivationConfigProperty(propertyName ="destinationType", propertyValue ="javax.jms.Topic")
        }
)
        </screen>
        <para>The client code for sending a message to a Topic is used and the topic name is set to:
        </para>
        <screen>
    private static final String SAMPLE_TOPIC = "mdbTopic";
        </screen>
      </section>

      <section><info><title>Run the sample</title></info>

        <para>
          Deploy the MDB application in each JOnAS instance and run the sample.
          The messages do appear on the two different JOnAS servers consoles that shows the messages broadcasting between the topic elements.
        </para>
      </section>


    <section xml:id="toc_lb_queue_intro"><info><title>Load-balancing for Queue</title></info>

      <para>
        Globally, the load balancing in the context of queues may be meaningless in comparison of load balancing topic. It would be a bit like load balancing a stateful session bean instance (which just requires failover). But the JORAM distributed architecture enables :
      </para>
      <itemizedlist>
        <listitem><para>
          equilibrating the load of the queue access between several JORAM server nodes, it's a queue load-balancing at the server side.
        </para></listitem>
        <listitem><para>
          load-balancing the load at the client side.
        </para></listitem>
      </itemizedlist>
    </section>
    <section xml:id="toc_lb_queue_scenario1"><info><title>First scenario for Queue : distribution of the load at the server side</title></info>

      <para>
        Here is a diagram of what is going to happen for the Queue and the message:
      </para>
      <para>
        <mediaobject>
          <imageobject>
            <imagedata align="center"
                       fileref="../../../../resources/images/jmsclustering/queuelb.png"
                       width="60%" scalefit="1">
            </imagedata>
          </imageobject>
        </mediaobject>
      </para>
      <para>
        A load balancing message queue may be needed for a high rate of messages. A clustered queue is a cluster of queues exchanging messages depending on their load. The example has a cluster of two queues. A heavy producer accesses its local queue and sends messages. It quickly becomes loaded and decides to forward messages to the other queue of its cluster which is not under heavy load.
      </para>
      <para>
        For this case some parameters must be set:
      </para>
      <itemizedlist>
        <listitem><para>
          period: period (in ms) of activation of the load factor evaluation routine for a queue
        </para></listitem>
        <listitem><para>
          producThreshold: number of messages above which a queue is considered loaded, a load factor evaluation launched, messages forwarded to other queues of the cluster
        </para></listitem>
        <listitem><para>
          consumThreshold: number of pending "receive" requests above which a queue will request messages from the other queues of the cluster
        </para></listitem>
        <listitem><para>
          autoEvalThreshold: set to "true" for requesting an automatic revaluation of the queues' thresholds values according to their activity
        </para></listitem>
        <listitem><para>
          waitAfterClusterReq: time (in ms) during which a queue that requested something from the cluster is not authorized to do it again
        </para></listitem>
      </itemizedlist>
      <para>
        For further information, see the JORAM documentation
        <link xlink:href="http://joram.ow2.org/doc/index.html">
          here
        </link>
        .
      </para>
      <para>
        The scenario for Queue is similar to the topic one. A client sent messages to a queue in S1. MDB gets messages from each local cluster queue representative. After having sent a burst of messages to the server S1, the load distribution should occur and message should be moved to S2.
      </para>
      <para>
        The Queue definition in $JONAS_BASE/conf/joramAdmin.xml file is as following :
      </para>
      <itemizedlist>
        <listitem><para>
          For server 1
        </para>
  <example>
     <title>Cluster queue with JORAM</title>

        <screen>

&lt;Queue name="mdbQueue1"
          serverId="1"
          className="org.objectweb.joram.mom.dest.ClusterQueue"&gt;
  &lt;freeReader/&gt;
  &lt;freeWriter/&gt;
  &lt;property name="period" value="10000"/&gt;
  &lt;property name="producThreshold" value="50"/&gt;
  &lt;property name="consumThreshold" value="2"/&gt;
  &lt;property name="autoEvalThreshold" value="false"/&gt;
  &lt;property name="waitAfterClusterReq" value="1000"/&gt;
  &lt;jndi name="mdbQueue"/&gt;
&lt;/Queue&gt;

&lt;Queue name="mdbQueue2"
          serverId="2"
          className="org.objectweb.joram.mom.dest.ClusterQueue"&gt;
  &lt;freeReader/&gt;
  &lt;freeWriter/&gt;
  &lt;property name="period" value="10000"/&gt;
  &lt;property name="producThreshold" value="50"/&gt;
  &lt;property name="consumThreshold" value="2"/&gt;
  &lt;property name="autoEvalThreshold" value="false"/&gt;
  &lt;property name="waitAfterClusterReq" value="1000"/&gt;
  &lt;jndi name="mdbQueue2"/&gt;
&lt;/Queue&gt;

&lt;ClusterQueue&gt;
    &lt;ClusterElement name="mdbQueue1" location="s1"/&gt;
    &lt;ClusterElement name="mdbQueue2" location="s2"/&gt;
    &lt;jndi name="mdbQueueCluster"/&gt;
&lt;/ClusterQueue&gt;

        </screen></example></listitem>
        <listitem><para>
          For server 2
        </para>
        <screen>

&lt;Queue name="mdbQueue1"
          serverId="1"
          className="org.objectweb.joram.mom.dest.ClusterQueue"&gt;
  &lt;freeReader/&gt;
  &lt;freeWriter/&gt;
  &lt;property name="period" value="10000"/&gt;
  &lt;property name="producThreshold" value="50"/&gt;
  &lt;property name="consumThreshold" value="2"/&gt;
  &lt;property name="autoEvalThreshold" value="false"/&gt;
  &lt;property name="waitAfterClusterReq" value="1000"/&gt;
  &lt;jndi name="mdbQueue1"/&gt;
&lt;/Queue&gt;

&lt;Queue name="mdbQueue2"
          serverId="2"
          className="org.objectweb.joram.mom.dest.ClusterQueue"&gt;
  &lt;freeReader/&gt;
  &lt;freeWriter/&gt;
  &lt;property name="period" value="10000"/&gt;
  &lt;property name="producThreshold" value="50"/&gt;
  &lt;property name="consumThreshold" value="2"/&gt;
  &lt;property name="autoEvalThreshold" value="false"/&gt;
  &lt;property name="waitAfterClusterReq" value="1000"/&gt;
  &lt;jndi name="mdbQueue"/&gt;
&lt;/Queue&gt;

&lt;ClusterQueue&gt;
    &lt;ClusterElement name="mdbQueue1" location="s1"/&gt;
    &lt;ClusterElement name="mdbQueue2" location="s2"/&gt;
    &lt;jndi name="mdbQueueCluster"/&gt;
&lt;/ClusterQueue&gt;
        </screen></listitem>
      </itemizedlist>
        <note>
        <para>
          The joramAdmin.xml file has to be loaded when all cluster members are started since some remote
          cluster elements are defined. An alternative consists in splitting the configuration into two different files joramAdmin-local.xml
          and joramAdmin-cluster.xml, the first one containing only the local elements and the  second one,
          both local and remote elements. At the JOnAS starting, a script could copy the right file
          to joramAdmin.xml according to the others members presence (joramAdmin-local.xml if it's the first member
          which starts and joramAdmin-cluster.xml if all the cluster members are started).
        </para>
        </note>
    </section>

    <section><info><title>Changes in the example</title></info>
        <para>The <literal>@MessageDriven</literal> annotation is set with the <literal>mdbQueue</literal> queue. That could be done
        through the optional deployment descriptor as well.
        </para>
        <screen>
@MessageDriven(activationConfig = {
        @ActivationConfigProperty(propertyName ="destination", propertyValue ="mdbQueue"),
        @ActivationConfigProperty(propertyName ="destinationType", propertyValue ="javax.jms.Queue")
        }
)
        </screen>
        <para>The client code for the Queue is used and the queue name is set to:
        </para>
        <screen>
    private static final String SAMPLE_Queue = "mdbQueue";
        </screen>
        <para>The loop number can be increased in order to generate some pending messages in the first server:
        </para>
        <screen>
    private static final int NUMBER_MESSAGES = 1000;
        </screen>
      </section>
      <section><info><title>Run the sample</title></info>
         <para>
          Deploy the MDB application in each JOnAS instance and run the sample.
          The messages do appear on the two different JOnAS servers consoles that shows the load-balacing at the server side.
        </para>
     </section>

    <section xml:id="toc_lb_queue_scenario2"><info><title>Second scenario for Queue : load-balancing at the client side</title></info>

      <section><info><title>Principle</title></info>

        <para>
          The load-balancing is done at the client side. A server is selected randomly among the cluster members at the first message sending or through the 'location' java property. And then, for a given client, all the messages are sent to the same server unless the java property resetting.
        </para>
        <para>
        <mediaobject>
          <imageobject>
            <imagedata align="center"
                       fileref="../../../../resources/images/jmsclustering/JmsClustering-queues.jpg"
                       width="70%" scalefit="1">
            </imagedata>
          </imageobject>
        </mediaobject>

        </para>
        <para>
          For setting the load-balancing at the client side, the client application must use a clustered connection factory that embeds the network connection parameters of the cluster members. This factory must be registered in the JORAM's distributed JNDI for ensuring that the client gets an up to date object. The main parameters are given below :
        </para>
      </section>
      <section><info><title>Setting of the JORAM's distributed jndi</title></info>

        <para>
          At first, the a3servers.xml file must enhanced with the JORAM's jndi service as following :
        </para>
        <screen>

&lt;?xml version="1.0"?&gt;
&lt;config&gt;
  &lt;domain name="D1"/&gt;
  &lt;property name="Transaction" value="fr.dyade.aaa.util.NTransaction"/&gt;
  &lt;server id="1" name="s1" hostname="localhost"&gt;
    &lt;property name="location" value="s1" /&gt;
    &lt;network domain="D1" port="16301"/&gt;
    &lt;service class="org.objectweb.joram.mom.proxies.ConnectionManager"
             args="root root"/&gt;
    &lt;service class="org.objectweb.joram.mom.proxies.tcp.TcpProxyService"
             args="16010"/&gt;
    &lt;service class="fr.dyade.aaa.jndi2.distributed.DistributedJndiServer"
               args="16401 1 2"/&gt;
  &lt;/server&gt;

  &lt;server id="2" name="s2" hostname="localhost"&gt;
    &lt;property name="location" value="s2" /&gt;
     &lt;network domain="D1" port="16302"/&gt;
     &lt;service class="org.objectweb.joram.mom.proxies.ConnectionManager"
             args="root root"/&gt;
    &lt;service class="org.objectweb.joram.mom.proxies.tcp.TcpProxyService"
             args="16020"/&gt;
    &lt;service class="fr.dyade.aaa.jndi2.distributed.DistributedJndiServer"
               args="16402 2 1"/&gt;
  &lt;/server&gt;

&lt;/config&gt;
        </screen>
        <note>
          The <emphasis>location</emphasis> property is set for binding the MDB to the local queue instance.
        </note>
        <para>
          Only the JMS objects must be registered in the JORAM's jndi. The standard routing mechanism is used through a jndi.properties file put in each $JONAS_BASE/conf directory :
        </para>
        <itemizedlist>
          <listitem><para>
            port number (16401 or 16402)
          </para>
          <screen>

  java.naming.factory.url.pkgs    org.objectweb.jonas.naming:fr.dyade.aaa.jndi2
  scn.naming.factory.host         localhost
  scn.naming.factory.port         16402
           </screen></listitem>
        </itemizedlist>
        <para>
          The port number must be adapted according to the local server configuration (16401 for S1 and 16402 for S2). The 'scn' prefix is defined for identifying the objects to bind or to lookup in this registry.
        </para>
      </section>
      <section><info><title>Setting of the clustered connection factories</title></info>

        <para>
          The clustered connection factories are defined in the $JONAS_BASE/conf/joramAdmin.xml file as following :
        </para>
        <screen>

&lt;ConnectionFactory name="JQCF1" className="org.objectweb.joram.client.jms.tcp.QueueTcpConnectionFactory"&gt;
  &lt;tcp host="localhost"
       port="16010"/&gt;
  &lt;jndi name="scn:comp/JQCF1"/&gt;
&lt;/ConnectionFactory&gt;
&lt;ConnectionFactory name="JQCF2" className="org.objectweb.joram.client.jms.tcp.QueueTcpConnectionFactory"&gt;
  &lt;tcp host="localhost"
       port="16020"/&gt;
  &lt;jndi name="scn:comp/JQCF2"/&gt;
&lt;/ConnectionFactory&gt;
&lt;ClusterCF&gt;
    &lt;ClusterElement name="JQCF1" location="s1"/&gt;
    &lt;ClusterElement name="JQCF2" location="s2"/&gt;
    &lt;jndi name="scn:comp/clusterJQCF"/&gt;
&lt;/ClusterCF&gt;
        </screen>
        <para>
          The 'scn:comp/' prefix in the jndi name indicates that the object must be bound in the JORAM's jndi.
        </para>
      </section>
      <section><info><title>Cluster queue definition</title></info>

        <para>
          The cluster queue is defined in the $JONAS_BASE/conf/joramAdmin.xml file :
        </para>
        <screen>

&lt;Queue name="mdbQueue1" serverId="1"
       className="org.objectweb.joram.mom.dest.ClusterQueue"&gt;
   &lt;freeReader/&gt;
   &lt;freeWriter/&gt;
   &lt;jndi name="scn:comp/mdbQueue1"/&gt;
&lt;/Queue&gt;

&lt;Queue name="mdbQueue2" serverId="2"
       className="org.objectweb.joram.mom.dest.ClusterQueue"&gt;
   &lt;freeReader/&gt;
   &lt;freeWriter/&gt;
   &lt;jndi name="scn:comp/mdbQueue2"/&gt;
&lt;/Queue&gt;

&lt;ClusterQueue&gt;
   &lt;ClusterElement name="mdbQueue1" location="s1"/&gt;
   &lt;ClusterElement name="mdbQueue2" location="s2"/&gt;
   &lt;jndi name="scn:comp/mdbQueue"/&gt;
&lt;/ClusterQueue&gt;
        </screen>
        <note><para>
          The cluster queue definition is symetric across the cluster members.
          The well known jndi name is set on the cluster object (and not in the local representative as for the topic cluster).
        </para></note>
        <note><para>
          The joramAdmin.xml file has to be loaded when all cluster members
           are started since some remote cluster elements are defined.
            An alternative consists in splitting the configuration into two different files
            joramAdmin-local.xml and joramAdmin-cluster.xml, the first one containing only the local elements and the
             second one, both local and remote elements. At the JOnAS starting, a script could copy the right file
             to joramAdmin.xml according to the others members presence (joramAdmin-local.xml if it's the first member
             which starts and joramAdmin-cluster.xml if all the cluster members are started).

        </para></note>
      </section>
      <section><info><title>Changes in the example</title></info>

        <para>
          The message driven bean must be configured with the queue registered in the JORAM jndi ('scn:/comp' selector).
          The @MessageDriven annotation is set with the <literal>scn:/comp/mdbQueue</literal> queue.
          That could be done through the optional deployment descriptor as well.
        </para>
        <screen>
@MessageDriven(activationConfig = {
        @ActivationConfigProperty(propertyName ="destination", propertyValue ="scn:comp/mdbQueue"),
        @ActivationConfigProperty(propertyName ="destinationType", propertyValue ="javax.jms.Queue")
        }
)
        </screen>

        <para>
          The client must lookup the clustered objects in the JORAM's jndi by using the 'scn:/comp' selector.
          The client code for sending a message to a client is changed as following:
        </para>
        <screen>

private static final String QUEUE_CONNECTION_FACTORY = "scn:comp/clusterJQCF";
private static final String SAMPLE_QUEUE = "scn:comp/mdbQueue";

        </screen>
        <para>
          The connection creation, session creation and producer are created like this:
        </para>
        <screen>

        Queue queue = (Queue) initialContext.lookup(SAMPLE_QUEUE);
        Connection connection = ConnectionFactory.createConnection();
        Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
        MessageProducer messageProducer = session.createProducer(queue);
        </screen>
        <para>
          A server is chosen at the first message sending.
          A switch may be forced through the resetting of the 'location' java property. Below a new server election is requested for each odd iteration.
        </para>
        <screen>
        for (int i = 0; i &lt; NUMBER_MESSAGES; i++) {
            message = session.createTextMessage();
            String text = "Message_" + i;
            message.setText(text);
            messageProducer.send(message);
            System.out.println("Message [" + message.getJMSMessageID() + ", text:" + text + "] sent");
            System.out.println("location=" + System.getProperty("location"));
            if (i%2 == 0) {
              System.setProperty("location", "");
            }
        }
        messageProducer.close();
        session.close();
        connection.close();

        </screen>
      </section>
      <section><info><title>Run the sample</title></info>

        <para>
          Deploy the MDB application in each JOnAS instance and run the sample.
          The messages do appear on the two different JOnAS servers consoles that shows the messages load-balancing between the cluster elements.

        </para>
      </section>
    </section>
  </section>
  <section xml:id="configure.jms.ha"><info><title>JORAM HA and JOnAS</title></info>

    <section><info><title>Generality</title></info>

      <para>
        <mediaobject>
          <imageobject>
            <imagedata align="center"
                       fileref="../../../../resources/images/jmsclustering/joram_ha.jpg"
                       width="70%" scalefit="1">
            </imagedata>
          </imageobject>
        </mediaobject>

      </para>
      <para>
        In JORAM terminology, an HA server is actually a group of servers, one of which is the master server that coordinates the other slave servers. An external server that communicates with the HA server is actually connected to the master server.
      </para>
      <para>
        Each replicated JORAM server (element of the JORAM HA cluster, master or slave) executes the same code as a standard server except for the communication with the clients.
      </para>
      <para>
        In the example, the collocated clients use a client module (MDB). If the server replica is the master, then the connection is active enabling the client to use the HA JORAM server.  If the replica is a slave, then the connection opening is blocked until the replica becomes the master.
      </para>
    </section>
    <section><info><title>Configuration</title></info>

      <para>
        Several files must be changed to create a JORAM HA configuration:
      </para>
      <section><info><title>a3servers.xml</title></info>

        <para>
          A clustered server is defined by the element "cluster". A cluster owns an identifier and a name defined by the attributes "id" and "name"
          (exactly like a standard server). Two properties must be defined:
        </para>
        <itemizedlist>
          <listitem><para>
            "Engine" must be set to "fr.dyade.aaa.agent.HAEngine" which is the class name of the engine that provides high availability.
          </para></listitem>
          <listitem><para>
            "nbClusterExpected" defines the number of replicas that must be connected to the group communication channel used before this replica starts.
            By default it is set to 2. If there are more than two clusters,  this specification must be inserted in the configuration file.
            If there are two clusters, this specification is not required.
          </para></listitem>
        </itemizedlist>
        <para>
          In the case of one server and one replica, the value must be set to 1.
        </para>
        <screen>

&lt;?xml version="1.0"?/&gt;
&lt;config&gt;
  &lt;domain name="D1"/&gt;

  &lt;property name="Transaction" value="fr.dyade.aaa.util.NullTransaction"/&gt;

  &lt;cluster id="1" name="s1"&gt;

    &lt;property name="Engine" value="fr.dyade.aaa.agent.HAEngine" /&gt;
    &lt;property name="nbClusterExpected" value="1" /&gt;
        </screen>
        <para>
          For each replica, an element "server" must be added. The attribute "id" defines the identifier of the replica inside the cluster.
          The attribute "hostname" gives the address of the host where the replica is running.
          The network is used by the replica to communicate with external agent servers, i.e., servers located outside of the cluster and not replicas.
        </para>
        <para>
          This is the entire configuration for the a3servers.xml file of the first JOnAS instance:
        </para>
        <screen>

&lt;?xml version="1.0"?&gt;
&lt;config&lt;
  &lt;domain name="D1"/&gt;

  &lt;property name="Transaction" value="fr.dyade.aaa.util.NullTransaction"/&gt;

  &lt;cluster id="1" name="s1"&gt;

    &lt;property name="Engine" value="fr.dyade.aaa.agent.HAEngine" /&gt;
    &lt;property name="nbClusterExpected" value="1" /&gt;

    &lt;server id="1" hostname="localhost"&gt;
      &lt;network domain="D1" port="16301"/&gt;
      &lt;service class="org.objectweb.joram.mom.proxies.ConnectionManager" args="root root"/&gt;
      &lt;service class="org.objectweb.joram.mom.proxies.tcp.TcpProxyService" args="16010"/&gt;
      &lt;service class="org.objectweb.joram.client.jms.ha.local.HALocalConnection"/&gt;
    &lt;/server&gt;

    &lt;server id="2" hostname="localhost"&gt;
      &lt;network domain="D1" port="16302"/&gt;
      &lt;service class="org.objectweb.joram.mom.proxies.ConnectionManager" args="root root"/&gt;
      &lt;service class="org.objectweb.joram.mom.proxies.tcp.TcpProxyService" args="16020"/&gt;
      &lt;service class="org.objectweb.joram.client.jms.ha.local.HALocalConnection"/&gt;
    &lt;/server&gt;

  &lt;/cluster&gt;

&lt;/config&gt;
        </screen>
        <para>
          The cluster id = 1 and the name S1. It is exactly the same file for the second instance of JOnAS.
        </para>
      </section>
      <section><info><title>joramAdmin.xml</title></info>

        <para>
          Here is the joramAdmin.xml file configuration:
        </para>
        <screen>

&lt;?xml version="1.0"?&gt;

&lt;JoramAdmin&gt;

&lt;AdminModule&gt;
  &lt;collocatedConnect name="root" password="root"/&gt;
&lt;/AdminModule&gt;

&lt;ConnectionFactory className="org.objectweb.joram.client.jms.ha.tcp.HATcpConnectionFactory"&gt;
  &lt;hatcp url="hajoram://localhost:16010,localhost:16020"
            reliableClass="org.objectweb.joram.client.jms.tcp.ReliableTcpClient"/&gt;
  &lt;jndi name="JCF"/&gt;
&lt;/ConnectionFactory&gt;

&lt;ConnectionFactory className="org.objectweb.joram.client.jms.ha.tcp.QueueHATcpConnectionFactory"&gt;
  &lt;hatcp url="hajoram://localhost:16010,localhost:16020"
            reliableClass="org.objectweb.joram.client.jms.tcp.ReliableTcpClient"/&gt;
  &lt;jndi name="JQCF"/&gt;
&lt;/ConnectionFactory&gt;

&lt;ConnectionFactory className="org.objectweb.joram.client.jms.ha.tcp.TopicHATcpConnectionFactory"&gt;
  &lt;hatcp url="hajoram://localhost:16010,localhost:16020"
            reliableClass="org.objectweb.joram.client.jms.tcp.ReliableTcpClient"/&gt;
  &lt;jndi name="JTCF"/&gt;
&lt;/ConnectionFactory&gt;
        </screen>
        <para>
          Each connection factory has its own specification. One is in case of the Queue, one for Topic, and one for no define arguments.
          Each time the hatcp url must be entered, the url of the two instances. In the example, it is localhost:16010 and localhost:16020.
          It allows the client to change the instance when the first one is dead.
        </para>
        <para>
          After this definition the user, the queue and topic can be created.
        </para>
      </section>
      <section><info><title>ra and jonas-ra.xml files in joram_for_jonas_ra.rar</title></info>

        <para>
          First, in order to recognize the cluster, a new parameter must be declared in these files.
        </para>
        <screen>

      &lt;config-property&gt;
         &lt;config-property-name&gt;ClusterId&lt;/config-property-name&gt;
         &lt;config-property-type&gt;java.lang.Short&lt;/config-property-type&gt;
         &lt;config-property-value&gt;1&lt;/config-property-value&gt;
      &lt;/config-property&gt;
        </screen>
        <para>
          Here the name is not really appropriate but in order to keep some coherence this name was used. In fact it represents a replica so it would have been better to call it replicaId.
        </para>
        <para>
          Consequently, for the first JOnAS instance, copy the code just above.  For the second instance, change the value to 2 (in order to signify this is another replica).
        </para>
      </section>
    </section>
    <section><info><title>Run</title></info>

      <para>
        Deploy the MDB application in each JOnAS instance and start them.
      </para>
     <para>
        One of the two JOnAS bases (the one which is the slowest) will be in a waiting state when reading the joramAdmin.xml
      </para>
      <screen>

JoramAdapter.start :   - Collocated JORAM server has successfully started.
JoramAdapter.start :   - Reading the provided admin file: joramAdmin.xml
      </screen>
      <para>
        whereas the other one is launched successfully.
      </para>
      <para>
        Then launch the client:
      </para>
      <para>
        Messages are sent on the JOnAS instance which was launched before.
        Launch it again and kill the current JOnAS. The second JOnAS will automatically wake up and take care of the other messages.
      </para>
    </section>
  </section>
  <section xml:id="configure.jms.mdbcluster"><info><title>MDB Clustering</title></info>

    <section><info><title>Generality</title></info>

      <para>
        This is a proposal for building an MDB clustering based application.
      </para>
      <para>
        The HA mechanism can be mixed with the load balancing policy based on clustered destinations. The load is balanced between several HA servers. Each element of a clustered destination is deployed on a separate HA server.
      </para>
      <para>
        <mediaobject>
          <imageobject>
            <imagedata align="center"
                       fileref="../../../../resources/images/jmsclustering/mdbclustering.png"
                       width="70%" scalefit="1">
            </imagedata>
          </imageobject>
        </mediaobject>
      </para>
    </section>
    <section><info><title>Configuration</title></info>

      <para>
        Not available yet.
      </para>

    </section>
    <section><info><title>Illustration</title></info>

      <para>
        The configuration may now be tested, as follows:
        <itemizedlist>
          <listitem><para>
            First make JOnAS_A1 crash and verify that messages are spread between JOnAS_B1 and JOnAS_B2.
          </para></listitem>
          <listitem><para>
            Then make JOnAS_B2 crash and verify that messages are spread between JOnAS_A1 and JOnAS_A2.
          </para></listitem>
          <listitem><para>
            Finally make JOnAS_A1 and JOnAS_B2 crash and verify that messages are spread between JOnAS_A2 and JOnAS_B1.
          </para></listitem>
        </itemizedlist>
      </para>
    </section>
  </section>

</section>

