Menu Close

Chapter 6. Using the management API

AMQ Broker has an extensive management API, which you can use to modify a broker’s configuration, create new resources (for example, addresses and queues), inspect these resources (for example, how many messages are currently held in a queue), and interact with them (for example, to remove messages from a queue).

In addition, clients can use the management API to manage the broker and subscribe to management notifications.

6.1. Methods for managing AMQ Broker using the management API

There are two ways to use the management API to manage the broker:

  • Using JMX — JMX is the standard way to manage Java applications
  • Using the JMS API — management operations are sent to the broker using JMS messages and the AMQ JMS client

Although there are two different ways to manage the broker, 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 by using JMS messages and the AMQ JMS client.

This choice depends on your particular requirements, application settings, and environment. Regardless of the way you invoke management operations, the management API is the same.

For each managed resource, there exists a Java interface describing what can be invoked for this type of resource. The broker exposes its managed resources in the org.apache.activemq.artemis.api.core.management package. The way to invoke management operations depends on whether JMX messages or JMS messages and the AMQ JMS client are used.

Note

Some management operations require a filter parameter to choose which messages are affected by the operation. Passing null or an empty string means that the management operation will be performed on all messages.

6.2. Managing AMQ Broker using JMX

You can use Java Management Extensions (JMX) to manage a broker. The management API is exposed by the broker using MBeans interfaces. The broker registers its resources with the domain org.apache.activemq.

For example, the ObjectName to manage a queue named exampleQueue is:

org.apache.activemq.artemis:broker="__BROKER_NAME__",component=addresses,address="exampleQueue",subcomponent=queues,routingtype="anycast",queue="exampleQueue"

The MBean is:

org.apache.activemq.artemis.api.management.QueueControl

The MBean’s ObjectName is built using the helper class org.apache.activemq.artemis.api.core.management.ObjectNameBuilder. You can also use jconsole to find the ObjectName of the MBeans you want to manage.

Managing the broker 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.

6.2.1. Configuring JMX management

By default, JMX is enabled to manage the broker. You can enable or disable JMX management by setting the jmx-management-enabled property in the broker.xml configuration file.

Procedure

  1. Open the <broker_instance_dir>/etc/broker.xml configuration file.
  2. Set <jmx-management-enabled>.

    <jmx-management-enabled>true</jmx-management-enabled>

    If JMX is enabled, the broker can be managed locally using jconsole.

    Note

    Remote connections to JMX are not enabled by default for security reasons.

  3. If you want to manage multiple brokers from the same MBeanServer, configure the JMX domain for each of the brokers.

    By default, the broker uses the JMX domain org.apache.activemq.artemis.

    <jmx-domain>my.org.apache.activemq</jmx-domain>
    Note

    If you are using AMQ Broker on a Windows system, system properties must be set in artemis, or artemis.cmd. A shell script is located under <install_dir>/bin.

Additional resources

  • For more information on configuring the broker for remote management, see Oracle’s Java Management Guide.

6.2.2. Configuring JMX management access

By default, remote JMX access to a broker is disabled for security reasons. However, AMQ Broker has a JMX agent that allows remote access to JMX MBeans. You enable JMX access by configuring a connector element in the broker management.xml configuration file.

Note

While it is also possible to enable JMX access using the `com.sun.management.jmxremote ` JVM system property, that method is not supported and is not secure. Modifying that JVM system property can bypass RBAC on the broker. To minimize security risks, consider limited access to localhost.

Important

Exposing the JMX agent of a broker for remote management has security implications.

To secure your configuration as described in this procedure:

  • Use SSL for all connections.
  • Explicitly define the connector host, that is, the host and port to expose the agent on.
  • Explicitly define the port that the RMI (Remote Method Invocation) registry binds to.

Prerequisites

  • A working broker instance
  • The Java jconsole utility

