Back to blog

// OSSeva Blog

Migration

Migrating ActiveMQ Classic to Artemis: What Actually Changes

Randall McClure11 min read

Two brokers, one name

The most common misunderstanding in this migration is in its framing. ActiveMQ Classic 5.x and ActiveMQ Artemis are separate codebases under one Apache project. Artemis is not the next version of Classic — Classic has its own next version, 6.x, and both are maintained. Moving from Classic to Artemis is a broker replacement that happens to keep the brand.

That matters for planning, because “upgrade” and “replace” get very different budgets.

What is genuinely compatible

Start with the good news, because it is real. Artemis speaks OpenWire, the native protocol of Classic. Existing JMS clients built on the activemq-client library can connect to an Artemis broker through an OpenWire acceptor without being recompiled. For a first proof of concept this works almost embarrassingly well.

It is also the trap. A client connecting successfully tells you the wire protocol is compatible. It tells you nothing about whether destinations, persistence, redelivery, advisory messages or your network-of-brokers topology behave the same way. They do not.

The differences that define the project

These come from the Artemis project's own migration documentation.

AreaActiveMQ ClassicActiveMQ Artemis
IO layerSeveral transport implementations — tcp (synchronous), nio (non-blocking)Netty throughout
Message storeKahaDB: a message journal plus an indexAppend-only message journal, no separate index
Configurationconf/activemq.xmletc/broker.xml
DestinationsQueues and topics, declared under <destinations>Addresses with routing types, declared under <addresses>
Queue semanticsQueueAddress with anycast routing
Topic semanticsTopicAddress with multicast routing

The addressing model is the conceptual shift

Classic has queues and topics as first-class, distinct things. Artemis has addresses, and an address has a routing type: anycast delivers each message to one consumer (queue behaviour), multicast delivers to all subscribers (topic behaviour). JMS clients still see queues and topics, because Artemis maps them. But configuration, security settings, address settings and monitoring are all expressed in the address model, so everyone who operates the broker has to learn it even if no developer does.

The store does not carry over

KahaDB and the Artemis journal are different formats. Messages sitting in a Classic store on cutover day are not readable by Artemis. The project provides a route: the ActiveMQ command-line tools include an exporter that writes a KahaDB or mKahaDB store out in Artemis's XML format, for import on the other side.

The choice this gives you:

  • Drain, then cut over. Stop producers, let consumers empty the queues, switch. Simplest, and right for most estates — if your queues actually drain.
  • Export and import. For queues that hold messages for long periods, or DLQs you are obliged to keep.
  • Run both and bridge. Longer transition, no big-bang, more moving parts.

Virtual topics need explicit handling

If you use Classic's virtual topics — producers publish to VirtualTopic.Orders, consumers read from Consumer.A.VirtualTopic.Orders — this is the item most likely to break silently. Artemis can emulate the pattern, but only when told to: the OpenWire acceptor takes a virtualTopicConsumerWildcards option that maps the consumer-queue naming convention onto Artemis addresses. From version 0.2.0 the export tool also understands virtual topic consumer queue mapping, so existing consumers can resume on Artemis without message loss. Neither happens by default.

<!-- etc/broker.xml: OpenWire acceptor with virtual topic mapping -->
<acceptor name="openwire">
  tcp://0.0.0.0:61616?protocols=OPENWIRE;virtualTopicConsumerWildcards=Consumer.*.%3E%3B2
</acceptor>

What else to inventory before you estimate

  • Network of brokers. Classic's store-and-forward networks have no direct equivalent. Artemis clusters and bridges solve the same problems differently, and the topology has to be redesigned rather than translated.
  • Advisory messages. Applications that subscribe to ActiveMQ.Advisory.* topics for connection or consumer events depend on Classic behaviour.
  • Destination policies. Per-destination policy entries — memory limits, dead-letter strategies, slow-consumer handling — become address settings, with different names and sometimes different semantics.
  • Plugins and interceptors. Custom broker plugins are Classic API. They are rewritten, not ported.
  • JMX and monitoring. MBean names and structure differ, so dashboards and alerts built on Classic's JMX tree stop working.
  • Selectors and message groups are supported on both, but verify behaviour under your actual load rather than assuming.
# What is this broker actually using? Start here.
grep -cE '<networkConnector' conf/activemq.xml          # network of brokers
grep -cE 'VirtualTopic|virtualDestinations' conf/activemq.xml
grep -cE '<policyEntry' conf/activemq.xml               # destination policies
grep -cE '<plugins>|<bean ' conf/activemq.xml          # custom plugins

A sequence that works

  1. Inventory the configuration with the checks above. Each non-zero count is a work item.
  2. Stand up Artemis with an OpenWire acceptor and point a non-production client at it. Confirm connectivity — then keep going, because connectivity proves little.
  3. Translate destinations to addresses and policies to address settings.
  4. Test the behaviours, not the connections: redelivery and DLQ, transactions, selectors, durable subscriptions, virtual topics, slow consumers.
  5. Decide the message-store strategy per queue: drain, export, or bridge.
  6. Rebuild monitoring against the Artemis management model before cutover, not after.
  7. Migrate clients off OpenWire later, if at all. Moving to the Artemis core client or AMQP is a separate, optional project. Do not bundle it.

While you plan

This is a project measured in quarters for any estate with a network of brokers or custom plugins. Meanwhile, Apache ships Classic fixes only on the current 5.19.x line and on 6.x — brokers on 5.15 through 5.18 receive nothing, and that installed base is what CVE-2023-46604, the OpenWire remote code execution flaw, was exploited against within days of disclosure.

OSSeva backports security fixes onto the 5.x line you run, so the migration can be designed properly. We also cover Artemis and RabbitMQ, so the question of which broker you should land on gets an answer based on your workload rather than on which one we happen to sell.

Related

Tags

ActiveMQArtemisMigrationJMS

Ready to get your open source under control?

Talk to an OSSeva engineer about CVE coverage, compliance, and migration support for your stack.