<?xml version="1.0"?>
<!--

 Licensed to the Apache Software Foundation (ASF) under one
 or more contributor license agreements.  See the NOTICE file
 distributed with this work for additional information
 regarding copyright ownership.  The ASF licenses this file
 to you under the Apache License, Version 2.0 (the
 "License"); you may not use this file except in compliance
 with the License.  You may obtain a copy of the License at

   http://www.apache.org/licenses/LICENSE-2.0

 Unless required by applicable law or agreed to in writing,
 software distributed under the License is distributed on an
 "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 KIND, either express or implied.  See the License for the
 specific language governing permissions and limitations
 under the License.

-->

<chapter xmlns="http://docbook.org/ns/docbook" version="5.0" xml:id="JMS-Client-0-8-Client-Understanding">
  <title>Understanding the Client</title>
  <section xml:id="JMS-Client-0-8-Client-Understanding-Overview">
    <title>Overview</title>
    <para>The Client provides a JMS 1.1 compliant implementation. As such, the primary
      source of documentation is the <link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="${oracleJmsSpec}">JMS specification</link> and the
        <link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="${oracleJeeDocUrl}/javax/jms/package-summary.html">JMS javadocs</link>. This
      documentation assumes the reader has familiarity with these resources.</para>
    <para>The remainder of this section describes how the Client behaves and the effect(s)
      making JMS method calls will have on the Broker. </para>
    <para>There areas where the Client provides features beyond those required for JMS
      compliance. These are described in the sections that follow.</para>
    <para>These sections are also used to bring out differences that may surprise those moving from
      JMS implementations provided by other vendors.</para>
    <figure>
      <title>Architecture of a typical JMS application</title>
      <mediaobject>
        <imageobject>
          <imagedata fileref="images/QpidJmsOverview.png" format="PNG" scalefit="1"/>
        </imageobject>
      </mediaobject>
    </figure>
  </section>
  <section xml:id="JMS-Client-0-8-Client-Understanding-ConnectionFactory">
    <title>ConnectionFactory</title>
    <para>A <link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="${oracleJeeDocUrl}javax/jms/ConnectionFactory.html">ConnectionFactory</link>
      allows an application to create a <link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="${oracleJeeDocUrl}javax/jms/Connection.html">Connection</link>.</para>
    <para>The application obtains the ConnectionFactory from an <link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="${oracleJeeDocUrl}javax/naming/InitialContext.html">InitialContext</link>. The
      InitialContext is itself obtained from an InitialContextFactory. </para>
    <para>The Client provides a single implementation of the InitialContextFactory in class
        <literal>org.apache.qpid.jndi.PropertiesFileInitialContextFactory</literal>. This
      implementation is backed by a <link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="${oracleJeeDocUrl}java/util/Properties.html">Properties</link> object which can of course be loaded from an external properties file,
      or created programatically.</para>
    <para>The examples in the previous chapter illustrated the Java code required to <link linkend="JMS-Client-0-8-Examples-PTP">create the InitialContext</link> and an <link linkend="JMS-Client-0-8-Examples-PTP-PropertiesFile">example properties file</link>.</para>
    <para>The Client also provides an alternate connection factory implementation providing a
      connection pool. This can be useful when utilsing frameworks such as Spring.
      <xref linkend="JMS-Client-0-8-Appendix-PooledConnecytionFactory"/>.</para>
    <figure>
      <title>JNDI overview</title>
      <mediaobject>
        <imageobject>
          <imagedata fileref="images/JndiOverview.png" format="PNG" scalefit="1"/>
        </imageobject>
      </mediaobject>
    </figure>
    <para>Note that the Apache Qpid Broker for Java does not present a JNDI interface to the application.</para>
  </section>
  <section xml:id="JMS-Client-0-8-Client-Understanding-Connection">
    <title>Connection</title>
    <para>A Connection represents an open communication channel between application and
      Broker.</para>
    <para>Connections are created from the ConnectionFactory <footnote>
        <para>Constructors of the AMQConnection class must not be used.</para>
      </footnote>.</para>
    <para>Each connection utilises a single TCP/IP connection between the process of the application
      and the process of the Broker. The act of establishing a connection is therefore a relatively
      expensive operation. It is recommended that the same connection is used for a series of
      message interactions. Patterns utilising a connection per message should not be used. </para>
    <para>The underlying TCP/IP connection remains open for the lifetime of the JMS connection. It
      is closed when the application calls <link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="${oracleJeeDocUrl}javax/jms/Connection.html#close()">Connection#close()</link>, but it
      can also be closed if the connection is closed from the Broker side (via a Management
      operation or broker shutdown or running into conditions which AMQP specifications treats as
      errors and mandates closing the connection). The JMS connection will also be closed if the
      underlying TCP/IP connection is broken.</para>
    <para>Qpid connections have failover and heartbeating capabilities. They support SSL and
      client-auth. These are described in the sub-sections that follow.</para>
    <section xml:id="JMS-Client-0-8-Client-Understanding-Connection-Failover">
      <title>Failover</title>
      <para>Qpid connections support a failover feature. This is the ability to automatically
        re-establish a failed connection, either to the same Broker, or the next Broker in the
        broker list.</para>
      <para>This failover process is done in a manner that is mostly transparent to the application.
        After a successful failover, any existing Connection, Session, MessageConsumer and
        MessageProducer objects held by the application remain valid.</para>
      <para>If a failover occurs during the scope of a JMS Transaction, any work performed by that
        transaction is lost. The application is made aware of this loss by way of the <link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="${oracleJeeDocUrl}javax/jms/TransactionRolledBackException.html">TransactionRolledBackException</link> from the <link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="${oracleJeeDocUrl}javax/jms/Session.html#commit">Session#commit()</link> call.
        Applications utilising failover must be prepared to catch this exception and respond by
        either repeating the work of the transaction, or by propagating a rollback to the
        originating system.</para>
      <para>If, after all retries are exhausted, failover has failed to reconnect the application,
        the Connection's <link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="${oracleJeeDocUrl}javax/jms/ExceptionListener.html">ExceptionListener</link> will receive a JMSException with a linked exception of <link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="JMS-Client-0-8-Appendix-Exceptions-AMQDisconnectedException">AMQDisconnectedException</link>. Any further use of the JMS objects (Connection, Session
        etc), will results in a <link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="${oracleJeeDocUrl}javax/jms/IllegalStateException.html">IllegalStateException</link>.</para>
      <para>Configure failover using the Connection URL. Here's an example Connection URL utilising
        failover between two brokers. Note the use of the broker options <link linkend="JMS-Client-0-8-Connection-URL-BrokerOptions-Retries"><literal>retries</literal></link> and <link linkend="JMS-Client-0-8-Connection-URL-BrokerOptions-ConnectDelay"><literal>connectdelay</literal></link> to control the number of connection attempts to
        each individual broker, and the delay between each connection attempt. Also note the use of
        the <emphasis>failover option</emphasis>
        <literal>cyclecount</literal> to control the number of times the failover mechanism will
        traverse the brokerlist.</para>
      <example>
        <title>Connection URL configured for failover</title>
        <screen>