Procedure

  1. Open the <broker-instance-dir>/etc/management.xml configuration file.
  2. Define a connector for the JMX agent. The connector-port setting establishes an RMI registry that clients such as jconsole query for the JMX connector server. For example, to allow remote access on port 1099:

    <connector connector-port="1099"/>
  3. Verify the connection to the JMX agent using jconsole:

    service:jmx:rmi:///jndi/rmi://localhost:1099/jmxrmi
  4. Define additional properties on the connector, as described below.

    connector-host
    The broker server host to expose the agent on. To prevent remote access, set connector-host to 127.0.0.1 (localhost).
    rmi-registry-port
    The port that the JMX RMI connector server binds to. If not set, the port is always random. Set this property to avoid problems with remote JMX connections tunnelled through a firewall.
    jmx-realm
    JMX realm to use for authentication. The default value is activemq to match the JAAS configuration.
    object-name
    Object name to expose the remote connector on. The default value is connector:name=rmi.
    secured
    Specify whether the connector is secured using SSL. The default value is false. Set the value to true to ensure secure communication.
    key-store-path
    Location of the keystore. Required if you have set secured="true".
    key-store-password
    Keystore password. Required if you have set secured="true". The password can be encrypted.
    key-store-provider
    Keystore provider. Required if you have set secured="true". The default value is JKS.
    trust-store-path
    Location of the truststore. Required if you have set secured="true".
    trust-store-password
    Truststore password. Required if you have set secured="true". The password can be encrypted.
    trust-store-provider
    Truststore provider. Required if you have set secured="true". The default value is JKS
    password-codec
    The fully qualified class name of the password codec to use. See the password masking documentation, linked below, for more details on how this works.
  5. Set an appropriate value for the endpoint serialization using jdk.serialFilter as described in the Java Platform documentation.

Additional resources

6.2.3. MBeanServer configuration

When the broker runs in standalone mode, it uses the Java Virtual Machine’s Platform MBeanServer to register its MBeans. By default, Jolokia is also deployed to allow access to the MBean server using REST.

6.2.4. How JMX is exposed with Jolokia

By default, AMQ Broker ships with the Jolokia HTTP agent deployed as a web application. Jolokia is a remote JMX over HTTP bridge that exposes MBeans.

Note

To use Jolokia, the user must belong to the role defined by the hawtio.role system property in the <broker_instance_dir>/etc/artemis.profile configuration file. By default, this role is amq.

Example 6.1. Using Jolokia to query the broker’s version

This example uses a Jolokia REST URL to find the version of a broker. The Origin flag should specify the domain name or DNS host name for the broker server. In addition, the value you specify for Origin must correspond to an entry for <allow-origin> in your Jolokia Cross-Origin Resource Sharing (CORS) specification.

$ curl http://admin:admin@localhost:8161/console/jolokia/read/org.apache.activemq.artemis:broker=\"0.0.0.0\"/Version -H "Origin: mydomain.com"
{"request":{"mbean":"org.apache.activemq.artemis:broker=\"0.0.0.0\"","attribute":"Version","type":"read"},"value":"2.4.0.amq-710002-redhat-1","timestamp":1527105236,"status":200}

Additional resources

  • For more information on using a JMX-HTTP bridge, see the Jolokia documentation.
  • For more information on assigning a user to a role, see Adding Users.
  • For more information on specifying Jolokia Cross-Origin Resource Sharing (CORS), see section 4.1.5 of Security.

6.2.5. Subscribing to JMX management notifications

If JMX is enabled in your environment, you can subscribe to management notifications.

Procedure

  • Subscribe to ObjectName org.apache.activemq.artemis:broker="<broker-name>".

Additional resources

6.3. Managing AMQ Broker using the JMS API

The Java Message Service (JMS) API allows you to create, send, receive, and read messages. You can use JMS and the AMQ JMS client to manage brokers.

6.3.1. Configuring broker management using JMS messages and the AMQ JMS Client

