activemq-artemis/examples/jms/no-consumer-buffering
jbertram a102983d7a ACTIVEMQ6-51 Example server bootstrapping 2014-12-10 09:49:13 -06:00
..
src/main ACTIVEMQ6-51 Example server bootstrapping 2014-12-10 09:49:13 -06:00
pom.xml ACTIVEMQ6-51 Example server bootstrapping 2014-12-10 09:49:13 -06:00
readme.html More name changes to activemq 2014-11-19 16:01:54 -05:00

readme.html

<html>
  <head>
    <title>ActiveMQ No Consumer Buffering Example</title>
    <link rel="stylesheet" type="text/css" href="../common/common.css" />
    <link rel="stylesheet" type="text/css" href="../common/prettify.css" />
    <script type="text/javascript" src="../common/prettify.js"></script>
  </head>
  <body onload="prettyPrint()">
     <h1>No Consumer Buffering Example</h1>

     <p>By default, ActiveMQ consumers buffer messages from the server in a client side buffer
     before actual delivery actually occurs.</p>
     <p>This improves performance since otherwise every time you called receive() or had processed the last
     message in a MessageListener onMessage() method, the ActiveMQ client would have to go the
     server to request the next message involving a network round trip for every message reducing performance.</p>
     <p>Therefore, by default, ActiveMQ pre-fetches messages into a buffer on each consumer. The total maximum size of
     messages in bytes that will be buffered on each consumer is determined by the <code>consumer-window-size</code>
     parameter on the connection factory.</p>
     <p>In some cases it is not desirable to buffer any messages on the client side consumer.</p>
     <p>An example would be an order queue which had multiple consumers that processed orders from the queue.
     Each order takes a significant time to process, but each one should be processed in a timely fashion.</p>
     <p>If orders were buffered in each consumer, and a new consumer was added that consumer would not be able
     to process orders which were already in the client side buffer of another consumer.</p>
     <p>To turn off client side buffering of messages, set <code>consumer-window-size</code> to zero.</p>
     
     <p>With ActiveMQ you can specify a maximum consume rate at which a JMS MessageConsumer will consume messages.
     This can be specified when creating or deploying the connection factory. See <code>activemq-jms.xml</code></p>
     <h2>Example step-by-step</h2>
     <p>In this example we specify a <code>consumer-window-size</code> of <code>0</code> bytes in the <code>activemq-jms.xml</code>
     file when deploying the connection factory:</p>
     <pre class="prettyprint">
     <code>
   &lt;connection-factory name="ConnectionFactory"&gt;
      &lt;connector-ref connector-name="netty-connector"/&gt;
      &lt;entries&gt;
         &lt;entry name="ConnectionFactory"/&gt;       
      &lt;/entries&gt;
      
      &lt;!-- We set the consumer window size to 0, which means messages are not buffered at all
      on the client side --&gt;
      &lt;consumer-window-size&gt;0&lt;/consumer-window-size&gt;
      
   &lt;/connection-factory&gt;
     </code>
     </pre>
     <p>We create a consumer on a queue and send 10 messages to it. We then create another consumer on
     the same queue.</p>
     <p>We then consume messages from each consumer in a semi-random order. We note that the messages
     are consumed in the order they were sent.</p>
     <p>If the messages had been buffered in each consumer they would not be available to be consumed
     in an order determined afer delivery.</p>    

     <p><i>To run the example, simply type <code>mvn verify</code> from this directory</i></p>

     <ol>
        <li>Create an initial context to perform the JNDI lookup.</li>
        <pre class="prettyprint">
           <code>initialContext = getContext(0);</code>
        </pre>

        <li>Perfom a lookup on the queue</li>
        <pre class="prettyprint">
           <code>Queue queue = (Queue)initialContext.lookup("/queue/exampleQueue");</code>
        </pre>

        <li>Perform a lookup on the Connection Factory</li>
        <pre class="prettyprint">
           <code>ConnectionFactory cf = (ConnectionFactory)initialContext.lookup("/ConnectionFactory");</code>
        </pre>

        <li>Create a JMS Connection</li>
        <pre class="prettyprint">
           <code>connection = cf.createConnection();</code>
        </pre>

        <li>Create a JMS Session</li>
        <pre class="prettyprint">
           <code>Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);</code>
        </pre>

        <li>Create a JMS MessageProducer</li>
        <pre class="prettyprint">
          <code>MessageProducer producer = session.createProducer(queue);</code>
        </pre>

        <li>Create a JMS MessageConsumer</li>
        <pre class="prettyprint">
           <code>MessageConsumer consumer1 = session.createConsumer(queue);</code>
        </pre>
        
        <li>Start the connection</li>
        
        <pre class="prettyprint">
           <code>
     connection.start();
           </code>
        </pre>
           

        <li>Send 10 messages to the queue</li>
        <pre class="prettyprint">
           <code>
     final int numMessages = 10;
         
     for (int i = 0; i < numMessages; i++)
     {
        TextMessage message = session.createTextMessage("This is text message: " + i);

        producer.send(message);
     }           
           </code>
        </pre>
        
        <li>Create another JMS MessageConsumer on the same queue.</li>
        <pre class="prettyprint">
           <code>MessageConsumer consumer2 = session.createConsumer(queue);</code>
        </pre>
        
        <li>Consume three messages from consumer2</li>
        
        <pre class="prettyprint">
           <code>
   for (int i = 0; i < 3; i++)
   {         
      TextMessage message = (TextMessage)consumer2.receive(2000);
            
      System.out.println("Consumed message from consumer2: " + message.getText());
   }    
           </code>
        </pre>
        
        <li>Consume five messages from consumer1</li>
        
        <pre class="prettyprint">
           <code>
   for (int i = 0; i < 5; i++)
   {         
      TextMessage message = (TextMessage)consumer1.receive(2000);
            
      System.out.println("Consumed message from consumer1: " + message.getText());
   }    
           </code>
        </pre> 
               
        <li>Consume two more messages from consumer2</li>
        
        <pre class="prettyprint">
           <code>
   for (int i = 0; i < 2; i++)
   {         
      TextMessage message = (TextMessage)consumer1.receive(2000);
            
      System.out.println("Consumed message from consumer2: " + message.getText());
   }    
           </code>
        </pre>                
        

        <li>Be sure to close our resources!</li>

        <pre class="prettyprint">
           <code>
           finally
           {
              if (initialContext != null)
              {
                initialContext.close();
              }
              
              if (connection != null)
              {
                 connection.close();
              }
           }</code>
        </pre>
     </ol>

     <h2>More information</h2>
     
     <ul>
         <li>User Manual's <a href="../../../docs/user-manual/en/html_single/index.html#flow-control.consumer.window">Consumer Window-Based Flow Control chapter</a></li>
     </ul>

  </body>
</html>