<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>hornetq-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>hornetq-jms.xml</code>
file when deploying the connection factory:</p>
<pre class="prettyprint">
<code>
<connection-factory name="ConnectionFactory">
<connector-ref connector-name="netty-connector"/>
<entries>
<entry name="ConnectionFactory"/>
</entries>
<!-- We set the consumer window size to 0, which means messages are not buffered at all
on the client side -->
<consumer-window-size>0</consumer-window-size>
</connection-factory>
</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>