Reputation: 922
I'm consuming messages from an ActiveMQ Artemis topic using JMS. My consumers are connecting directly to the FQQN of their consumer queues. Like this:
jmsTemplate.setDefaultDestinationName("Transactions.Client1::ConsumerA");
And the configuration in the broker.xml
is:
<address-setting match="Transactions.*">
<auto-create-dead-letter-resources>true</auto-create-dead-letter-resources>
<dead-letter-address>Transactions.Retry</dead-letter-address>
</address-setting>
But then, the name of the DLQ will be DLQ.Transactions.Client1
, without the consumer name.
What I need is that each consumer has its own DLQ. Something like DLQ.Transactions.Client1.ConsumerA
. Is this possible?
EDIT:
When I say "consumer", it may (actually) be more like a "consumer group". For example, ConsumerA
and ConsumerB
are two totally different applications, with (possibly) multiple running instances and managed by its own team. That's why I want a different DLQ for each one.
Upvotes: 1
Views: 1192
Reputation: 922
Justin Bertram's answer is probably what most people should do. It is what I would have done if wasn't for the requirements of having different dead letter address and expiry address per consumer application.
In my case, I solved it using Diverts.
First, the producer wasn't changed. It keeps posting to the topic Transactions.Client1
.
Then, I configured a divert in the broker.xml
file:
<divert name="Transactions.Divert">
<address>Transactions.Client1</address>
<forwarding-address>Transactions.Client1.ConsumerA</forwarding-address>
<exclusive>false</exclusive>
</divert>
IMPORTANT: The downside is that it doesn't scale. If I have N clients and M consumers, I'll have N×M diverts.
Then, the address-settings was changed to (note the two asterisks in the match attribute):
<address-setting match="Transactions.*.*">
<auto-create-dead-letter-resources>true</auto-create-dead-letter-resources>
<dead-letter-address>Transactions.Retry</dead-letter-address>
</address-setting>
So, when the processing of a message fails, at the address Transactions.Retry
will be created a queue named DLQ.Transactions.Client1.ConsumerA
.
And everybody is happy, except the ops guy, who will have to configure more than a hundred diverts in production. I hope his vim-fu is OK.
PS: Just a tip: Always divert to addresses with same prefix (in the example it is "Transactions"). It will make your life much easier when you have to configure a cluster in production.
Upvotes: 0
Reputation: 35038
It's not possible to configure the broker to auto-create a dead-letter queue whose name contains the name of the queue where the message was originally sent. As noted in the documentation, the dead-letter queue is named according to the address where the message was originally sent along with any configured prefix and/or suffix.
However, the message itself will have a property named _AMQ_ORIG_QUEUE
which will contain the name of the queue where the message was originally routed. This means you can use a consumer with a message selector (e.g. _AMQ_ORIG_QUEUE = 'ConsumerA'
) so that the consumer will only receive messages which were originally routed to a particular queue. This is functionally equivalent to having a dead-letter queue per-queue.
For what it's worth, what you're calling the "consumer name" isn't the name of the consumer at all, at least not from the broker's point of view. It's just the name of the queue.
Ultimately it's just not possible to configure a dead-letter queue per-queue. It's only possible to configure a dead-letter queue per address. This is true whether the resources are create manually (e.g. via broker.xml
) or automatically.
Upvotes: 2