To use JMS to manage a broker, you must first configure the broker’s management address with the manage permission.

Procedure

  1. Open the <broker_instance_dir>/etc/broker.xml configuration file.
  2. Add the <management-address> element, and specify a management address.

    By default, the management address is queue.activemq.management. You only need to specify a different address if you do not want to use the default.

    <management-address>my.management.address</management-address>
  3. Provide the management address with the manage user permission type.

    This permission type enables the management address to receive and handle management messages.

    <security-setting-match="queue.activemq.management">
        <permission-type="manage" roles="admin"/>
    </security-setting>

6.3.2. Managing brokers using the JMS API and AMQ JMS Client

To invoke management operations using JMS messages, the AMQ JMS client must instantiate the special management queue.

Procedure

  1. Create a QueueRequestor to send messages to the management address and receive replies.
  2. Create a Message.
  3. Use the helper class org.apache.activemq.artemis.api.jms.management.JMSManagementHelper to fill the message with the management properties.
  4. Send the message using the QueueRequestor.
  5. Use the helper class org.apache.activemq.artemis.api.jms.management.JMSManagementHelper to retrieve the operation result from the management reply.

Example 6.2. Viewing the number of messages in a queue

This example shows how to use the JMS API to view the number of messages in the JMS queue exampleQueue:

Queue managementQueue = ActiveMQJMSClient.createQueue("activemq.management");

QueueSession session = ...
QueueRequestor requestor = new QueueRequestor(session, managementQueue);
connection.start();
Message message = session.createMessage();
JMSManagementHelper.putAttribute(message, "queue.exampleQueue", "messageCount");
Message reply = requestor.request(message);
int count = (Integer)JMSManagementHelper.getResult(reply);
System.out.println("There are " + count + " messages in exampleQueue");

6.4. Management operations

Whether you are using JMX or JMS messages to manage AMQ Broker, you can use the same API management operations. Using the management API, you can manage brokers, addresses, and queues.

6.4.1. Broker management operations

You can use the management API to manage your brokers.

Listing, creating, deploying, and destroying queues

A list of deployed queues can be retrieved using the getQueueNames() method.

Queues can be created or destroyed using the management operations createQueue(), deployQueue(), or destroyQueue() on the ActiveMQServerControl (with the ObjectName org.apache.activemq.artemis:broker="BROKER_NAME" or the resource name server).

createQueue will fail if the queue already exists while deployQueue will do nothing.

Pausing and resuming queues
The QueueControl can pause and resume the underlying queue. When a queue is paused, it will receive messages but will not deliver them. When it is resumed, it will begin delivering the queued messages, if any.
Listing and closing remote connections

Retrieve a client’s remote addresses by using listRemoteAddresses(). It is also possible to close the connections associated with a remote address using the closeConnectionsForAddress() method.

Alternatively, list connection IDs using listConnectionIDs() and list all the sessions for a given connection ID using listSessions().

Managing transactions

In case of a broker crash, when the broker restarts, some transactions might require manual intervention. Use the the following methods to help resolve issues you encounter.

List the transactions which are in the prepared states (the transactions are represented as opaque Base64 Strings) using the listPreparedTransactions() method lists.

Commit or rollback a given prepared transaction using commitPreparedTransaction() or rollbackPreparedTransaction() to resolve heuristic transactions.

List heuristically completed transactions using the listHeuristicCommittedTransactions() and listHeuristicRolledBackTransactions methods.

Enabling and resetting message counters

Enable and disable message counters using the enableMessageCounters() or disableMessageCounters() method.

Reset message counters by using the resetAllMessageCounters() and resetAllMessageCounterHistories() methods.

Retrieving broker configuration and attributes
The ActiveMQServerControl exposes the broker’s configuration through all its attributes (for example, getVersion() method to retrieve the broker’s version, and so on).
Listing, creating, and destroying Core Bridge and diverts