amqp://username:password@clientid/test
            ?brokerlist='tcp://localhost:15672?retries='10'&amp;connectdelay='1000';tcp://localhost:25672?retries='10'&amp;connectdelay='1000''
            &amp;failover='roundrobin?cyclecount='20''
        </screen>
      </example>
      <para>For full details see <xref linkend="JMS-Client-0-8-Connection-URL"/></para>
      <note>
        <para>Note, that a single broker failover is enabled by default. If the failover behaviour
          is not desired it can be switched off by setting a failover option to
            <literal>nofailover</literal> as in the example below <example>
            <title>Connection URL configured with nofailover</title>
            <screen>
amqp://username:password@clientid/test
            ?brokerlist='tcp://localhost:15672?failover='nofailover'
        </screen>
          </example>
        </para>
      </note>
    </section>
    <section xml:id="JMS-Client-0-8-Client-Understanding-Connection-Heartbeating">
      <title>Heartbeating</title>
      <para>Qpid connections support heartbeating. When enabled, the Client and Broker
        exchange a heartbeat during periods of inactivity. This allows both peers to discover if the
        TCP/IP connection becomes inoperable in a timely manner.</para>
      <para>This feature is sometimes useful in applications that must traverse firewalls as the
        heartbeat prevents connections from being closed during periods when there is no application
        traffic.</para>
      <para>It is also allows the both the JMS client and the Broker to confirm that the other is
          <emphasis>minimally</emphasis> responsive. (It does nothing however to determine the
        health of the higher level tiers of application, for this reason, applications may implement
        an application level heartbeat either in addition to, or instead of the heartbeat.</para>
      <para>If the client ever fails to receive two consecutive heartbeats, the Connection will be
        automatically closed and the Connection's <link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="${oracleJeeDocUrl}javax/jms/ExceptionListener.html">ExceptionListener</link> will
        receive a JMSException with a linked exception of AMQDisconnectedException. Any further use
        of the JMS objects (Connection, Session etc), will results in a <link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="${oracleJeeDocUrl}javax/jms/IllegalStateException.html">IllegalStateException</link>.</para>
      <para>To enable heartbeating either use a Connection URL including the broker option <link linkend="JMS-Client-0-8-Connection-URL-BrokerOptions-Heartbeat"><literal>heartbeat</literal></link>, or use the system property <link linkend="JMS-Client-0-8-System-Properties-Heartbeat"><literal>qpid.heartbeat</literal></link>. </para>
      <example>
        <title>Connection URL configured for heartbeating</title>
        <screen>
amqp://guest:guest@clientid/?brokerlist='localhost:5672?heartbeat='5''
        </screen>
      </example>
    </section>
    <section xml:id="JMS-Client-0-8-Client-Understanding-Connection-SSL">
      <title>SSL</title>
      <para>The Client supports connections encrypted using Secure Socket Layer (SSL) and
        SSL-Client Authentication. SSL is configured using Connection URL. To use SSL, SSL must be
        be configured on the Broker.</para>
      <para>Some example Connection URLs using SSL follow:</para>
      <itemizedlist>
        <listitem>
          <para>Simple SSL when the Broker is secured by a certificate that is signed by a CA which
            is trusted by the JVM.</para>
          <example>
            <title>Connection URL configured for SSL - CA trusted by JVM</title>
            <screen>
amqp://guest:guest@clientid/?brokerlist='localhost:5671'&amp;ssl='true'
            </screen>
          </example>
        </listitem>
        <listitem>
          <para>SSL when the Broker is secured by a certificate that is signed by a CA which is NOT
            trusted by the JVM (such as when a organisation is using a private CA, or self-signed
            certificates are in use). For this case, we use <link linkend="JMS-Client-0-8-Connection-URL-BrokerOptions-TrustStore"><literal>trust_store</literal></link> and <link linkend="JMS-Client-0-8-Connection-URL-BrokerOptions-TrustStorePassword"><literal>trust_store_password</literal></link> to specify a path a truststore file
            (containing the certificate of the private-CA) and the truststore password.</para>
          <example>
            <title>Connection URL configured for SSL - CA not trusted by JVM</title>
            <screen>
amqp://guest:guest@clientid/?brokerlist='localhost:5671?trust_store='/path/to/acme_org_ca.ts'&amp;trust_store_password='secret''&amp;ssl='true'
            </screen>
          </example>
        </listitem>
        <listitem>
          <para>SSL with SSL client-auth. For this case, we use <link linkend="JMS-Client-0-8-Connection-URL-BrokerOptions-KeyStore"><literal>key_store</literal></link> and <link linkend="JMS-Client-0-8-Connection-URL-BrokerOptions-KeyStorePassword"><literal>key_store_password</literal></link> to specify a path a keystore file
            (containing the certificate of the client) and the keystore password.</para>
          <example>
            <title>Connection URL configured for SSL - SSL client-auth</title>
            <screen>
amqp://guest:guest@clientid/?brokerlist='localhost:5671?key_store='/path/to/app1_client_cert.ks'&amp;key_store_password='secret''&amp;ssl='true'
            </screen>
          </example>
          <para>Alternatively we can use <link linkend="JMS-Client-0-8-Connection-URL-BrokerOptions-ClientCertPath"><literal>client_cert_path</literal></link> and <link linkend="JMS-Client-0-8-Connection-URL-BrokerOptions-ClientCertPrivKeyPath"><literal>client_cert_priv_key_ath</literal></link> to specify a path to a certificate file (in PEM or DER format)
            and the private key information (again in either PEM or DER format) respectively.</para>
          <example>
            <title>Connection URL configured for SSL - SSL client-auth (2)</title>
            <screen>
amqp://guest:guest@clientid/?brokerlist='localhost:5671?client_cert_path='/path/to/app1_client.crt'&amp;client_cert_priv_key_path='/path/to/app1_client.key''&amp;ssl='true'
            </screen>
          </example>
        </listitem>
      </itemizedlist>
    </section>
    <section xml:id="JMS-Client-0-8-Client-Understanding-Connection-MessageCompression">
      <title>Message Compression</title>
      <para>The client has the ability to transparently compress message payloads on outgoing
        messages and decompress them on incoming messages. In some environments and with some
        payloads this feature might offer performance improvements by reducing the number of bytes
        transmitted over the connection.</para>
      <para>In order to make use of message compression, the Broker must enable the feature too,
        otherwise the compression options will be ignored.</para>
      <para> To enable message compression on the client use the connection url property <link linkend="JMS-Client-0-8-Connection-URL-ConnectionOptions-CompressMessages"><literal>compressMessages</literal></link> (or JVM wide using the system property <link linkend="JMS-Client-0-8-System-Properties-ConnectionCompressMessages"><literal>qpid.connection_compress_messages</literal></link>)</para>
      <para>It is also possible to control the threshold at which the client will begin to compress
        message payloads. See connection url property <link linkend="JMS-Client-0-8-Connection-URL-ConnectionOptions-MessageCompressionThresholdSize"><literal>messageCompressionThresholdSize</literal></link> (or JVM wide using the system
        property <link linkend="JMS-Client-0-8-System-Properties-MessageCompressionThresholdSize"><literal>qpid.message_compression_threshold_size</literal></link>)</para>
      <note>
        <para>The Broker, where necessary, takes care of compressing/decompressing messages of the
          fly so that clients using message compression can exchange messages with clients not
          supporting message compression transparently, without application intervention.</para>
      </note>
    </section>
  </section>
  <section xml:id="JMS-Client-0-8-Client-Understanding-Session">
    <title>Session</title>
    <para>A Session object is a single-threaded context for producing and consuming messages.</para>
    <para>Session objects are created from the Connection. Whilst Session objects are relatively
      lightweight, patterns utilising a single Session per message are not recommended.</para>
    <para>The number of sessions open per connection at any one time is limited. This value is
      negotiated when the connection is made. It defaults to 256.</para>
    <para>Qpid JMS Sessions have the ability to prefetch messages to improve consumer performance.
      This feature is described next.</para>
    <section xml:id="JMS-Client-0-8-Client-Understanding-Session-Prefecth">
      <title>Prefetch</title>
      <para>Prefetch specifies how many messages the client will optimistically cache for delivery
        to a consumer. This is a useful parameter to tune that can improve the throughput of an
        application. The prefetch buffer is scoped per <emphasis>Session</emphasis>.</para>
      <para>The size of the prefetch buffer can be tuned per Connection using the connection url
        option <link linkend="JMS-Client-0-8-Connection-URL-ConnectionOptions-Maxprefetch"><literal>maxprefetch</literal></link> (or JVM wide using the system property <link linkend="JMS-Client-0-8-System-Properties-Maxprefetch"><literal>max_prefetch</literal></link>). By default, prefetch defaults to 500.</para>
      <para>There are situations when you may wish to consider reducing the size of prefetch:</para>
      <para>
        <orderedlist>
          <listitem>
            <para>When using a <link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="http://www.eaipatterns.com/CompetingConsumers.html">Competing Consumers</link> pattern, prefetch can give the appearance of unequal
              division of work. This will be apparent on startup when the queue has messages. The
              first consumer started will cache prefetch size number of messages, possibly leaving
              the other consumers with no initial work.</para>
          </listitem>
          <listitem>
            <para>When using special queue types (such as LVQs, Sorted Queue and Priority Queues).
              For these queue types the special delivery rules apply whilst the message resides on
              the Broker. As soon as the message is sent to the client it delivery order is then
              fixed. For example, if using a priority queue, and a prefetch of 100, and 100 messages
              arrive with priority 2, the broker will send these to the client. If then a new
              message arrives with priority 1, the broker cannot leap frog messages of the lower
              priority. The priority 1 message will be delivered at the front of the next
              batch.</para>
          </listitem>
          <listitem>
            <para>When message size is large and you do not wish the memory footprint of the
              application to grow (or suffer an OutOfMemoryError).</para>
          </listitem>
        </orderedlist>
      </para>
      <para>Finally, if using multiple MessageConsumers on a single Session, keep in mind that
        unless you keep polling <emphasis>all</emphasis> consumers, it is possible for some traffic
        patterns to result in consumer starvation and an application level deadlock. For example, if
        prefetch is 100, and 100 hundred messages arrive suitable for consumer A, those messages
        will be prefetched by the session, entirely filling the prefetch buffer. Now if the
        application performs a blocking <link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="${oracleJeeDocUrl}javax/jms/MessageConsumer.html#receive()">MessageConsumer#receive()</link> for Consumer B on the same Session, the application
        will hang indefinitely as even if messages suitable for B arrive at the Broker. Those
        messages can never be sent to the Session as no space is available in prefetch. </para>
      <note>
        <para>Please note, when the acknowledgement mode
            <emphasis>Session#SESSION_TRANSACTED</emphasis> or
            <emphasis>Session#CLIENT_ACKNOWLEDGE</emphasis> is set on a consuming session, the
          prefetched messages are released from the prefetch buffer on transaction commit/rollback
          (in case of acknowledgement mode <emphasis>Session#SESSION_TRANSACTED</emphasis> ) or
          acknowledgement of the messages receipt (in case of acknowledgement mode
            <emphasis>Session#CLIENT_ACKNOWLEDGE</emphasis> ). If the consuming application does not
          commit/rollback the receiving transaction (for example, due to mistakes in application
          exception handling logic), the prefetched messages continue to remain in the prefetch
          buffer preventing the delivery of the following messages. As result, the application might
          stop the receiving of the messages until the transaction is committed/rolled back (for
            <emphasis>Session#SESSION_TRANSACTED</emphasis> ) or received messages are acknowledged
          (for <emphasis>Session#CLIENT_ACKNOWLEDGE</emphasis>).</para>
      </note>
      <para>
          Settings maxprefetch to 0 ( either globally via JVM system property
          <link linkend="JMS-Client-0-8-System-Properties-Maxprefetch"><literal>max_prefetch</literal></link>
          or on a connection level as a connection option
          <link linkend="JMS-Client-0-8-Connection-URL-ConnectionOptions-Maxprefetch"><literal>maxprefetch</literal></link> )
          switches off the pre-fetching functionality. With maxprefetch=0 messages are fetched one by one without caching on the client.
      </para>
      <note>
        <para> Setting maxprefetch to 0 is recommended in Spring-JMS based applications whenever
            <emphasis>DefaultMassgeListenerContainer</emphasis> is configured with a
            <emphasis>CachingConnectionFactory</emphasis> that has <emphasis>cacheLevel</emphasis>
          set to either <emphasis>CACHE_CONSUMER</emphasis> or <emphasis>CACHE_SESSION</emphasis>.
          In these configurations the Qpid JMS <emphasis>Session</emphasis> objects remain open in
          Spring's dynamically scaled pools. If maxprefetch is not 0, any prefetched messages held
          by the <emphasis>Session</emphasis> and any new ones subsequently sent to it (in the
          background until prefetch is reached) will be effectively by 'stuck' (unavailable to the
          application) until Spring decides to utilise the cached Session again. This can give the
          impression that message delivery has stopped even though messages remain of the queue.
          Setting maxprefetch to 0 prevents this problem from occurring.</para>
        <para> If using maxprefetch &gt; 0 <emphasis>SingleConnectionFactory</emphasis> must be
          used. SingleConnectionFactory does not have the same session/consumer caching behaviour so
          does not exhibit the same problem. </para>
      </note>
    </section>
    <section xml:id="JMS-Client-0-8-Client-Understanding-Session-TemporaryQueues">
      <title>TemporaryQueues</title>
      <para>Temporary queues are exposed to Management in the same way as normal queues. Temporary
        queue names take the form string <literal>TempQueue</literal> followed by a random
        UUID.</para>
    </section>
    <section xml:id="JMS-Client-0-8-Client-Understanding-Session-CreateQueue">
      <title>CreateQueue</title>
      <para>In the Client, <link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="${oracleJeeDocUrl}javax/jms/Session.html#createQueue(java.lang.String)">Session#createQueue()</link> accepts either a queue name, or a Binding URL. If only name
        is specified the destination will be resolved into binding URL:
        direct://amq.direct//&lt;queue name&gt;?routingkey=&apos;&lt;queue name&gt;&apos;&amp;durable=&apos;true&apos;. </para>
      <para>Calling Session#createQueue() has no effect on the Broker.</para>
      <para>Reiterating the advice from the JMS javadoc, it is suggested that this method is not
        generally used. Instead, application should lookup Destinations declared within JNDI.</para>
    </section>
    <section xml:id="JMS-Client-0-8-Client-Understanding-Session-CreateTopic">
      <title>CreateTopic</title>
      <para>In the Client, <link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="${oracleJeeDocUrl}javax/jms/Session.html#createTopic(java.lang.String)">Session#createTopic()</link> accepts either a topic name, or a Binding URL. If only name
        is specified the destination will be resolved into binding URL: topic://amq.topic//&lt;topic
        name&gt;?routingkey=&apos;&lt;topic name&gt;&apos;.</para>
      <para>Calling Session#createTopic() has no effect on the Broker.</para>
      <para>Reiterating the advice from the JMS javadoc, it is suggested that this method is not
        generally used. Instead, application should lookup Destinations declared within JNDI.</para>
    </section>
  </section>
  <section xml:id="JMS-Client-0-8-Client-Understanding-MessageProducer">
    <title>MessageProducer</title>
    <para>A MessageProducer sends a message an <emphasis>Exchange</emphasis>. It is the Exchange
      (within the Broker) that routes the message to zero or more queue(s). Routing is performed
      according to rules expressed as <emphasis>bindings</emphasis> between the exchange and queues
      and a <emphasis>routing key</emphasis> included with each message.</para>
    <para>To understand how this mechanism is used to deliver messages to queues and topics, see
        <link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="${qpidJavaBrokerBook}Java-Broker-Concepts-Exchanges.html">Exchanges</link>
      within the Apache Qpid Broker for Java book.</para>
    <para>It is important to understand that when synchronous publish is not exlicitly enabled,
      <link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="${oracleJeeDocUrl}javax/jms/MessageProducer.html#send(javax.jms.Message)">MessageProducer#send()</link> is <emphasis>asynchronous</emphasis> in nature. When #send()
      returns to the application, the application cannot be certain if the Broker has received the
      message. The Client may not have yet started to send the message, the message could
      residing in a TCP/IP buffer, or the messages could be in some intermediate buffer within the
      Broker. If the application requires certainty the message has been received by the Broker, a
        <link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="${oracleJeeDocUrl}javax/jms/Session.html#SESSION_TRANSACTED">transactional
        session</link>
      <emphasis>must</emphasis> be used, or synchronous publishing must be enabled using either the
      <link linkend="JMS-Client-0-8-System-Properties-SyncPublish">system property</link> or the
      <link linkend="JMS-Client-0-8-Connection-URL-ConnectionOptions-SyncPublish">connection URL
      option</link>.</para>
    <para>Qpid JMS MessageProducers have a number of features above that required by JMS. These are
      described in the sub-sections that follow.</para>
    <section xml:id="JMS-Client-0-8-Client-Understanding-MessageProducer-MandatoryMessage">
      <title>Mandatory Messages</title>
      <para>With this feature, publishing a message with a routing key for which no binding exists
        on the exchange will result in the message being returned to the publisher's
        connection.</para>
      <para>The Message is returned to the application in an asynchronous fashion via the
        Connection's <link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="${oracleJeeDocUrl}javax/jms/ExceptionListener.html">ExceptionListener</link>. When a message is returned, it will be invoked with a
        JMSException whose linked exception is an <link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="JMS-Client-0-8-Appendix-Exceptions-AMQNoRouteException">AMQNoRouteException</link>.
        The returned message is available to the application by calling
        AMQNoRouteException#getUndeliveredMessage(). The ExceptionListener will be invoked exactly
        once for each returned message.</para>
      <para>If synchronous publishing has been enabled, and a mandatory message is returned, the
      <link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="${oracleJeeDocUrl}javax/jms/MessageProducer.html#send(javax.jms.Message)">MessageProducer#send()</link> method will throw a JMSException.
      </para>
      <para>The mandatory message feature is turned <emphasis>on</emphasis> by default for Queue
        destinations and <emphasis>off</emphasis> for Topic destinations. This can be overridden
        using system properties <link linkend="JMS-Client-0-8-System-Properties-DefaultMandatory"><literal>qpid.default_mandatory</literal></link> and <link linkend="JMS-Client-0-8-System-Properties-DefaultMandatoryTopic"><literal>qpid.default_mandatory_topic</literal></link> for Queues and Topics
        respectively.</para>
      <note>
        <para>If this the mandatory flag is not set, the Broker will treat <link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="${qpidJavaBrokerBook}Java-Broker-Concepts-Exchanges.html#Java-Broker-Concepts-Exchanges-UnroutableMessage">the messages as unroutable</link>.</para>
      </note>
    </section>
    <section xml:id="JMS-Client-0-8-Client-Understanding-MessageProducer-CloseWhenNoRoute">
      <title>Close When No Route</title>
      <para>With this feature, if a mandatory message is published with a routing key for which no
        binding exists on the exchange the Broker will close the connection. This client feature
        requires support for the corresponding feature by the Broker.</para>
      <para>To enable or disable from the client, use the Connection URL option <link linkend="JMS-Client-0-8-Connection-URL-ConnectionOptions-CloseWhenNoRoute"><literal>closeWhenNoRoute</literal></link>.</para>
      <para>See <link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="${qpidJavaBrokerBook}Java-Broker-Runtime-Close-Connection-When-No-Route.html">
          Closing client connections on unroutable mandatory messages</link> within the Apache Qpid Broker for Java
        book for full details of the functioning of this feature.</para>
    </section>
    <section xml:id="JMS-Client-0-8-Client-Understanding-MessageProducer-ImmediateMessage">
      <title>Immediate Messages</title>
      <para>This feature is defined in <link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="${amqpSrc}">AMQP specifications</link>.</para>
      <para>When this feature is enabled, when publishing a message the Broker ensures that a
        Consumer is attached to queue. If there is no Consumer attached to the queue, the message is
        returned to the publisher's connection. The Message is returned to the application in an
        asynchronous fashion using the Connection's <link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="${oracleJeeDocUrl}javax/jms/ExceptionListener.html">ExceptionListener</link>.</para>
      <para>The ExceptionListener will be invoked with a JMSException whose linked exception is an
          <link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="JMS-Client-0-8-Appendix-Exceptions-AMQNoConsumersException">AMQNoConsumersException</link>. The returned message is available to the application by
        calling AMQNoConsumersException#getUndeliveredMessage(). The ExceptionListener will be
        invoked exactly once for each returned message.</para>
      <para>If synchronous publishing has been enabled, and an immediate message is returned, the
      <link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="${oracleJeeDocUrl}javax/jms/MessageProducer.html#send(javax.jms.Message)">MessageProducer#send()</link> method will throw a JMSException.
      </para>
      <para>The immediate message feature is turned <emphasis>off</emphasis> by default. It can be
        enabled with system property <link linkend="JMS-Client-0-8-System-Properties-DefaultImmediate"><literal>qpid.default_immediate</literal></link>.</para>
    </section>
    <section xml:id="JMS-Client-0-8-Client-Understanding-MessageProducer-FlowControl">
      <title>Flow Control</title>
      <para>With this feature, if a message is sent to a queue that is overflow, the producer's
        session is blocked until the queue becomes underfull, or a timeout expires. This client
        feature requires support for the corresponding feature by the Broker.</para>
      <para>To control the timeout use System property <link linkend="JMS-Client-0-8-System-Properties-FlowControlWaitFailure"><literal>qpid.flow_control_wait_failure</literal></link>. To control the frequency with
        which warnings are logged whilst a Session is blocked, use System property <link linkend="JMS-Client-0-8-System-Properties-FlowControlWaitNotifyPeriod"><literal>qpid.flow_control_wait_notify_period</literal></link></para>
      <para>See <link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="${qpidJavaBrokerBook}Java-Broker-Runtime-Disk-Space-Management.html#Qpid-Producer-Flow-Control"> Producer Flow Control</link> within the Apache Qpid Broker for Java book for full details of the
        functioning of this feature.</para>
    </section>
  </section>
  <section xml:id="JMS-Client-0-8-Client-Understanding-MessageConsumer">
    <title>MessageConsumer</title>
    <para>A MessageConsumer receives messages from a Queue or Topic.</para>
    <para>MessageConsumer objects are created from the Session.</para>
    <para>Qpid JMS MessageConsumers have a number of features above that required by JMS. These are
      described in the sub-sections that follow.</para>
    <section xml:id="JMS-Client-0-8-Client-Understanding-MessageConsumer-ConsumerSideEffect">
      <title>Consumers have Exchange/Queue Declaration and Binding Side Effect</title>
      <para>By default, calling <link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="${oracleJeeDocUrl}javax/jms/Session.html#createConsumer(javax.jms.Destination)">Session#createConsumer()</link> will cause:</para>
      <orderedlist>
        <listitem>
          <para>If the exchange does not exist on the Broker, it will be created. The exchange is
            specified by the Binding URL associated with the Destination.</para>
        </listitem>
        <listitem>
          <para>If the queue does not exist on the Broker, it will be created. The queue is
            specified by the Binding URL associated with the Destination.</para>
        </listitem>
        <listitem>
          <para>If there is no binding between the exchange and queue, a binding will be created
            using the routingkey as a bindingkey. The exchange, queue and routing key are specified
            by the Binding URL associated with the Destination.</para>
        </listitem>
      </orderedlist>
      <para>The exchange declare, queue declare and bind side effects can be suppressed using system
        properties <link linkend="JMS-Client-0-8-System-Properties-DeclareExchanges"><literal>qpid.declare_exchanges</literal></link>, <link linkend="JMS-Client-0-8-System-Properties-DeclareQueues"><literal>qpid.declare_queues</literal></link> and <link linkend="JMS-Client-0-8-System-Properties-BindQueues"><literal>qpid.bind_queues</literal></link>.</para>
    </section>
    <section xml:id="JMS-Client-0-8-Client-Understanding-MessageConsumer-TopicSubscriptions">
      <title>Topic Subscriptions</title>
      <para>The Client implements each subscription to a Topic as separate queue on the
        Broker. From the perspective of the JMS application this implementational detail is
        irrelevant: the application never needs to directly address these queues. However, these
        details are important when considering Management and Operational concerns.</para>
      <para>Durable topic subscriptions use a <emphasis>durable</emphasis> and
          <emphasis>exclusive</emphasis> queue named as follows:</para>
      <programlisting>
        clientid: + subscriptionId
      </programlisting>
      <para>where <literal>subscriptionId</literal> is that passed to the <link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="${oracleJeeDocUrl}javax/jms/Session.html#createDurableSubscriber(javax.jms.Topic,%20java.lang.String)">Session#createDurableSubscriber(javax.jms.Topic,java.lang.String)</link></para>
      <para>Calling <link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="${oracleJeeDocUrl}javax/jms/Session.html#unsubscribe(java.lang.String)">Session#unsubscribe(java.lang.String)</link> deletes the underlying queue.</para>
      <para>Non-durable topic subscriptions use a <emphasis>non-durable</emphasis>,
          <emphasis>exclusive</emphasis> and <emphasis>auto-delete</emphasis> queue named as
        follows:</para>
      <programlisting>
        tmp + _ + ip + _ + port + _ + sequence
      </programlisting>
      <para>where <literal>ip</literal> is the ip address of the client with dots replaced by
        underscores, <literal>port</literal> is the ephemeral port number assigned to the client's
        connection, and <literal>sequence</literal> is a sequence number.</para>
      <para>Closing the consumer (or closing the connection) will delete the underlying
        queue.</para>
    </section>
    <section xml:id="JMS-Client-0-8-Client-Understanding-MessageConsumer-MaximumDeliveryCount">
      <title>Maximum Delivery Count</title>
      <para>With this feature, the Broker keeps track of a number of times a message has been
        delivered to a consumer. If the count ever exceeds a threshold value, the Broker moves the
        message to a dead letter queue (DLQ). This is used to prevent poison messages preventing a
        system's operation. This client feature requires support for the corresponding feature by
        the Broker.</para>
      <para>When using this feature, the application must either set system property <link linkend="JMS-Client-0-8-System-Properties-RejectBehaviour">qpid.reject.behaviour</link> or
        the Binding URL option <link linkend="JMS-Client-0-8-Binding-URL-Options-RejectBehaviour"><literal>rejectbehaviour</literal></link> to the value
        <literal>server</literal>.</para>
      <para>See <link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="${qpidJavaBrokerBook}Java-Broker-Runtime-Handling-Undeliverable-Messages.html#Java-Broker-Runtime-Handling-Undeliverable-Messages-Maximum-Delivery-Count"> Handling Undeliverable Messages</link> within the Apache Qpid Broker for Java book for full details of
        the functioning of this feature.</para>
      <note>
        <para>The optional JMS message header <literal>JMSXDeliveryCount</literal> is
            <emphasis>not</emphasis> supported.</para>
      </note>
    </section>
  </section>
  <section xml:id="JMS-Client-0-8-Client-Understanding-Destinations">
    <title>Destinations</title>
    <para>A Destination is either a Queue or Topic. In the Client a Destination
      encapsulates a Binding URL. In simple terms, the Binding URL comprises of an exchange, queue
      and a routing key. Binding URLs are described fully by <xref linkend="JMS-Client-0-8-Binding-URL"/>. </para>
    <para>In many cases, applications do not need to deal directly with Binding URLs, instead they
      can refer to JMS administered objects declared in the JNDI properties file with the
        <literal>queue.</literal> and <literal>topic.</literal> prefix to create Queues and Topics
      objects respectively. </para>
  </section>
</chapter>
