<!--
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.
-->
<html>
<head>
<title>ActiveMQ Artemis Management 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>Management Example</h1>
<p>This example shows how to manage ActiveMQ Artemis using JMS Messages to invoke management operations on the server.</a></p>
<p>To manage ActiveMQ Artemis using JMX, see the <a href="../jmx/readme.html">JMX</a> example.</p>
<h2>Example configuration</h2>
<p>ActiveMQ Artemis can be managed by sending JMS messages with specific properties to its <em>management</em> queue.</p>
</p>By default, the management name is called <code>activemq.management</code> but this can be configured in <a href="server0/broker.xml">broker.xml</a>
<pre class="prettyprint">
<code><management-address>activemq.management</management-address></code>
</pre>
<p>The management queue requires a "special" user permission <code>manage</code> to be able to receive management messages.
This is also configured in <a href="server0/broker.xml">broker.xml</a></p>
<pre class="prettyprint">
<code><security-setting match="activemq.management">
<permission type="manage" roles="guest" />
</security-setting></code>
</pre>
<h2>Example step-by-step</h2>
<p><em>To run the example, simply type <code>mvn verify -Pexample</code> from this directory</em></p>
<ol>
<li>First we need to get an initial context so we can look-up the JMS connection factory and destination objects from JNDI. This initial context will get its properties from <a href="server0/client-jndi.properties">client-jndi.properties</a></li>
<pre class="prettyprint">
<code>InitialContext initialContext = getContext(0);</code>
</pre>
<li>We look up the JMS queue object from JNDI</li>
<pre class="prettyprint">
<code>Queue queue = (Queue) initialContext.lookup("/queue/exampleQueue");</code>
</pre>
<li>We look up the JMS connection factory object from JNDI</li>
<pre class="prettyprint">
<code>ConnectionFactory cf = (ConnectionFactory) initialContext.lookup("/ConnectionFactory");</code>
</pre>
<li>We create a JMS connection</li>
<pre class="prettyprint">
<code>connection = cf.createConnection();</code>
</pre>
<li>We create a JMS session. The session is created as non transacted and will auto acknowledge messages.</li>
<pre class="prettyprint">
<code>Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);</code>
</pre>
<li>We create a JMS message producer on the session. This will be used to send the messages.</li>
<pre class="prettyprint">
<code>MessageProducer messageProducer = session.createProducer(topic);</code>
</pre>
<li>We create a JMS text message that we are going to send.</li>
<pre class="prettyprint">
<code>TextMessage message = session.createTextMessage("This is a text message");</code>
</pre>
<li>We send message to the queue</li>
<pre class="prettyprint">
<code>messageProducer.send(message);</code>
</pre>
<p><em>Now that we have a message in the queue, we will manage the queue by retrieving the number of messages in the queue
(i.e. 1) and by removing the message which has been sent in step 8.</em></p>
<li>We create the JMS management queue. This is a <em>special</em> queue which is not looked up from JNDI but instantiated directly</li>
<pre class="prettyprint">
<code>Queue managementQueue = new ActiveMQQueue("activemq.management", "activemq.management");</code>
</pre>
<li>We create a <code>QueueRequestor</code> to send messages to the management queue and receive replies (see <a href="../queue-requestor/readme.html">queue-requestor example</a>)</li>
<pre class="prettyprint">
<code>QueueRequestor requestor = new QueueRequestor(session, managementQueue);</code>
</pre>
<li>We start the connection to receive replies on the requestor</li>
<pre class="prettyprint">
<code>connection.start()</code>
</pre>
<li>We create a JMS message which will be used as a <em>management</em> message</li>
<pre class="prettyprint">
<code>Message m = session.createMessage();</code>
</pre>
<li>a <em>management</em> message has well-defined properties that ActiveMQ Artemis server needs to know to perform management operations.<br />
We use a helper class <code>JMSManagementHelper</code> to fill these properties:
<ul>
<li>The name of the resource to manage <code>jms.queue.exampleQueue</code>
(i.e. <code>jms.queue</code> followed by the name of the queue as defined in <a href="server0/activemq-jms.xml">activemq-jms.xml</a>)</li>
<li>In our case, the name of the attribute to retrieve <code>MessageCount</code></li>
</ul>
</li>
<pre class="prettyprint">
<code>JMSManagementHelper.putAttribute(m, "jms.queue.exampleQueue", "MessageCount");</code>
</pre>
<li>We send the <em>management</em> message using the requestor and wait for a reply</li>
<pre class="prettyprint">
<code>Message reply = requestor.request(m);</code>
</pre>
<li>We use a helper class <code>JMSManagementHelper</code> to retrieve the result from the reply message:
<pre class="prettyprint">
<code>int messageCount = (Integer)JMSManagementHelper.getResult(reply);
System.out.println(queue.getQueueName() + " contains " + messageCount + " messages");</code>
</pre>
<li>We create another JMS message to use as a management message</li>
<pre class="prettyprint">
<code>m = session.createMessage();</code>
</pre>
<li>This time, we fill the <em>management</em> message with properties to <em>invoke</em> a management operation on the queue
<ul>
<li>the name of the resource <code>jms.queue.exampleQueue</code></li>
<li>the name of the management operation <code>removeMessage</code></li>
<li>any parameters required to invoke the management operations (in our case, the JMS Message ID of the message sent in step 8)</li>
</ul>
</li>
<pre class="prettyprint">
<code>JMSManagementHelper.putOperationInvocation(m, "jms.queue.exampleQueue", "removeMessage", message.getJMSMessageID());</code>
</pre>
<li>Again, we use the requestor to send the management message and wait for a reply</li>
<pre class="prettyprint">
<code>reply = requestor.request(m);</code>
</pre>
<li>We use the helper class to check that the operation was successfully invoked on the server</li>
<pre class="prettyprint">
<code>boolean success = JMSManagementHelper.hasOperationSucceeded(reply);
System.out.println("operation invocation has succeeded: " + success);</code>
</pre>
<li>We use a helper class <code>JMSManagementHelper</code> to retrieve the result from the reply message:
(in our case, the <code>removeMessage</code> method returns a boolean)</li>
<pre class="prettyprint">
<code>boolean messageRemoved = (Boolean)JMSManagementHelper.getResult(reply);
System.out.println("message has been removed: " + messageRemoved);</code>
</pre>
<p><em>We will now consume the message from the queue but there will be none: the message sent at step 8 was removed by the management operation</em></p>
<li>We create a JMS message consumer on the queue</li>
<pre class="prettyprint">
<code>MessageConsumer messageConsumer = session.createConsumer(queue);</code>
</pre>
<li>We try to receive a message from the queue. Since there is none, the call will timeout after 5000ms and messageReceived will be null
</li>
<pre class="prettyprint">
<code>TextMessage messageReceived = (TextMessage) messageConsumer.receive(5000);
System.out.println("Received message: " + messageReceived);</code>
</pre>
<li>And finally, <b>always</b> remember to close your JMS connections and resources after use, in a <code>finally</code> block. Closing a JMS connection will automatically close all of its sessions, consumers, producer and browser objects</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#management.jms">Using Management Via JMS chapter</a></li>
</ul>
</body>
</html>