List deployed Core Bridge and diverts using the getBridgeNames() and getDivertNames() methods respectively.

Create or destroy using bridges and diverts using createBridge() and destroyBridge() or createDivert() and destroyDivert() on the ActiveMQServerControl (with the ObjectName org.apache.activemq.artemis:broker="BROKER_NAME" or the resource name server).

Stopping the broker and forcing failover to occur with any currently attached clients

Use the forceFailover() on the ActiveMQServerControl (with the ObjectName org.apache.activemq.artemis:broker="BROKER_NAME" or the resource name server)

Note

Because this method actually stops the broker, you will likely receive an error. The exact error depends on the management service you used to call the method.

6.4.2. Address management operations

You can use the management API to manage addresses.

Manage addresses using the AddressControl class with ObjectName org.apache.activemq.artemis:broker="<broker-name>", component=addresses,address="<address-name>" or the resource name address.<address-name>.

Modify roles and permissions for an address using the addRole() or removeRole() methods. You can list all the roles associated with the queue with the getRoles() method.

6.4.3. Queue management operations

You can use the management API to manage queues.

The core management API deals with queues. The QueueControl class defines the queue management operations (with the ObjectName,org.apache.activemq.artemis:broker="<broker-name>",component=addresses,address="<bound-address>",subcomponent=queues,routing-type="<routing-type>",queue="<queue-name>" or the resource name queue.<queue-name>).

Most of the management operations on queues take either a single message ID (for example, to remove a single message) or a filter (for example, to expire all messages with a given property).

Expiring, sending to a dead letter address, and moving messages

Expire messages from a queue using the expireMessages() method. If an expiry address is defined, messages are sent to this address, otherwise they are discarded. You can define the expiry address for an address or set of addresses (and hence the queues bound to those addresses) in the address-settings element of the broker.xml configuration file. For an example, see the "Default message address settings" section in Understanding the default broker configuration.

Send messages to a dead letter address using the sendMessagesToDeadLetterAddress() method. This method returns the number of messages sent to the dead letter address. If a dead letter address is defined, messages are sent to this address, otherwise they are removed from the queue and discarded. You can define the dead letter address for an address or set of addresses (and hence the queues bound to those addresses) in the address-settings element of the broker.xml configuration file. For an example, see the "Default message address settings" section in Understanding the default broker configuration.

Move messages from one queue to another using the moveMessages() method.

Listing and removing messages

List messages from a queue using the listMessages() method. It will return an array of Map, one Map for each message.

Remove messages from a queue using the removeMessages() method, which returns a boolean for the single message ID variant or the number of removed messages for the filter variant. This method takes a filter argument to remove only filtered messages. Setting the filter to an empty string will in effect remove all messages.

Counting messages
The number of messages in a queue is returned by the getMessageCount() method. Alternatively, the countMessages() will return the number of messages in the queue which match a given filter.
Changing message priority
The message priority can be changed by using the changeMessagesPriority() method which returns a boolean for the single message ID variant or the number of updated messages for the filter variant.
Message counters
Message counters can be listed for a queue with the listMessageCounter() and listMessageCounterHistory() methods (see Section 6.6, “Using message counters”). The message counters can also be reset for a single queue using the resetMessageCounter() method.
Retrieving the queue attributes
The QueueControl exposes queue settings through its attributes (for example, getFilter() to retrieve the queue’s filter if it was created with one, isDurable() to know whether the queue is durable, and so on).
Pausing and resuming queues
The QueueControl can pause and resume the underlying queue. When a queue is paused, it will receive messages but will not deliver them. When it is resumed, it will begin delivering the queued messages, if any.

6.4.4. Remote resource management operations

You can use the management API to start and stop a broker’s remote resources (acceptors, diverts, bridges, and so on) so that the broker can be taken offline for a given period of time without stopping completely.

