blob: 4b0b120c5b872c9262f08bb675397d48e4d2dd37 [file] [log] [blame]
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="generator" content="Asciidoctor 2.0.18">
<link rel="icon" type="image/png" href="images/favicon.png">
<title>Management</title>
<link rel="stylesheet" href="css/asciidoctor.css">
<link rel="stylesheet" href="css/font-awesome.css">
<link rel="stylesheet" href="css/rouge-github.css">
</head>
<body class="book toc2 toc-left">
<div id="header">
<h1>Management</h1>
<div id="toc" class="toc2">
<div id="toctitle"><a href="index.html">User Manual for 2.32.0</a></div>
<ul class="sectlevel1">
<li><a href="#the-management-api">1. The Management API</a>
<ul class="sectlevel2">
<li><a href="#server-management">1.1. Server Management</a></li>
<li><a href="#address-management">1.2. Address Management</a></li>
<li><a href="#queue-management">1.3. Queue Management</a></li>
<li><a href="#other-resources-management">1.4. Other Resources Management</a></li>
</ul>
</li>
<li><a href="#management-via-jmx">2. Management Via JMX</a>
<ul class="sectlevel2">
<li><a href="#configuring-jmx">2.1. Configuring JMX</a></li>
<li><a href="#example">2.2. Example</a></li>
<li><a href="#exposing-jmx-using-jolokia">2.3. Exposing JMX using Jolokia</a></li>
<li><a href="#jmx-and-the-web-console">2.4. JMX and the Web Console</a></li>
</ul>
</li>
<li><a href="#using-management-message-api">3. Using Management Message API</a>
<ul class="sectlevel2">
<li><a href="#configuring-management">3.1. Configuring Management</a></li>
<li><a href="#example-2">3.2. Example</a></li>
</ul>
</li>
<li><a href="#management-notifications">4. Management Notifications</a>
<ul class="sectlevel2">
<li><a href="#jmx-notifications">4.1. JMX Notifications</a></li>
<li><a href="#notification-messages">4.2. Notification Messages</a></li>
<li><a href="#example-3">4.3. Example</a></li>
<li><a href="#notification-types-and-headers">4.4. Notification Types and Headers</a></li>
</ul>
</li>
<li><a href="#message-counters">5. Message Counters</a>
<ul class="sectlevel2">
<li><a href="#configuring-message-counters">5.1. Configuring Message Counters</a></li>
<li><a href="#example-4">5.2. Example</a></li>
</ul>
</li>
</ul>
</div>
</div>
<div id="content">
<div id="preamble">
<div class="sectionbody">
<div class="paragraph">
<p>Apache ActiveMQ Artemis has an extensive <em>management API</em> that allows a user to modify a server configuration, create new resources (e.g. addresses and queues), inspect these resources (e.g. how many messages are currently held in a queue) and interact with it (e.g. to remove messages from a queue).
Apache ActiveMQ Artemis also allows clients to subscribe to management notifications.</p>
</div>
<div class="paragraph">
<p>There are numerous ways to access Apache ActiveMQ Artemis management API:</p>
</div>
<div class="ulist">
<ul>
<li>
<p>Using JMX&#8201;&#8212;&#8201;<em>JMX</em> is the standard way to manage Java applications</p>
</li>
<li>
<p>Using Jolokia&#8201;&#8212;&#8201;Jolokia exposes the JMX API of an application through an <em>HTTP interface</em></p>
</li>
<li>
<p>Using the Core Client&#8201;&#8212;&#8201;management operations are sent to Apache ActiveMQ Artemis server using <em>Core Client messages</em></p>
</li>
<li>
<p>Using any JMS Client&#8201;&#8212;&#8201;management operations are sent to Apache ActiveMQ Artemis server using <em>JMS Client messages</em></p>
</li>
<li>
<p>Web Console&#8201;&#8212;&#8201;a web application which provides a graphical interface to the management API.</p>
</li>
</ul>
</div>
<div class="paragraph">
<p>Although there are four different ways to manage Apache ActiveMQ Artemis, each API supports the same functionality.
If it is possible to manage a resource using JMX it is also possible to achieve the same result using Core messages.</p>
</div>
<div class="paragraph">
<p>Besides these four management interfaces, a <a href="management-console.html#management-console">Web Console</a> and a Command Line <em>management utility</em> are also available to administrators of ActiveMQ Artemis.</p>
</div>
<div class="paragraph">
<p>The choice depends on your requirements, your application settings, and your environment to decide which way suits you best.</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="the-management-api"><a class="anchor" href="#the-management-api"></a><a class="link" href="#the-management-api">1. The Management API</a></h2>
<div class="sectionbody">
<div class="paragraph">
<p>Regardless of the way you <em>invoke</em> management operations, the management API is the same.</p>
</div>
<div class="paragraph">
<p>For each <em>managed resource</em>, there exists a Java interface describing what operations can be invoked for this type of resource.</p>
</div>
<div class="paragraph">
<p>To learn about available <em>management operations</em>, see the Javadoc for these interfaces.
They are located in the <code>org.apache.activemq.artemis.api.core.management</code> package and they are named with the word <code>Control</code> at the end.</p>
</div>
<div class="sect2">
<h3 id="server-management"><a class="anchor" href="#server-management"></a><a class="link" href="#server-management">1.1. Server Management</a></h3>
<div class="paragraph">
<p>The <code>ActiveMQServerControl</code> interface is the entry point for broker management.</p>
</div>
<div class="ulist">
<ul>
<li>
<p>Listing, creating, deploying and destroying queues</p>
<div class="paragraph">
<p>A list of deployed queues can be retrieved using the <code>getQueueNames()</code> method.</p>
</div>
<div class="paragraph">
<p>Queues can be created or destroyed using the management operations <code>createQueue()</code> or <code>deployQueue()</code> or <code>destroyQueue()</code>.</p>
</div>
<div class="paragraph">
<p><code>createQueue</code> will fail if the queue already exists while <code>deployQueue</code> will do nothing.</p>
</div>
</li>
<li>
<p>Listing and closing remote connections</p>
<div class="paragraph">
<p>Client&#8217;s remote addresses can be retrieved using <code>listRemoteAddresses()</code>.
It is also possible to close the connections associated with a remote address using the <code>closeConnectionsForAddress()</code> method.</p>
</div>
<div class="paragraph">
<p>Alternatively, connection IDs can be listed using <code>listConnectionIDs()</code> and all the sessions for a given connection ID can be listed using <code>listSessions()</code>.</p>
</div>
</li>
<li>
<p>Transaction heuristic operations</p>
<div class="paragraph">
<p>In case of a server crash, when the server restarts, it possible that some transaction requires manual intervention.
The <code>listPreparedTransactions()</code> method lists the transactions which are in the prepared states (the transactions are represented as opaque Base64 Strings.) To commit or rollback a given prepared transaction, the <code>commitPreparedTransaction()</code> or <code>rollbackPreparedTransaction()</code> method can be used to resolve heuristic transactions.
Heuristically completed transactions can be listed using the <code>listHeuristicCommittedTransactions()</code> and <code>listHeuristicRolledBackTransactions</code> methods.</p>
</div>
</li>
<li>
<p>Enabling and resetting Message counters</p>
<div class="paragraph">
<p>Message counters can be enabled or disabled using the <code>enableMessageCounters()</code> or <code>disableMessageCounters()</code> method.
To reset message counters, it is possible to invoke <code>resetAllMessageCounters()</code> and <code>resetAllMessageCounterHistories()</code> methods.</p>
</div>
</li>
<li>
<p>Retrieving the server configuration and attributes</p>
<div class="paragraph">
<p>The <code>ActiveMQServerControl</code> exposes Apache ActiveMQ Artemis server configuration through all its attributes (e.g. <code>getVersion()</code> method to retrieve the server&#8217;s version, etc.)</p>
</div>
</li>
<li>
<p>Listing, creating and destroying Core bridges and diverts</p>
<div class="paragraph">
<p>A list of deployed core bridges (resp.
diverts) can be retrieved using the <code>getBridgeNames()</code> (resp.
<code>getDivertNames()</code>) method.</p>
</div>
<div class="paragraph">
<p>Core bridges (resp.
diverts) can be created or destroyed using the management operations <code>createBridge()</code> and <code>destroyBridge()</code> (resp.
<code>createDivert()</code> and <code>destroyDivert()</code>).</p>
</div>
<div class="paragraph">
<p>Diverts can be updated using the management operation <code>updateDivert()</code>.</p>
</div>
</li>
<li>
<p>It is possible to stop the server and force failover to occur with any currently attached clients.</p>
<div class="paragraph">
<p>To do this use the <code>forceFailover()</code> operation.</p>
</div>
<div class="admonitionblock note">
<table>
<tr>
<td class="icon">
<i class="fa icon-note" title="Note"></i>
</td>
<td class="content">
<div class="paragraph">
<p>Since this method actually stops the server you will probably receive some sort of error depending on which management service you use to call it.</p>
</div>
</td>
</tr>
</table>
</div>
</li>
</ul>
</div>
</div>
<div class="sect2">
<h3 id="address-management"><a class="anchor" href="#address-management"></a><a class="link" href="#address-management">1.2. Address Management</a></h3>
<div class="paragraph">
<p>Individual addresses can be managed using the <code>AddressControl</code> interface.</p>
</div>
<div class="ulist">
<ul>
<li>
<p>Modifying roles and permissions for an address</p>
<div class="paragraph">
<p>You can add or remove roles associated to a queue using the <code>addRole()</code> or <code>removeRole()</code> methods.
You can list all the roles associated to the queue with the <code>getRoles()</code> method</p>
</div>
</li>
<li>
<p>Pausing and resuming an Address</p>
<div class="paragraph">
<p>The <code>AddressControl</code> can pause and resume an address and all the queues that are bound to it.
Newly added queue will be paused too until the address is resumed.
Thus all messages sent to the address will be received but not delivered.
When it is resumed, delivering will occur again.</p>
</div>
</li>
<li>
<p>Blocking and un blocking an Address</p>
<div class="paragraph">
<p>The <code>AddressControl</code> can block and unblock an address.
A blocked address will not issue any more credit to existing producers.
New producers will not be granted any credit.
When the address is unblocked, credit granting will resume.
In this way, it is possible to drain all the queues associated with an address to quiesce a broker in a managed way.</p>
</div>
</li>
</ul>
</div>
</div>
<div class="sect2">
<h3 id="queue-management"><a class="anchor" href="#queue-management"></a><a class="link" href="#queue-management">1.3. Queue Management</a></h3>
<div class="paragraph">
<p>The bulk of the management API deals with queues.
The <code>QueueControl</code> interface defines the queue management operations.</p>
</div>
<div class="paragraph">
<p>Most of the management operations on queues take either a single message ID (e.g. to remove a single message) or a filter (e.g. to expire all messages with a given property.)</p>
</div>
<div class="admonitionblock note">
<table>
<tr>
<td class="icon">
<i class="fa icon-note" title="Note"></i>
</td>
<td class="content">
<div class="paragraph">
<p>Passing <code>null</code> or an empty string in the <code>filter</code> parameter means that the management operation will be performed on <em>all messages</em> in a queue.</p>
</div>
</td>
</tr>
</table>
</div>
<div class="ulist">
<ul>
<li>
<p>Expiring, sending to a dead letter address and moving messages</p>
<div class="paragraph">
<p>Messages can be expired from a queue by using the <code>expireMessages()</code> method.
If an expiry address is defined, messages will be sent to it, otherwise they are discarded.</p>
</div>
<div class="paragraph">
<p>Messages can also be sent to a dead letter address with the <code>sendMessagesToDeadLetterAddress()</code> method.
It returns the number of messages which are sent to the dead letter address.
If a dead letter address is not defined, message are removed from the queue and discarded.</p>
</div>
<div class="paragraph">
<p>Messages can also be moved from a queue to another queue by using the <code>moveMessages()</code> method.</p>
</div>
</li>
<li>
<p>Listing and removing messages</p>
<div class="paragraph">
<p>Messages can be listed from a queue by using the <code>listMessages()</code> method which returns an array of <code>Map</code>, one <code>Map</code> for each message.</p>
</div>
<div class="paragraph">
<p>Messages can also be removed from the queue by using the <code>removeMessages()</code> method which returns a <code>boolean</code> for the single message ID variant or the number of removed messages for the filter variant.
The <code>removeMessages()</code> method takes a <code>filter</code> argument to remove only filtered messages.
Setting the filter to an empty string will in effect remove all messages.</p>
</div>
</li>
<li>
<p>Counting messages</p>
<div class="paragraph">
<p>The number of messages in a queue is returned by the <code>getMessageCount()</code> method.
Alternatively, the <code>countMessages()</code> will return the number of messages in the queue which <em>match a given filter</em>.</p>
</div>
</li>
<li>
<p>Changing message priority</p>
<div class="paragraph">
<p>The message priority can be changed by using the <code>changeMessagesPriority()</code> method which returns a <code>boolean</code> for the single message ID variant or the number of updated messages for the filter variant.</p>
</div>
</li>
<li>
<p>Message counters</p>
<div class="paragraph">
<p>Message counters can be listed for a queue with the <code>listMessageCounter()</code> and <code>listMessageCounterHistory()</code> methods (see Message Counters section).
The message counters can also be reset for a single queue using the <code>resetMessageCounter()</code> method.</p>
</div>
</li>
<li>
<p>Retrieving the queue attributes</p>
<div class="paragraph">
<p>The <code>QueueControl</code> exposes queue settings through its attributes (e.g. <code>getFilter()</code> to retrieve the queue&#8217;s filter if it was created with one, <code>isDurable()</code> to know whether the queue is durable or not, etc.)</p>
</div>
</li>
<li>
<p>Pausing and resuming Queues</p>
<div class="paragraph">
<p>The <code>QueueControl</code> can pause and resume the underlying queue.
When a queue is paused, it will receive messages but will not deliver them.
When it&#8217;s resumed, it&#8217;ll begin delivering the queued messages, if any.</p>
</div>
</li>
<li>
<p>Disabling and Enabling Queues</p>
<div class="paragraph">
<p>The <code>QueueControl</code> can disable and enable the underlying queue.
When a queue is disabled, it will not longer have messages routed to it.
When it&#8217;s enabled, it&#8217;ll begin having messages routed to it again.</p>
</div>
<div class="paragraph">
<p>This is useful where you may need to disable message routing to a queue but wish to keep consumers active to investigate issues, without causing further message build up in the queue.</p>
</div>
</li>
</ul>
</div>
</div>
<div class="sect2">
<h3 id="other-resources-management"><a class="anchor" href="#other-resources-management"></a><a class="link" href="#other-resources-management">1.4. Other Resources Management</a></h3>
<div class="paragraph">
<p>Apache ActiveMQ Artemis allows to start and stop its remote resources (acceptors, diverts, bridges, etc.) so that a server can be taken off line for a given period of time without stopping it completely (e.g. if other management operations must be performed such as resolving heuristic transactions).
These resources are:</p>
</div>
<div class="ulist">
<ul>
<li>
<p>Acceptors</p>
<div class="paragraph">
<p>They can be started or stopped using the <code>start()</code> or.
<code>stop()</code> method on the <code>AcceptorControl</code> interface.
The acceptors parameters can be retrieved using the <code>AcceptorControl</code> attributes (see <a href="configuring-transports.html#configuring-the-transport">Understanding Acceptors</a>)</p>
</div>
</li>
<li>
<p>Diverts</p>
<div class="paragraph">
<p>They can be started or stopped using the <code>start()</code> or <code>stop()</code> method on the <code>DivertControl</code> interface.
Diverts parameters can be retrieved using the <code>DivertControl</code> attributes (see <a href="diverts.html#diverting-and-splitting-message-flows">Diverting and Splitting Message Flows)</a>)</p>
</div>
</li>
<li>
<p>Bridges</p>
<div class="paragraph">
<p>They can be started or stopped using the <code>start()</code> (resp.
<code>stop()</code>) method on the <code>BridgeControl</code> interface.
Bridges parameters can be retrieved using the <code>BridgeControl</code> attributes (see <a href="core-bridges.html#core-bridges">Core bridges</a>)</p>
</div>
</li>
<li>
<p>Broadcast groups</p>
<div class="paragraph">
<p>They can be started or stopped using the <code>start()</code> or <code>stop()</code> method on the <code>BroadcastGroupControl</code> interface.
Broadcast groups parameters can be retrieved using the <code>BroadcastGroupControl</code> attributes (see <a href="clusters.html#clusters">Clusters</a>)</p>
</div>
</li>
<li>
<p>Cluster connections</p>
<div class="paragraph">
<p>They can be started or stopped using the <code>start()</code> or <code>stop()</code> method on the <code>ClusterConnectionControl</code> interface.
Cluster connections parameters can be retrieved using the <code>ClusterConnectionControl</code> attributes (see <a href="clusters.html#clusters">Clusters</a>)</p>
</div>
</li>
</ul>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="management-via-jmx"><a class="anchor" href="#management-via-jmx"></a><a class="link" href="#management-via-jmx">2. Management Via JMX</a></h2>
<div class="sectionbody">
<div class="paragraph">
<p>Apache ActiveMQ Artemis can be managed using <a href="http://www.oracle.com/technetwork/java/javase/tech/javamanagement-140525.html">JMX</a>.</p>
</div>
<div class="paragraph">
<p>The management API is exposed by Apache ActiveMQ Artemis using MBeans.
By default, Apache ActiveMQ Artemis registers its resources with the domain <code>org.apache.activemq.artemis</code>.
For example, the <code>ObjectName</code> to manage the anycast queue <code>exampleQueue</code> on the address <code>exampleAddress</code> is:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="nowrap">org.apache.activemq.artemis:broker=&lt;brokerName&gt;,component=addresses,address="exampleAddress",subcomponent=queues,routing-type="anycast",queue="exampleQueue"</pre>
</div>
</div>
<div class="paragraph">
<p>and the MBean is:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="nowrap">org.apache.activemq.artemis.api.core.management.QueueControl</pre>
</div>
</div>
<div class="paragraph">
<p>The MBean&#8217;s <code>ObjectName</code> is built using the helper class <code>org.apache.activemq.artemis.api.core.management.ObjectNameBuilder</code>.
Example usage of the <code>ObjectNameBuilder</code> to obtain <code>ActiveMQServerControl</code>'s name:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight nowrap"><code data-lang="java"><span class="n">brokerName</span> <span class="o">=</span> <span class="s">"0.0.0.0"</span><span class="o">;</span> <span class="c1">// configured e.g. in broker.xml &lt;broker-name&gt; element</span>
<span class="n">objectNameBuilder</span> <span class="o">=</span> <span class="nc">ObjectNameBuilder</span><span class="o">.</span><span class="na">create</span><span class="o">(</span><span class="nc">ArtemisResolver</span><span class="o">.</span><span class="na">DEFAULT_DOMAIN</span><span class="o">,</span> <span class="n">brokerName</span><span class="o">,</span> <span class="kc">true</span><span class="o">);</span>
<span class="n">serverObjectName</span> <span class="o">=</span> <span class="n">objectNameBuilder</span><span class="o">.</span><span class="na">getActiveMQServerObjectName</span><span class="o">()</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>Managing Apache ActiveMQ Artemis using JMX is identical to management of any Java Applications using JMX.
It can be done by reflection or by creating proxies of the MBeans.</p>
</div>
<div class="sect2">
<h3 id="configuring-jmx"><a class="anchor" href="#configuring-jmx"></a><a class="link" href="#configuring-jmx">2.1. Configuring JMX</a></h3>
<div class="paragraph">
<p>By default, JMX is enabled to manage Apache ActiveMQ Artemis.
It can be disabled by setting <code>jmx-management-enabled</code> to <code>false</code> in <code>broker.xml</code>:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight nowrap"><code data-lang="xml"><span class="nt">&lt;jmx-management-enabled&gt;</span>false<span class="nt">&lt;/jmx-management-enabled&gt;</span></code></pre>
</div>
</div>
<div class="sect3">
<h4 id="role-based-authorisation-for-jmx"><a class="anchor" href="#role-based-authorisation-for-jmx"></a><a class="link" href="#role-based-authorisation-for-jmx">2.1.1. Role Based Authorisation for JMX</a></h4>
<div class="paragraph">
<p>Although by default Artemis uses the Java Virtual Machine&#8217;s <code>Platform MBeanServer</code> this is guarded using role based authorisation that leverages the broker&#8217;s JAAS plugin support.
This is configured via the <code>authorisation</code> element in the <code>management.xml</code> configuration file and can be used to restrict access to attributes and methods on MBeans.</p>
</div>
<div class="paragraph">
<p>There are 3 elements within the <code>authorisation</code> element, <code>allowlist</code>, <code>default-access</code> and <code>role-access</code>.
Lets discuss each in turn.</p>
</div>
<div class="paragraph">
<p>Allowlist contains a list of MBeans that will bypass the authorisation, this is typically used for any MBeans that are needed by the console to run etc.
The default configuration is:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight nowrap"><code data-lang="xml"><span class="nt">&lt;allowlist&gt;</span>
<span class="nt">&lt;entry</span> <span class="na">domain=</span><span class="s">"hawtio"</span><span class="nt">/&gt;</span>
<span class="nt">&lt;/allowlist&gt;</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>This means that any MBean with the domain <code>hawtio</code> will be allowed access without authorisation.
for instance <code>hawtio:plugin=artemis</code>.
You can also use wildcards for the MBean properties so the following would also match.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight nowrap"><code data-lang="xml"><span class="nt">&lt;allowlist&gt;</span>
<span class="nt">&lt;entry</span> <span class="na">domain=</span><span class="s">"hawtio"</span> <span class="na">key=</span><span class="s">"type=*"</span><span class="nt">/&gt;</span>
<span class="nt">&lt;/allowlist&gt;</span></code></pre>
</div>
</div>
<div class="admonitionblock note">
<table>
<tr>
<td class="icon">
<i class="fa icon-note" title="Note"></i>
</td>
<td class="content">
<div class="paragraph">
<p>The <code>allowlist</code> element has replaced the <code>whitelist</code> element which is now deprecated</p>
</div>
</td>
</tr>
</table>
</div>
<div class="paragraph">
<p>The <code>role-access</code> defines how roles are mapped to particular MBeans and its attributes and methods.
The default configuration looks like:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight nowrap"><code data-lang="xml"><span class="nt">&lt;role-access&gt;</span>
<span class="nt">&lt;match</span> <span class="na">domain=</span><span class="s">"org.apache.activemq.artemis"</span><span class="nt">&gt;</span>
<span class="nt">&lt;access</span> <span class="na">method=</span><span class="s">"list*"</span> <span class="na">roles=</span><span class="s">"view,update,amq"</span><span class="nt">/&gt;</span>
<span class="nt">&lt;access</span> <span class="na">method=</span><span class="s">"get*"</span> <span class="na">roles=</span><span class="s">"view,update,amq"</span><span class="nt">/&gt;</span>
<span class="nt">&lt;access</span> <span class="na">method=</span><span class="s">"is*"</span> <span class="na">roles=</span><span class="s">"view,update,amq"</span><span class="nt">/&gt;</span>
<span class="nt">&lt;access</span> <span class="na">method=</span><span class="s">"set*"</span> <span class="na">roles=</span><span class="s">"update,amq"</span><span class="nt">/&gt;</span>
<span class="nt">&lt;access</span> <span class="na">method=</span><span class="s">"*"</span> <span class="na">roles=</span><span class="s">"amq"</span><span class="nt">/&gt;</span>
<span class="nt">&lt;/match&gt;</span>
<span class="nt">&lt;/role-access&gt;</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>This contains 1 match and will be applied to any MBean that has the domain <code>org.apache.activemq.artemis</code>.
Any access to any MBeans that have this domain are controlled by the <code>access</code> elements which contain a method and a set of roles.
The method being invoked will be used to pick the closest matching method and the roles for this will be applied for access.
For instance if you try the invoke a method called <code>listMessages</code> on an MBean with the <code>org.apache.activemq.artemis</code> domain then this would match the <code>access</code> with the method of <code>list*</code>.
You could also explicitly configure this by using the full method name, like so:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight nowrap"><code data-lang="xml"><span class="nt">&lt;access</span> <span class="na">method=</span><span class="s">"listMessages"</span> <span class="na">roles=</span><span class="s">"view,update,amq"</span><span class="nt">/&gt;</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>You can also match specific MBeans within a domain by adding a key attribute that is used to match one of the properties on the MBean, like:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight nowrap"><code data-lang="xml"><span class="nt">&lt;match</span> <span class="na">domain=</span><span class="s">"org.apache.activemq.artemis"</span> <span class="na">key=</span><span class="s">"subcomponent=queues"</span><span class="nt">&gt;</span>
<span class="nt">&lt;access</span> <span class="na">method=</span><span class="s">"list*"</span> <span class="na">roles=</span><span class="s">"view,update,amq"</span><span class="nt">/&gt;</span>
<span class="nt">&lt;access</span> <span class="na">method=</span><span class="s">"get*"</span> <span class="na">roles=</span><span class="s">"view,update,amq"</span><span class="nt">/&gt;</span>
<span class="nt">&lt;access</span> <span class="na">method=</span><span class="s">"is*"</span> <span class="na">roles=</span><span class="s">"view,update,amq"</span><span class="nt">/&gt;</span>
<span class="nt">&lt;access</span> <span class="na">method=</span><span class="s">"set*"</span> <span class="na">roles=</span><span class="s">"update,amq"</span><span class="nt">/&gt;</span>
<span class="nt">&lt;access</span> <span class="na">method=</span><span class="s">"*"</span> <span class="na">roles=</span><span class="s">"amq"</span><span class="nt">/&gt;</span>
<span class="nt">&lt;/match&gt;</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>You could also match a specific queue for instance:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="nowrap">org.apache.activemq.artemis:broker=&lt;brokerName&gt;,component=addresses,address="exampleAddress",subcomponent=queues,routing-type="anycast",queue="exampleQueue"</pre>
</div>
</div>
<div class="paragraph">
<p>by configuring:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight nowrap"><code data-lang="xml"><span class="nt">&lt;match</span> <span class="na">domain=</span><span class="s">"org.apache.activemq.artemis"</span> <span class="na">key=</span><span class="s">"queue=exampleQueue"</span><span class="nt">&gt;</span>
<span class="nt">&lt;access</span> <span class="na">method=</span><span class="s">"list*"</span> <span class="na">roles=</span><span class="s">"view,update,amq"</span><span class="nt">/&gt;</span>
<span class="nt">&lt;access</span> <span class="na">method=</span><span class="s">"get*"</span> <span class="na">roles=</span><span class="s">"view,update,amq"</span><span class="nt">/&gt;</span>
<span class="nt">&lt;access</span> <span class="na">method=</span><span class="s">"is*"</span> <span class="na">roles=</span><span class="s">"view,update,amq"</span><span class="nt">/&gt;</span>
<span class="nt">&lt;access</span> <span class="na">method=</span><span class="s">"set*"</span> <span class="na">roles=</span><span class="s">"update,amq"</span><span class="nt">/&gt;</span>
<span class="nt">&lt;access</span> <span class="na">method=</span><span class="s">"*"</span> <span class="na">roles=</span><span class="s">"amq"</span><span class="nt">/&gt;</span>
<span class="nt">&lt;/match&gt;</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>You can also use wildcards for the MBean properties so the following would also match, allowing prefix match for the MBean properties.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight nowrap"><code data-lang="xml"><span class="nt">&lt;match</span> <span class="na">domain=</span><span class="s">"org.apache.activemq.artemis"</span> <span class="na">key=</span><span class="s">"queue=example*"</span><span class="nt">&gt;</span>
<span class="nt">&lt;access</span> <span class="na">method=</span><span class="s">"list*"</span> <span class="na">roles=</span><span class="s">"view,update,amq"</span><span class="nt">/&gt;</span>
<span class="nt">&lt;access</span> <span class="na">method=</span><span class="s">"get*"</span> <span class="na">roles=</span><span class="s">"view,update,amq"</span><span class="nt">/&gt;</span>
<span class="nt">&lt;access</span> <span class="na">method=</span><span class="s">"is*"</span> <span class="na">roles=</span><span class="s">"view,update,amq"</span><span class="nt">/&gt;</span>
<span class="nt">&lt;access</span> <span class="na">method=</span><span class="s">"set*"</span> <span class="na">roles=</span><span class="s">"update,amq"</span><span class="nt">/&gt;</span>
<span class="nt">&lt;access</span> <span class="na">method=</span><span class="s">"*"</span> <span class="na">roles=</span><span class="s">"amq"</span><span class="nt">/&gt;</span>
<span class="nt">&lt;/match&gt;</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>In case of multiple matches, the exact matches have higher priority than the wildcard matches and the longer wildcard matches have higher priority than the shorter wildcard matches.</p>
</div>
<div class="paragraph">
<p>Access to JMX MBean attributes are converted to method calls so these are controlled via the <code>set*</code>, <code>get*</code> and <code>is*</code>.
The <code>*</code> access is the catch all for everything other method that isn&#8217;t specifically matched.</p>
</div>
<div class="paragraph">
<p>The <code>default-access</code> element is basically the catch all for every method call that isn&#8217;t handled via the <code>role-access</code> configuration.
This has the same semantics as a <code>match</code> element.</p>
</div>
</div>
<div class="sect3">
<h4 id="local-jmx-access-with-jconsole"><a class="anchor" href="#local-jmx-access-with-jconsole"></a><a class="link" href="#local-jmx-access-with-jconsole">2.1.2. Local JMX Access with JConsole</a></h4>
<div class="paragraph">
<p>Due to the authorisation which is enabled by default Apache ActiveMQ Artemis can <em>not</em> be managed locally using JConsole when connecting as a <em>local process</em>.
This is because JConsole does not pass any authentication information when connecting this way which means the user cannot therefore be authorised for any management operations.
In order to use JConsole the user will either have to disable authorisation by completely removing the <code>authorisation</code> element from <code>management.xml</code> or by enabling remote access and providing the proper username and password credentials (discussed next).</p>
</div>
</div>
<div class="sect3">
<h4 id="remote-jmx-access"><a class="anchor" href="#remote-jmx-access"></a><a class="link" href="#remote-jmx-access">2.1.3. Remote JMX Access</a></h4>
<div class="paragraph">
<p>By default remote JMX access to Artemis is disabled for security reasons.</p>
</div>
<div class="paragraph">
<p>Artemis has a JMX agent which allows access to JMX MBeans remotely.
This is configured via the <code>connector</code> element in the <code>management.xml</code> configuration file.
To enable this you simply add the following xml:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight nowrap"><code data-lang="xml"><span class="nt">&lt;connector</span> <span class="na">connector-port=</span><span class="s">"1099"</span><span class="nt">/&gt;</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>This exposes the agent remotely on the port <code>1099</code>.
If you were connecting via JConsole you would connect as a remote process using the service url:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="nowrap">service:jmx:rmi:///jndi/rmi://localhost:1099/jmxrmi</pre>
</div>
</div>
<div class="paragraph">
<p>You&#8217;d be able to supply an appropriate user name and password in this case as well.</p>
</div>
<div class="paragraph">
<p>You can also configure the connector using the following:</p>
</div>
<div class="dlist">
<dl>
<dt class="hdlist1">connector-host</dt>
<dd>
<p>The host to expose the agent on.</p>
</dd>
<dt class="hdlist1">connector-port</dt>
<dd>
<p>The port to expose the agent on.</p>
</dd>
<dt class="hdlist1">rmi-registry-port</dt>
<dd>
<p>The port that the RMI registry binds to.
If not set, the port is always random.
Set to avoid problems with remote JMX connections tunnelled through firewall.</p>
</dd>
<dt class="hdlist1">jmx-realm</dt>
<dd>
<p>The jmx realm to use for authentication, defaults to <code>activemq</code> to match the JAAS configuration.</p>
</dd>
<dt class="hdlist1">object-name</dt>
<dd>
<p>The object name to expose the remote connector on;
default is <code>connector:name=rmi</code>.</p>
</dd>
<dt class="hdlist1">secured</dt>
<dd>
<p>Whether the connector is secured using SSL.</p>
</dd>
<dt class="hdlist1">key-store-path</dt>
<dd>
<p>The location of the keystore.</p>
</dd>
<dt class="hdlist1">key-store-password</dt>
<dd>
<p>The keystore password.
This can be <a href="masking-passwords.html#masking-passwords">masked</a>.</p>
</dd>
<dt class="hdlist1">key-store-provider</dt>
<dd>
<p>The provider;
<code>JKS</code> by default.</p>
</dd>
<dt class="hdlist1">trust-store-path</dt>
<dd>
<p>The location of the truststore.</p>
</dd>
<dt class="hdlist1">trust-store-password</dt>
<dd>
<p>The trustore password.
This can be <a href="masking-passwords.html#masking-passwords">masked</a>.</p>
</dd>
<dt class="hdlist1">trust-store-provider</dt>
<dd>
<p>The provider;
<code>JKS</code> by default.</p>
</dd>
<dt class="hdlist1">password-codec</dt>
<dd>
<p>The fully qualified class name of the password codec to use.
See the <a href="masking-passwords.html#masking-passwords">password masking</a> documentation for more details on how this works.</p>
</dd>
</dl>
</div>
<div class="admonitionblock note">
<table>
<tr>
<td class="icon">
<i class="fa icon-note" title="Note"></i>
</td>
<td class="content">
<div class="paragraph">
<p>It is important to note that the rmi registry will pick an ip address to bind to, If you have a multi IP addresses/NICs present on the system then you can choose the ip address to use by adding the following to artemis.profile <code>-Djava.rmi.server.hostname=localhost</code></p>
</div>
</td>
</tr>
</table>
</div>
<div class="admonitionblock note">
<table>
<tr>
<td class="icon">
<i class="fa icon-note" title="Note"></i>
</td>
<td class="content">
<div class="paragraph">
<p>Remote connections using the default JVM Agent not enabled by default as Artemis exposes the MBean Server via its own configuration.
This is so Artemis can leverage the JAAS authentication layer via JMX.
If you want to expose this then you will need to disable both the connector and the authorisation by removing them from the <code>management.xml</code> configuration.
Please refer to <a href="https://docs.oracle.com/javase/8/docs/technotes/guides/management/agent.html">Java Management guide</a> to configure the server for remote management (system properties must be set in <code>artemis.profile</code>).</p>
</div>
</td>
</tr>
</table>
</div>
<div class="paragraph">
<p>By default, Apache ActiveMQ Artemis server uses the JMX domain "org.apache.activemq.artemis".
To manage several Apache ActiveMQ Artemis servers from the <em>same</em> MBeanServer, the JMX domain can be configured for each individual Apache ActiveMQ Artemis server by setting <code>jmx-domain</code> in <code>broker.xml</code>:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight nowrap"><code data-lang="xml"><span class="c">&lt;!-- use a specific JMX domain for ActiveMQ Artemis MBeans --&gt;</span>
<span class="nt">&lt;jmx-domain&gt;</span>my.org.apache.activemq<span class="nt">&lt;/jmx-domain&gt;</span></code></pre>
</div>
</div>
</div>
</div>
<div class="sect2">
<h3 id="example"><a class="anchor" href="#example"></a><a class="link" href="#example">2.2. Example</a></h3>
<div class="paragraph">
<p>See the <a href="examples.html#jmx-management">JMX Management Example</a> which shows how to use a remote connection to JMX and MBean proxies to manage Apache ActiveMQ Artemis.</p>
</div>
</div>
<div class="sect2">
<h3 id="exposing-jmx-using-jolokia"><a class="anchor" href="#exposing-jmx-using-jolokia"></a><a class="link" href="#exposing-jmx-using-jolokia">2.3. Exposing JMX using Jolokia</a></h3>
<div class="paragraph">
<p>The default Broker configuration ships with the <a href="https://jolokia.org">Jolokia</a> HTTP agent deployed as a web application.
Jolokia is a remote JMX-over-HTTP bridge that exposes MBeans.
For a full guide as to how to use it refer to <a href="https://jolokia.org/documentation.html">Jolokia Documentation</a>, however a simple example to query the broker&#8217;s version would be to use a <code>curl</code> command like this:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight nowrap"><code data-lang="console"><span class="gp">$</span><span class="w"> </span>curl <span class="nt">-v</span> <span class="nt">-H</span> <span class="s2">"Origin: http://localhost"</span> <span class="nt">-u</span> myUser:myPass http://localhost:8161/console/jolokia/read/org.apache.activemq.artemis:broker<span class="o">=</span><span class="se">\"</span>0.0.0.0<span class="se">\"</span>/Active</code></pre>
</div>
</div>
<div class="paragraph">
<p>Or you could send a JSON formatted request instead of using the URL</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight nowrap"><code data-lang="console"><span class="gp">$</span><span class="w"> </span>curl <span class="nt">-v</span> <span class="nt">-H</span> <span class="s2">"Origin: http://localhost"</span> <span class="nt">-u</span> myUser:myPass <span class="nt">--header</span> <span class="s2">"Content-type: application/json"</span> <span class="nt">--request</span> POST <span class="nt">--data</span> <span class="s1">'{"attribute": "Active", "mbean": "org.apache.activemq.artemis:broker=\"0.0.0.0\"", "type": "read"}'</span> http://localhost:8161/console/jolokia</code></pre>
</div>
</div>
<div class="paragraph">
<p>By default it&#8217;s necessary to pass the <code>Origin</code> header due to the CORS checking which is configured in <code>etc/jolokia-access.xml</code>.</p>
</div>
<div class="paragraph">
<p>Such a <code>curl</code> command would give you back something like the following (after formatting):</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight nowrap"><code data-lang="json"><span class="p">{</span><span class="w">
</span><span class="nl">"request"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w">
</span><span class="nl">"mbean"</span><span class="p">:</span><span class="w"> </span><span class="s2">"org.apache.activemq.artemis:broker=</span><span class="se">\"</span><span class="s2">0.0.0.0</span><span class="se">\"</span><span class="s2">"</span><span class="p">,</span><span class="w">
</span><span class="nl">"attribute"</span><span class="p">:</span><span class="w"> </span><span class="s2">"Version"</span><span class="p">,</span><span class="w">
</span><span class="nl">"type"</span><span class="p">:</span><span class="w"> </span><span class="s2">"read"</span><span class="w">
</span><span class="p">},</span><span class="w">
</span><span class="nl">"value"</span><span class="p">:</span><span class="w"> </span><span class="s2">"2.24.0"</span><span class="p">,</span><span class="w">
</span><span class="nl">"timestamp"</span><span class="p">:</span><span class="w"> </span><span class="mi">1663086398</span><span class="p">,</span><span class="w">
</span><span class="nl">"status"</span><span class="p">:</span><span class="w"> </span><span class="mi">200</span><span class="w">
</span><span class="p">}</span></code></pre>
</div>
</div>
</div>
<div class="sect2">
<h3 id="jmx-and-the-web-console"><a class="anchor" href="#jmx-and-the-web-console"></a><a class="link" href="#jmx-and-the-web-console">2.4. JMX and the Web Console</a></h3>
<div class="paragraph">
<p>The web console that ships with Artemis uses Jolokia under the covers which in turn uses JMX.
This will use the authentication configuration in the <code>management.xml</code> file as described in the previous section.
This means that when MBeans are accessed via the console the credentials used to log into the console and the roles associated with them.
By default access to the console is only allow via users with the <code>amq</code> role.
This is configured in the <code>artemis.profile</code> via the system property <code>-Dhawtio.role=amq</code>.
You can configure multiple roles by changing this to <code>-Dhawtio.roles=amq,view,update</code>.</p>
</div>
<div class="paragraph">
<p>If a user doesn&#8217;t have the correct role to invoke a specific operation then this will display an authorisation exception in the console.</p>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="using-management-message-api"><a class="anchor" href="#using-management-message-api"></a><a class="link" href="#using-management-message-api">3. Using Management Message API</a></h2>
<div class="sectionbody">
<div class="paragraph">
<p>The management message API in ActiveMQ Artemis is accessed by sending Core Client messages to a special address, the <em>management address</em>.</p>
</div>
<div class="paragraph">
<p><em>Management messages</em> are regular Core Client messages with well-known properties that the server needs to understand to interact with the management API:</p>
</div>
<div class="ulist">
<ul>
<li>
<p>The name of the managed resource</p>
</li>
<li>
<p>The name of the management operation</p>
</li>
<li>
<p>The parameters of the management operation</p>
</li>
</ul>
</div>
<div class="paragraph">
<p>When such a management message is sent to the management address, Apache ActiveMQ Artemis server will handle it, extract the information, invoke the operation on the managed resources and send a <em>management reply</em> to the management message&#8217;s reply-to address (specified by <code>ClientMessageImpl.REPLYTO_HEADER_NAME</code>).</p>
</div>
<div class="paragraph">
<p>A <code>ClientConsumer</code> can be used to consume the management reply and retrieve the result of the operation (if any) stored in the reply&#8217;s body.
For portability, results are returned as a <a href="https://json.org">JSON</a> String rather than Java Serialization (the <code>org.apache.activemq.artemis.api.core.management.ManagementHelper</code> can be used to convert the JSON string to Java objects).</p>
</div>
<div class="paragraph">
<p>These steps can be simplified to make it easier to invoke management operations using Core messages:</p>
</div>
<div class="olist arabic">
<ol class="arabic">
<li>
<p>Create a <code>ClientRequestor</code> to send messages to the management address and receive replies</p>
</li>
<li>
<p>Create a <code>ClientMessage</code></p>
</li>
<li>
<p>Use the helper class <code>org.apache.activemq.artemis.api.core.management.ManagementHelper</code> to fill the message with the management properties</p>
</li>
<li>
<p>Send the message using the <code>ClientRequestor</code></p>
</li>
<li>
<p>Use the helper class <code>org.apache.activemq.artemis.api.core.management.ManagementHelper</code> to retrieve the operation result from the management reply.</p>
</li>
</ol>
</div>
<div class="paragraph">
<p>For example, to find out the number of messages in the queue <code>exampleQueue</code>:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight nowrap"><code data-lang="java"><span class="nc">ClientSession</span> <span class="n">session</span> <span class="o">=</span> <span class="o">...</span>
<span class="nc">ClientRequestor</span> <span class="n">requestor</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">ClientRequestor</span><span class="o">(</span><span class="n">session</span><span class="o">,</span> <span class="s">"activemq.management"</span><span class="o">);</span>
<span class="nc">ClientMessage</span> <span class="n">message</span> <span class="o">=</span> <span class="n">session</span><span class="o">.</span><span class="na">createMessage</span><span class="o">(</span><span class="kc">false</span><span class="o">);</span>
<span class="nc">ManagementHelper</span><span class="o">.</span><span class="na">putAttribute</span><span class="o">(</span><span class="n">message</span><span class="o">,</span> <span class="s">"queue.exampleQueue"</span><span class="o">,</span> <span class="s">"messageCount"</span><span class="o">);</span>
<span class="n">session</span><span class="o">.</span><span class="na">start</span><span class="o">();</span>
<span class="nc">ClientMessage</span> <span class="n">reply</span> <span class="o">=</span> <span class="n">requestor</span><span class="o">.</span><span class="na">request</span><span class="o">(</span><span class="n">m</span><span class="o">);</span>
<span class="kt">int</span> <span class="n">count</span> <span class="o">=</span> <span class="o">(</span><span class="nc">Integer</span><span class="o">)</span> <span class="nc">ManagementHelper</span><span class="o">.</span><span class="na">getResult</span><span class="o">(</span><span class="n">reply</span><span class="o">);</span>
<span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="s">"There are "</span> <span class="o">+</span> <span class="n">count</span> <span class="o">+</span> <span class="s">" messages in exampleQueue"</span><span class="o">);</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>Management operation name and parameters must conform to the Java interfaces defined in the <code>management</code> packages.</p>
</div>
<div class="paragraph">
<p>Names of the resources are built using the helper class <code>org.apache.activemq.artemis.api.core.management.ResourceNames</code> and are straightforward (e.g. <code>queue.exampleQueue</code> for <code>QueueControl</code> of the Queue <code>exampleQueue</code>, or <code>broker</code> for the <code>ActiveMQServerControl</code>).</p>
</div>
<div class="admonitionblock note">
<table>
<tr>
<td class="icon">
<i class="fa icon-note" title="Note"></i>
</td>
<td class="content">
<div class="paragraph">
<p>The <code>ManagementHelper</code> class can be used only with Core JMS messages.
When called with a message from a different JMS library, an exception will be thrown.</p>
</div>
</td>
</tr>
</table>
</div>
<div class="sect2">
<h3 id="configuring-management"><a class="anchor" href="#configuring-management"></a><a class="link" href="#configuring-management">3.1. Configuring Management</a></h3>
<div class="paragraph">
<p>The management address to send management messages is configured in <code>broker.xml</code>:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight nowrap"><code data-lang="xml"><span class="nt">&lt;management-address&gt;</span>activemq.management<span class="nt">&lt;/management-address&gt;</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>By default, the address is <code>activemq.management</code>.</p>
</div>
<div class="paragraph">
<p>The management address requires a <em>special</em> user permission <code>manage</code> to be able to receive and handle management messages.
This is also configured in broker.xml:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight nowrap"><code data-lang="xml"><span class="c">&lt;!-- users with the admin role will be allowed to manage --&gt;</span>
<span class="c">&lt;!-- Apache ActiveMQ Artemis using management messages --&gt;</span>
<span class="nt">&lt;security-setting</span> <span class="na">match=</span><span class="s">"activemq.management"</span><span class="nt">&gt;</span>
<span class="nt">&lt;permission</span> <span class="na">type=</span><span class="s">"manage"</span> <span class="na">roles=</span><span class="s">"admin"</span> <span class="nt">/&gt;</span>
<span class="nt">&lt;/security-setting&gt;</span></code></pre>
</div>
</div>
</div>
<div class="sect2">
<h3 id="example-2"><a class="anchor" href="#example-2"></a><a class="link" href="#example-2">3.2. Example</a></h3>
<div class="paragraph">
<p>See the <a href="examples.html#management">Management Example</a> which shows how to use JMS messages to manage the Apache ActiveMQ Artemis server.</p>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="management-notifications"><a class="anchor" href="#management-notifications"></a><a class="link" href="#management-notifications">4. Management Notifications</a></h2>
<div class="sectionbody">
<div class="paragraph">
<p>Apache ActiveMQ Artemis emits <em>notifications</em> to inform listeners of potentially interesting events (creation of new resources, security violation, etc.).</p>
</div>
<div class="paragraph">
<p>These notifications can be received by two different ways:</p>
</div>
<div class="ulist">
<ul>
<li>
<p>JMX notifications</p>
</li>
<li>
<p>Notification messages</p>
</li>
</ul>
</div>
<div class="sect2">
<h3 id="jmx-notifications"><a class="anchor" href="#jmx-notifications"></a><a class="link" href="#jmx-notifications">4.1. JMX Notifications</a></h3>
<div class="paragraph">
<p>If JMX is enabled (see Configuring JMX section), JMX notifications can be received by subscribing to <code>org.apache.activemq.artemis:type=Broker,brokerName=&lt;broker name&gt;,module=Core,serviceType=Server</code> for notifications on resources.</p>
</div>
</div>
<div class="sect2">
<h3 id="notification-messages"><a class="anchor" href="#notification-messages"></a><a class="link" href="#notification-messages">4.2. Notification Messages</a></h3>
<div class="paragraph">
<p>Apache ActiveMQ Artemis defines a special <em>management notification address</em>.
Queues can be bound to this address so that clients will receive management notifications as messages.</p>
</div>
<div class="paragraph">
<p>A client which wants to receive management notifications must create a queue bound to the management notification address.
It can then receive the notifications from its queue.</p>
</div>
<div class="paragraph">
<p>Notifications messages are regular messages with additional properties corresponding to the notification (its type, when it occurred, the resources which were concerned, etc.).</p>
</div>
<div class="paragraph">
<p>Since notifications are regular messages, it is possible to use message selectors to filter out notifications and receives only a subset of all the notifications emitted by the server.</p>
</div>
<div class="sect3">
<h4 id="configuring-the-management-notification-address"><a class="anchor" href="#configuring-the-management-notification-address"></a><a class="link" href="#configuring-the-management-notification-address">4.2.1. Configuring The Management Notification Address</a></h4>
<div class="paragraph">
<p>The management notification address to receive management notifications is configured in <code>broker.xml</code>:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight nowrap"><code data-lang="xml"><span class="nt">&lt;management-notification-address&gt;</span>activemq.notifications<span class="nt">&lt;/management-notification-address&gt;</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>By default, the address is <code>activemq.notifications</code>.</p>
</div>
</div>
<div class="sect3">
<h4 id="suppressing-session-notifications"><a class="anchor" href="#suppressing-session-notifications"></a><a class="link" href="#suppressing-session-notifications">4.2.2. Suppressing Session Notifications</a></h4>
<div class="paragraph">
<p>Some messaging patterns can generate a lot of <code>SESSION_CREATED</code> and <code>SESSION_CLOSED</code> notifications.
In a clustered environment this will come with some computational overhead.
If these notifications are not otherwise used they can be disabled through:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight nowrap"><code data-lang="xml"><span class="nt">&lt;suppress-session-notifications&gt;</span>true<span class="nt">&lt;/suppress-session-notifications&gt;</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>The only time these notifications are <em>required</em> is in a cluster with MQTT clients where unique client ID utilization needs to be enforced.
Default value is <code>false</code></p>
</div>
</div>
<div class="sect3">
<h4 id="receiving-notification-messages"><a class="anchor" href="#receiving-notification-messages"></a><a class="link" href="#receiving-notification-messages">4.2.3. Receiving Notification Messages</a></h4>
<div class="paragraph">
<p>Apache ActiveMQ Artemis&#8217;s Core JMS Client can be used to receive notifications:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight nowrap"><code data-lang="java"><span class="nc">Topic</span> <span class="n">notificationsTopic</span> <span class="o">=</span> <span class="nc">ActiveMQJMSClient</span><span class="o">.</span><span class="na">createTopic</span><span class="o">(</span><span class="s">"activemq.notifications"</span><span class="o">);</span>
<span class="nc">Session</span> <span class="n">session</span> <span class="o">=</span> <span class="o">...</span>
<span class="nc">MessageConsumer</span> <span class="n">notificationConsumer</span> <span class="o">=</span> <span class="n">session</span><span class="o">.</span><span class="na">createConsumer</span><span class="o">(</span><span class="n">notificationsTopic</span><span class="o">);</span>
<span class="n">notificationConsumer</span><span class="o">.</span><span class="na">setMessageListener</span><span class="o">(</span><span class="k">new</span> <span class="nc">MessageListener</span><span class="o">()</span> <span class="o">{</span>
<span class="kd">public</span> <span class="kt">void</span> <span class="nf">onMessage</span><span class="o">(</span><span class="nc">Message</span> <span class="n">notif</span><span class="o">)</span> <span class="o">{</span>
<span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="s">"------------------------"</span><span class="o">);</span>
<span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="s">"Received notification:"</span><span class="o">);</span>
<span class="k">try</span> <span class="o">{</span>
<span class="nc">Enumeration</span> <span class="n">propertyNames</span> <span class="o">=</span> <span class="n">notif</span><span class="o">.</span><span class="na">getPropertyNames</span><span class="o">();</span>
<span class="k">while</span> <span class="o">(</span><span class="n">propertyNames</span><span class="o">.</span><span class="na">hasMoreElements</span><span class="o">())</span> <span class="o">{</span>
<span class="nc">String</span> <span class="n">propertyName</span> <span class="o">=</span> <span class="o">(</span><span class="nc">String</span><span class="o">)</span><span class="n">propertyNames</span><span class="o">.</span><span class="na">nextElement</span><span class="o">();</span>
<span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">format</span><span class="o">(</span><span class="s">" %s: %s\n"</span><span class="o">,</span> <span class="n">propertyName</span><span class="o">,</span> <span class="n">notif</span><span class="o">.</span><span class="na">getObjectProperty</span><span class="o">(</span><span class="n">propertyName</span><span class="o">));</span>
<span class="o">}</span>
<span class="o">}</span> <span class="k">catch</span> <span class="o">(</span><span class="nc">JMSException</span> <span class="n">e</span><span class="o">)</span> <span class="o">{</span>
<span class="o">}</span>
<span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="s">"------------------------"</span><span class="o">);</span>
<span class="o">}</span>
<span class="o">});</span></code></pre>
</div>
</div>
</div>
</div>
<div class="sect2">
<h3 id="example-3"><a class="anchor" href="#example-3"></a><a class="link" href="#example-3">4.3. Example</a></h3>
<div class="paragraph">
<p>See the <a href="examples.html#management-notification">Management Notification Example</a> which shows how to use a JMS <code>MessageListener</code> to receive management notifications from ActiveMQ Artemis server.</p>
</div>
</div>
<div class="sect2">
<h3 id="notification-types-and-headers"><a class="anchor" href="#notification-types-and-headers"></a><a class="link" href="#notification-types-and-headers">4.4. Notification Types and Headers</a></h3>
<div class="paragraph">
<p>Below is a list of all the different kinds of notifications as well as which headers are on the messages.
Every notification has a <code>_AMQ_NotifType</code> (value noted in parentheses) and <code>_AMQ_NotifTimestamp</code> header.
The timestamp is the un-formatted result of a call to <code>java.lang.System.currentTimeMillis()</code>.</p>
</div>
<div class="dlist">
<dl>
<dt class="hdlist1">BINDING_ADDED (0)</dt>
<dd>
<p><code>_AMQ_Binding_Type</code>, <code>_AMQ_Address</code>, <code>_AMQ_ClusterName</code>, <code>_AMQ_RoutingName</code>, <code>_AMQ_Binding_ID</code>, <code>_AMQ_Distance</code>, <code>_AMQ_FilterString</code></p>
</dd>
<dt class="hdlist1">BINDING_REMOVED (1)</dt>
<dd>
<p><code>_AMQ_Address</code>, <code>_AMQ_ClusterName</code>, <code>_AMQ_RoutingName</code>, <code>_AMQ_Binding_ID</code>, <code>_AMQ_Distance</code>, <code>_AMQ_FilterString</code></p>
</dd>
<dt class="hdlist1">CONSUMER_CREATED (2)</dt>
<dd>
<p><code>_AMQ_Address</code>, <code>_AMQ_ClusterName</code>, <code>_AMQ_RoutingName</code>, <code>_AMQ_Distance</code>, <code>_AMQ_ConsumerCount</code>, <code>_AMQ_User</code>, <code>_AMQ_ValidatedUser</code>, <code>_AMQ_RemoteAddress</code>, <code>_AMQ_SessionName</code>, <code>_AMQ_FilterString</code>, <code>_AMQ_CertSubjectDN</code></p>
</dd>
<dt class="hdlist1">CONSUMER_CLOSED (3)</dt>
<dd>
<p><code>_AMQ_Address</code>, <code>_AMQ_ClusterName</code>, <code>_AMQ_RoutingName</code>, <code>_AMQ_Distance</code>, <code>_AMQ_ConsumerCount</code>, <code>_AMQ_User</code>, <code>_AMQ_RemoteAddress</code>, <code>_AMQ_SessionName</code>, <code>_AMQ_FilterString</code></p>
</dd>
<dt class="hdlist1">SECURITY_AUTHENTICATION_VIOLATION (6)</dt>
<dd>
<p><code>_AMQ_User</code>, <code>_AMQ_CertSubjectDN</code>, <code>_AMQ_RemoteAddress</code></p>
</dd>
<dt class="hdlist1">SECURITY_PERMISSION_VIOLATION (7)</dt>
<dd>
<p><code>_AMQ_Address</code>, <code>_AMQ_CheckType</code>, <code>_AMQ_User</code></p>
</dd>
<dt class="hdlist1">DISCOVERY_GROUP_STARTED (8)</dt>
<dd>
<p><code>name</code></p>
</dd>
<dt class="hdlist1">DISCOVERY_GROUP_STOPPED (9)</dt>
<dd>
<p><code>name</code></p>
</dd>
<dt class="hdlist1">BROADCAST_GROUP_STARTED (10)</dt>
<dd>
<p><code>name</code></p>
</dd>
<dt class="hdlist1">BROADCAST_GROUP_STOPPED (11)</dt>
<dd>
<p><code>name</code></p>
</dd>
<dt class="hdlist1">BRIDGE_STARTED (12)</dt>
<dd>
<p><code>name</code></p>
</dd>
<dt class="hdlist1">BRIDGE_STOPPED (13)</dt>
<dd>
<p><code>name</code></p>
</dd>
<dt class="hdlist1">CLUSTER_CONNECTION_STARTED (14)</dt>
<dd>
<p><code>name</code></p>
</dd>
<dt class="hdlist1">CLUSTER_CONNECTION_STOPPED (15)</dt>
<dd>
<p><code>name</code></p>
</dd>
<dt class="hdlist1">ACCEPTOR_STARTED (16)</dt>
<dd>
<p><code>factory</code>, <code>id</code></p>
</dd>
<dt class="hdlist1">ACCEPTOR_STOPPED (17)</dt>
<dd>
<p><code>factory</code>, <code>id</code></p>
</dd>
<dt class="hdlist1">PROPOSAL (18)</dt>
<dd>
<p><code>_JBM_ProposalGroupId</code>, <code>_JBM_ProposalValue</code>, <code>_AMQ_Binding_Type</code>, <code>_AMQ_Address</code>, <code>_AMQ_Distance</code></p>
</dd>
<dt class="hdlist1">PROPOSAL_RESPONSE (19)</dt>
<dd>
<p><code>_JBM_ProposalGroupId</code>, <code>_JBM_ProposalValue</code>, <code>_JBM_ProposalAltValue</code>, <code>_AMQ_Binding_Type</code>, <code>_AMQ_Address</code>, <code>_AMQ_Distance</code></p>
</dd>
<dt class="hdlist1">CONSUMER_SLOW (21)</dt>
<dd>
<p><code>_AMQ_Address</code>, <code>_AMQ_ConsumerCount</code>, <code>_AMQ_RemoteAddress</code>, <code>_AMQ_ConnectionName</code>, <code>_AMQ_ConsumerName</code>, <code>_AMQ_SessionName</code></p>
</dd>
<dt class="hdlist1">ADDRESS_ADDED (22)</dt>
<dd>
<p><code>_AMQ_Address</code>, <code>_AMQ_Routing_Type</code></p>
</dd>
<dt class="hdlist1">ADDRESS_REMOVED (23)</dt>
<dd>
<p><code>_AMQ_Address</code>, <code>_AMQ_Routing_Type</code></p>
</dd>
<dt class="hdlist1">CONNECTION_CREATED (24)</dt>
<dd>
<p><code>_AMQ_ConnectionName</code>, <code>_AMQ_RemoteAddress</code></p>
</dd>
<dt class="hdlist1">CONNECTION_DESTROYED (25)</dt>
<dd>
<p><code>_AMQ_ConnectionName</code>, <code>_AMQ_RemoteAddress</code></p>
</dd>
<dt class="hdlist1">SESSION_CREATED (26)</dt>
<dd>
<p><code>_AMQ_ConnectionName</code>, <code>_AMQ_User</code>, <code>_AMQ_SessionName</code></p>
</dd>
<dt class="hdlist1">SESSION_CLOSED (27)</dt>
<dd>
<p><code>_AMQ_ConnectionName</code>, <code>_AMQ_User</code>, <code>_AMQ_SessionName</code></p>
</dd>
<dt class="hdlist1">MESSAGE_DELIVERED (28)</dt>
<dd>
<p><code>_AMQ_Address</code>, <code>_AMQ_Routing_Type</code>, <code>_AMQ_RoutingName</code>, <code>_AMQ_ConsumerName</code>, <code>_AMQ_Message_ID</code></p>
</dd>
<dt class="hdlist1">MESSAGE_EXPIRED (29)</dt>
<dd>
<p><code>_AMQ_Address</code>, <code>_AMQ_Routing_Type</code>, <code>_AMQ_RoutingName</code>, <code>_AMQ_ConsumerName</code>, <code>_AMQ_Message_ID</code></p>
</dd>
</dl>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="message-counters"><a class="anchor" href="#message-counters"></a><a class="link" href="#message-counters">5. Message Counters</a></h2>
<div class="sectionbody">
<div class="paragraph">
<p>Message counters can be used to obtain information on queues <em>over time</em> as Apache ActiveMQ Artemis keeps a history on queue metrics.</p>
</div>
<div class="paragraph">
<p>They can be used to show <em>trends</em> on queues.
For example, using the management API, it would be possible to query the number of messages in a queue at regular interval.
However, this would not be enough to know if the queue is used: the number of messages can remain constant because nobody is sending or receiving messages from the queue or because there are as many messages sent to the queue than messages consumed from it.
The number of messages in the queue remains the same in both cases but its use is widely different.</p>
</div>
<div class="paragraph">
<p>Message counters give additional information about the queues:</p>
</div>
<div class="dlist">
<dl>
<dt class="hdlist1">count</dt>
<dd>
<p>The <em>total</em> number of messages added to the queue since the server was started</p>
</dd>
<dt class="hdlist1">countDelta</dt>
<dd>
<p>the number of messages added to the queue <em>since the last message counter update</em></p>
</dd>
<dt class="hdlist1">messageCount</dt>
<dd>
<p>The <em>current</em> number of messages in the queue</p>
</dd>
<dt class="hdlist1">messageCountDelta</dt>
<dd>
<p>The <em>overall</em> number of messages added/removed from the queue <em>since the last message counter update</em>.
For example, if <code>messageCountDelta</code> is equal to <code>-10</code> this means that overall 10 messages have been removed from the queue (e.g. 2 messages were added and 12 were removed)</p>
</dd>
<dt class="hdlist1">lastAddTimestamp</dt>
<dd>
<p>The timestamp of the last time a message was added to the queue</p>
</dd>
<dt class="hdlist1">lastAckTimestamp</dt>
<dd>
<p>The timestamp of the last time a message from the queue was acknowledged</p>
</dd>
<dt class="hdlist1">updateTimestamp</dt>
<dd>
<p>The timestamp of the last message counter update</p>
<div class="paragraph">
<p>These attributes can be used to determine other meaningful data as well.
For example, to know specifically how many messages were <em>consumed</em> from the queue since the last update simply subtract the <code>messageCountDelta</code> from <code>countDelta</code>.</p>
</div>
</dd>
</dl>
</div>
<div class="sect2">
<h3 id="configuring-message-counters"><a class="anchor" href="#configuring-message-counters"></a><a class="link" href="#configuring-message-counters">5.1. Configuring Message Counters</a></h3>
<div class="paragraph">
<p>By default, message counters are disabled as it might have a small negative effect on memory.</p>
</div>
<div class="paragraph">
<p>To enable message counters, you can set it to <code>true</code> in <code>broker.xml</code>:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight nowrap"><code data-lang="xml"><span class="nt">&lt;message-counter-enabled&gt;</span>true<span class="nt">&lt;/message-counter-enabled&gt;</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>Message counters keep a history of the queue metrics (10 days by default) and sample all the queues at regular interval (10 seconds by default).
If message counters are enabled, these values should be configured to suit your messaging use case in <code>broker.xml</code>:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight nowrap"><code data-lang="xml"><span class="c">&lt;!-- keep history for a week --&gt;</span>
<span class="nt">&lt;message-counter-max-day-history&gt;</span>7<span class="nt">&lt;/message-counter-max-day-history&gt;</span>
<span class="c">&lt;!-- sample the queues every minute (60000ms) --&gt;</span>
<span class="nt">&lt;message-counter-sample-period&gt;</span>60000<span class="nt">&lt;/message-counter-sample-period&gt;</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>Message counters can be retrieved using the Management API.
For example, to retrieve message counters on a queue using JMX:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight nowrap"><code data-lang="java"><span class="c1">// retrieve a connection to Apache ActiveMQ Artemis's MBeanServer</span>
<span class="nc">MBeanServerConnection</span> <span class="n">mbsc</span> <span class="o">=</span> <span class="o">...</span>
<span class="nc">QueueControlMBean</span> <span class="n">queueControl</span> <span class="o">=</span> <span class="o">(</span><span class="nc">QueueControl</span><span class="o">)</span><span class="nc">MBeanServerInvocationHandler</span><span class="o">.</span><span class="na">newProxyInstance</span><span class="o">(</span><span class="n">mbsc</span><span class="o">,</span>
<span class="n">on</span><span class="o">,</span>
<span class="nc">QueueControl</span><span class="o">.</span><span class="na">class</span><span class="o">,</span>
<span class="kc">false</span><span class="o">);</span>
<span class="c1">// message counters are retrieved as a JSON String</span>
<span class="nc">String</span> <span class="n">counters</span> <span class="o">=</span> <span class="n">queueControl</span><span class="o">.</span><span class="na">listMessageCounter</span><span class="o">();</span>
<span class="c1">// use the MessageCounterInfo helper class to manipulate message counters more easily</span>
<span class="nc">MessageCounterInfo</span> <span class="n">messageCounter</span> <span class="o">=</span> <span class="nc">MessageCounterInfo</span><span class="o">.</span><span class="na">fromJSON</span><span class="o">(</span><span class="n">counters</span><span class="o">);</span>
<span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">format</span><span class="o">(</span><span class="s">"%s message(s) in the queue (since last sample: %s)\n"</span><span class="o">,</span>
<span class="n">messageCounter</span><span class="o">.</span><span class="na">getMessageCount</span><span class="o">(),</span>
<span class="n">messageCounter</span><span class="o">.</span><span class="na">getMessageCountDelta</span><span class="o">());</span></code></pre>
</div>
</div>
</div>
<div class="sect2">
<h3 id="example-4"><a class="anchor" href="#example-4"></a><a class="link" href="#example-4">5.2. Example</a></h3>
<div class="paragraph">
<p>See the <a href="examples.html#message-counter">Message Counter Example</a> which shows how to use message counters to retrieve information on a queue.</p>
</div>
</div>
</div>
</div>
</div>
</body>
</html>