Overview
Apache ActiveMQ is an open-source, multi-protocol message broker written in Java. It supports JMS 1.1 and 2.0, AMQP, STOMP, MQTT, and OpenWire protocols, making it one of the most versatile message brokers available. ActiveMQ Classic is the long-standing version, while ActiveMQ Artemis is the next-generation broker with improved performance.
ActiveMQ provides persistent and non-persistent messaging, message groups, virtual destinations, composite destinations, and advanced clustering features. It integrates seamlessly with Java EE application servers and Spring Framework, and can be embedded directly into Java applications.
Installation
Using Docker
# ActiveMQ Classic
docker run -d --name activemq \
-p 61616:61616 \
-p 8161:8161 \
apache/activemq-classic:latest
# ActiveMQ Artemis
docker run -d --name artemis \
-p 61616:61616 \
-p 8161:8161 \
apache/activemq-artemis:latest
Linux / macOS Binary Install
# Download and extract
wget https://downloads.apache.org/activemq/5.18.3/apache-activemq-5.18.3-bin.tar.gz
tar -xzf apache-activemq-5.18.3-bin.tar.gz
cd apache-activemq-5.18.3
# Start the broker
./bin/activemq start
# Check status
./bin/activemq status
# Stop the broker
./bin/activemq stop
Web Console Access
# Default web console URL
# http://localhost:8161/admin
# Default credentials: admin / admin
Core Commands
| Command | Description |
|---|
./bin/activemq start | Start broker in background |
./bin/activemq console | Start broker in foreground |
./bin/activemq stop | Stop the broker |
./bin/activemq status | Check broker status |
./bin/activemq restart | Restart the broker |
./bin/activemq list | List all running brokers |
./bin/activemq browse <queue> | Browse messages in a queue |
./bin/activemq purge <queue> | Purge all messages from a queue |
Queue and Topic Management
CLI Operations
# Send a message to a queue
./bin/activemq producer --destination queue://TEST.QUEUE \
--messageCount 100 --message "Hello ActiveMQ"
# Consume messages from a queue
./bin/activemq consumer --destination queue://TEST.QUEUE \
--messageCount 100
# Send to a topic
./bin/activemq producer --destination topic://TEST.TOPIC \
--messageCount 10
# Browse queue messages
./bin/activemq browse --amqurl tcp://localhost:61616 TEST.QUEUE
REST API
# List queues via Jolokia REST API
curl -u admin:admin \
'http://localhost:8161/api/jolokia/read/org.apache.activemq:type=Broker,brokerName=localhost'
# Get queue stats
curl -u admin:admin \
'http://localhost:8161/api/jolokia/read/org.apache.activemq:type=Broker,brokerName=localhost,destinationType=Queue,destinationName=TEST.QUEUE'
# Purge a queue via REST
curl -u admin:admin \
'http://localhost:8161/api/jolokia/exec/org.apache.activemq:type=Broker,brokerName=localhost,destinationType=Queue,destinationName=TEST.QUEUE/purge'
Configuration
Main Broker Config (conf/activemq.xml)
<beans>
<broker xmlns="http://activemq.apache.org/schema/core"
brokerName="myBroker"
dataDirectory="${activemq.data}">
<!-- Transport connectors -->
<transportConnectors>
<transportConnector name="openwire" uri="tcp://0.0.0.0:61616"/>
<transportConnector name="amqp" uri="amqp://0.0.0.0:5672"/>
<transportConnector name="stomp" uri="stomp://0.0.0.0:61613"/>
<transportConnector name="mqtt" uri="mqtt://0.0.0.0:1883"/>
</transportConnectors>
<!-- Persistence adapter -->
<persistenceAdapter>
<kahaDB directory="${activemq.data}/kahadb"
journalMaxFileLength="32mb"/>
</persistenceAdapter>
<!-- Memory limits -->
<systemUsage>
<systemUsage>
<memoryUsage><memoryUsage percentOfJvmHeap="70"/></memoryUsage>
<storeUsage><storeUsage limit="100 gb"/></storeUsage>
<tempUsage><tempUsage limit="50 gb"/></tempUsage>
</systemUsage>
</systemUsage>
<!-- Destination policies -->
<destinationPolicy>
<policyMap>
<policyEntries>
<policyEntry queue=">" memoryLimit="256mb"
producerFlowControl="true"/>
<policyEntry topic=">" memoryLimit="256mb"/>
</policyEntries>
</policyMap>
</destinationPolicy>
</broker>
</beans>
Authentication (conf/jetty-realm.properties)
# username: password, role
admin: admin123, admin
user: user123, user
producer: prod123, producer
consumer: cons123, consumer
Advanced Usage
Network of Brokers (Clustering)
<!-- In activemq.xml — broker A connects to broker B -->
<networkConnectors>
<networkConnector name="A-to-B"
uri="static:(tcp://brokerB:61616)"
duplex="true"
decreaseNetworkConsumerPriority="true"
networkTTL="2"
dynamicOnly="true"/>
</networkConnectors>
Virtual Destinations
<!-- Route topic messages to individual consumer queues -->
<destinationInterceptors>
<virtualDestinationInterceptor>
<virtualDestinations>
<compositeQueue name="MY.QUEUE">
<forwardTo>
<queue physicalName="QUEUE.A"/>
<queue physicalName="QUEUE.B"/>
</forwardTo>
</compositeQueue>
<virtualTopic name="VirtualTopic.>"
prefix="Consumer.*."
selectorAware="false"/>
</virtualDestinations>
</virtualDestinationInterceptor>
</destinationInterceptors>
Dead Letter Queue Configuration
<policyEntry queue=">">
<deadLetterStrategy>
<individualDeadLetterStrategy queuePrefix="DLQ."
useQueueForQueueMessages="true"
processExpired="true"
processNonPersistent="true"/>
</deadLetterStrategy>
<redeliveryPolicy maximumRedeliveries="5"
initialRedeliveryDelay="1000"
redeliveryDelay="5000"
backOffMultiplier="2"
useExponentialBackOff="true"/>
</policyEntry>
Monitoring
JMX Monitoring
# Connect via JConsole
jconsole service:jmx:rmi:///jndi/rmi://localhost:1099/jmxrmi
# Key MBeans
# org.apache.activemq:type=Broker — broker stats
# org.apache.activemq:type=Queue — queue metrics
# org.apache.activemq:type=Topic — topic metrics
Key Metrics to Monitor
| Metric | Description |
|---|
QueueSize | Number of pending messages |
EnqueueCount | Total messages enqueued |
DequeueCount | Total messages dequeued |
ConsumerCount | Active consumers |
ProducerCount | Active producers |
MemoryPercentUsage | Broker memory utilization |
StorePercentUsage | Persistent store utilization |
DispatchCount | Messages dispatched to consumers |
Troubleshooting
| Issue | Solution |
|---|
| Broker won’t start | Check data/activemq.log for port conflicts or permission errors |
| Messages stuck in queue | Verify consumers are connected; check ConsumerCount via JMX |
| Out of memory | Increase heap in env file; tune memoryUsage in config |
| Slow consumers | Enable producer flow control; add more consumer instances |
| KahaDB corruption | Stop broker, delete data/kahadb/db.data, restart (loses messages) |
| Web console inaccessible | Check Jetty config in conf/jetty.xml; verify port 8161 is free |
| Connection refused | Ensure transport connector is bound to correct interface |
| DLQ filling up | Review redelivery policy; investigate consumer processing errors |