Acceptors
Start or stop an acceptor using the start() or. stop() method on the AcceptorControl class (with the ObjectName org.apache.activemq.artemis:broker="<broker-name>",component=acceptors,name="<acceptor-name>" or the resource name acceptor.<address-name>). Acceptor parameters can be retrieved using the AcceptorControl attributes. See Network Connections: Acceptors and Connectors for more information about Acceptors.
Diverts
Start or stop a divert using the start() or stop() method on the DivertControl class (with the ObjectName org.apache.activemq.artemis:broker="<broker-name>",component=diverts,name="<divert-name>" or the resource name divert.<divert-name>). Divert parameters can be retrieved using the DivertControl attributes.
Bridges
Start or stop a bridge using the start() (resp. stop()) method on the BridgeControl class (with the ObjectName org.apache.activemq.artemis:broker="<broker-name>",component=bridge,name="<bridge-name>" or the resource name bridge.<bridge-name>). Bridge parameters can be retrieved using the BridgeControl attributes.
Broadcast groups
Start or stop a broadcast group using the start() or stop() method on the BroadcastGroupControl class (with the ObjectName org.apache.activemq.artemis:broker="<broker-name>",component=broadcast-group,name="<broadcast-group-name>" or the resource name broadcastgroup.<broadcast-group-name>). Broadcast group parameters can be retrieved using the BroadcastGroupControl attributes. See Broker discovery methods for more information.
Discovery groups
Start or stop a discovery group using the start() or stop() method on the DiscoveryGroupControl class (with the ObjectName org.apache.activemq.artemis:broker="<broker-name>",component=discovery-group,name="<discovery-group-name>" or the resource name discovery.<discovery-group-name>). Discovery groups parameters can be retrieved using the DiscoveryGroupControl attributes. See Broker discovery methods for more information.
Cluster connections
Start or stop a cluster connection using the start() or stop() method on the ClusterConnectionControl class (with the ObjectName org.apache.activemq.artemis:broker="<broker-name>",component=cluster-connection,name="<cluster-connection-name>" or the resource name clusterconnection.<cluster-connection-name>). Cluster connection parameters can be retrieved using the ClusterConnectionControl attributes. See Creating a broker cluster for more information.

6.5. Management notifications

Below is a list of all the different kinds of notifications as well as which headers are on the messages. Every notification has a _AMQ_NotifType (value noted in parentheses) and _AMQ_NotifTimestamp header. The time stamp is the unformatted result of a call to java.lang.System.currentTimeMillis().

Notification typeHeaders

BINDING_ADDED (0)

_AMQ_Binding_Type

_AMQ_Address

_AMQ_ClusterName

_AMQ_RoutingName

_AMQ_Binding_ID

_AMQ_Distance

_AMQ_FilterString

BINDING_REMOVED (1)

_AMQ_Address

_AMQ_ClusterName

_AMQ_RoutingName

_AMQ_Binding_ID

_AMQ_Distance

_AMQ_FilterString

CONSUMER_CREATED (2)

_AMQ_Address

_AMQ_ClusterName

_AMQ_RoutingName

_AMQ_Distance

_AMQ_ConsumerCount

_AMQ_User

_AMQ_RemoteAddress

_AMQ_SessionName

_AMQ_FilterString

CONSUMER_CLOSED (3)

_AMQ_Address

_AMQ_ClusterName

_AMQ_RoutingName

_AMQ_Distance

_AMQ_ConsumerCount

_AMQ_User

_AMQ_RemoteAddress

_AMQ_SessionName

_AMQ_FilterString

SECURITY_AUTHENTICATION_VIOLATION (6)

_AMQ_User

SECURITY_PERMISSION_VIOLATION (7)

_AMQ_Address

_AMQ_CheckType

_AMQ_User

DISCOVERY_GROUP_STARTED (8)

name

DISCOVERY_GROUP_STOPPED (9)

name

BROADCAST_GROUP_STARTED (10)

name

BROADCAST_GROUP_STOPPED (11)

name

