Antoine Wils
Antoine Wils

Reputation: 349

ActiveMQ Artemis: Virtual Topic and Dead Letter Queue

We are migrating from ActiveMQ "Classic" to ActiveMQ Artemis. On ActiveMQ "Classic" we were using Virtual Topics. They were created with virtualDestinationInterceptor:

<virtualTopic name="VirtualTopic.>" prefix="Consumer.*."   selectorAware="false"/>

There is also deadLetterStrategy to automatically create the dead letter queue by appending .Dead at the end of the queue name.

With that setup when a message is undelivered on a Virtual Topic consumers queue it is placed on a queue with the same name suffixed with .Dead.

On ActiveMQ Artemis we have reproduced that by setting the OpenWire parameter virtualTopicConsumerWildcards=Consumer.*.>;2.
The result it that when a consumer is listening on the queue Consumer.CLIENT_ID.VirtualTopic.QUEUE_NAME he receives messages sent to the address VirtualTopic.QUEUE_NAME. The corresponding FQQN is therefore VirtualTopic.QUEUE_NAME::Consumer.CLIENT_ID.VirtualTopic.QUEUE_NAME.

The dead letter mechanism is reproduced by configuring the broker with auto create dead letter resource and suffixing the created queue with .Dead:

<address-setting match="#">
    <dead-letter-address>DLQ</dead-letter-address>          
    <auto-create-dead-letter-resources>true</auto-create-dead-letter-resources>
    <dead-letter-queue-prefix></dead-letter-queue-prefix>
    <dead-letter-queue-suffix>.Dead</dead-letter-queue-suffix>
    ...
</address-setting>

The result is that when a message is not delivered it ends on the DLQ address on a queue with the name of the original address suffixed with .Dead. FQQN: DLQ::VirtualTopic.QUEUE_NAME.Dead.

Question: How can we send the undelivered messages to a dead-letter queue with the same name as the consumed queue: FQQN Consumer.CLIENT_ID.VirtualTopic.QUEUE_NAME::Consumer.CLIENT_ID.VirtualTopic.QUEUE_NAME?

I was hoping that a divert could hook in but that has not effect. The undelivered message is still ending on the DLQ address:

<diverts>     
    <divert name="virtualTopicDeadDivert">
        <address>DLQ</address>
        <forwarding-address>Consumer.CLIENT_ID.VirtualTopic.FunctionalTest.Dead</forwarding-address>
        <!--filter string="_AMQ_ORIG_QUEUE='Consumer.CLIENT_ID.VirtualTopic.QUEUE_NAME'"/-->
        <exclusive>true</exclusive>
    </divert>
</diverts>

Upvotes: 0

Views: 573

Answers (1)

Justin Bertram
Justin Bertram

Reputation: 35028

There is currently no way to send an undelivered message to a dead-letter address with a queue which is automatically created and named according to the queue where the message was originally sent.

This mismatch in behavior is a consequence of the naming convention and the semantics of virtual topics in ActiveMQ "Classic" combined with the semantics of the address model of ActiveMQ Artemis. To be clear, ActiveMQ Artemis is not meant to be a feature-for-feature reimplementation of ActiveMQ "Classic." Rather, it is a new implementation with features and abilities not possible on ActiveMQ "Classic" with equivalent (and sometimes identical) behavior where it makes sense.

Please note that virtual topics in ActiveMQ "Classic" were originally developed to deal with some of the shortcomings of JMS topic subscriptions in JMS 1.1. However, these limitations are already dealt with by the fundamental address model of ActiveMQ Artemis, but more importantly these limitations are already dealt with in JMS 2.0. ActiveMQ "Classic" doesn't yet support JMS 2.0, but ActiveMQ Artemis always has. You might consider moving a way from virtual topics and using JMS 2.0 instead.

Upvotes: 1

Related Questions