BRIDGE_STARTED (12)

name

BRIDGE_STOPPED (13)

name

CLUSTER_CONNECTION_STARTED (14)

name

CLUSTER_CONNECTION_STOPPED (15)

name

ACCEPTOR_STARTED (16)

factory

id

ACCEPTOR_STOPPED (17)

factory

id

PROPOSAL (18)

_JBM_ProposalGroupId

_JBM_ProposalValue

_AMQ_Binding_Type

_AMQ_Address

_AMQ_Distance

PROPOSAL_RESPONSE (19)

_JBM_ProposalGroupId

_JBM_ProposalValue

_JBM_ProposalAltValue

_AMQ_Binding_Type

_AMQ_Address

_AMQ_Distance

CONSUMER_SLOW (21)

_AMQ_Address

_AMQ_ConsumerCount

_AMQ_RemoteAddress

_AMQ_ConnectionName

_AMQ_ConsumerName

_AMQ_SessionName

6.6. Using message counters

You use message counters to obtain information about queues over time. This helps you to identify trends that would otherwise be difficult to see.

For example, you could use message counters to determine how a particular queue is being used over time. You could also attempt to obtain this information by using the management API to query the number of messages in the queue at regular intervals, but this would not show how the queue is actually being used. The number of messages in a queue can remain constant because no clients are sending or receiving messages on it, or because the number of messages sent to the queue is equal to the number of messages consumed from it. In both of these cases, the number of messages in the queue remains the same even though it is being used in very different ways.

6.6.1. Types of message counters

Message counters provide additional information about queues on a broker.

count
The total number of messages added to the queue since the broker was started.
countDelta
The number of messages added to the queue since the last message counter update.
lastAckTimestamp
The time stamp of the last time a message from the queue was acknowledged.
lastAddTimestamp
The time stamp of the last time a message was added to the queue.
messageCount
The current number of messages in the queue.
messageCountDelta
The overall number of messages added/removed from the queue since the last message counter update. For example, if messageCountDelta is -10, then 10 messages overall have been removed from the queue.
udpateTimestamp
The time stamp of the last message counter update.
Note

You can combine message counters to determine other meaningful data as well. For example, to know specifically how many messages were consumed from the queue since the last update, you would subtract the messageCountDelta from countDelta.

6.6.2. Enabling message counters

Message counters can have a small impact on the broker’s memory; therefore, they are disabled by default. To use message counters, you must first enable them.

Procedure

  1. Open the <broker_instance_dir>/etc/broker.xml configuration file.
  2. Enable message counters.

    <message-counter-enabled>true</message-counter-enabled>
  3. Set the message counter history and sampling period.

    <message-counter-max-day-history>7</message-counter-max-day-history>
    <message-counter-sample-period>60000</message-counter-sample-period>
    message-counter-max-day-history
    The number of days the broker should store queue metrics. The default is 10 days.
    message-counter-sample-period
    How often (in milliseconds) the broker should sample its queues to collect metrics. The default is 10000 milliseconds.

6.6.3. Retrieving message counters

You can use the management API to retrieve message counters.

Prerequisites

Procedure

  • Use the management API to retrieve message counters.

    // Retrieve a connection to the broker's MBeanServer.
    MBeanServerConnection mbsc = ...
    JMSQueueControlMBean queueControl = (JMSQueueControl)MBeanServerInvocationHandler.newProxyInstance(mbsc,
       on,
       JMSQueueControl.class,
       false);
    
    // Message counters are retrieved as a JSON string.
    String counters = queueControl.listMessageCounter();
    
    // Use the MessageCounterInfo helper class to manipulate message counters more easily.
    MessageCounterInfo messageCounter = MessageCounterInfo.fromJSON(counters);
    System.out.format("%s message(s) in the queue (since last sample: %s)\n",
    messageCounter.getMessageCount(),
    messageCounter.getMessageCountDelta());

Additional resources