ActiveMQ Artemis message id - activemq-artemis

I'm working on the migration from ActiveMQ 5.0 to ActiveMQ Artemis. I see that the message Id format has changed. 5.0 was using the client Id as a prefix whereas Artemis seems to be using a kind of sequence.
Is there a way to control the message id somehow?
It's very convenient to deduce the producer from the ID.

In short, there is no user-configurable way to control the JMSMessageID.
For what it's worth, the ability to deduce the producer from the JMSMessageID is a quirk of the OpenWire JMS client implementation. As described in the JMS specification, the client implementation (i.e. the JMS "provider") sets the JMSMessageID on the message when it is sent. The OpenWire JMS client shipped with ActiveMQ 5.x uses the producer ID (which can include the client ID) and a sequence number to generate this value. The core JMS client shipped with ActiveMQ Artemis uses this method to generate a UUID value. The Qpid JMS client (which uses AMQP 1.0 and is also supported by ActiveMQ Artemis) uses another method still.
There is nothing in the JMS specification that requires a correlation between the producer and the JMSMessageID, and any such correlation would only work for that particular client implementation anyway. It wouldn't work for all the other kinds of clients supported by the broker (e.g. MQTT, STOMP, AMQP, etc.).
If you want to identify the producer which sent the message then I recommend you simply set a property on the message with the desired identification. This would work across all JMS client implementations.

Related

WildFly embedded ActiveMQ Artemis: Difference between queue and jms-queue

What is the difference between queue and jms-queue declaration in the server configuration in the activemq-messaging subsystem?
Could the queue be used with a MessageDriven bean instead of a jms-queue?
I'm using Wildlfy 19 and Artemis 2.12.0
ActiveMQ Artemis supports the JMS API, but it also supports industry standard protocols like AMQP, STOMP, OpenWire, & MQTT. Therefore the broker's underlying address model is not JMS-specific but rather more generic & flexible in order to support numerous different use-cases.
The bare queue refers to the underlying "core" queue from ActiveMQ Artemis. I believe WildFly exposes this low-level component to support unforeseen use-cases. The queue configuration gives control over the address and routing-type which are the other two main components of the ActiveMQ Artemis address model.
The jms-queue refers to the traditional JMS-based resource which MDBs and other JMS-based application components will use in a Java/Jakarta EE application server. It gives you control of JNDI entries which queue does not. It serves as a kind of familiar "wrapper" around the core queue. That's why there's so much overlap with the attributes and operations between the two.
There's really no reason to use queue in lieu of jms-queue unless you absolutely must. A jms-queue is more straight-forward to configure and understand for almost all use-cases. The only reason to use a queue is if you needed to control the address and routing-type in a way that isn't allowed by jms-queue. This is highly unlikely for JMS applications.
It is possible, for example, to send messages to or consumer a message from a queue, but since queue lacks a way to configure JNDI bindings the JMS client would have to instantiate the queue directly using javax.jms.Session.createQueue(String). However, this method is discouraged as it reduces the portability of the application.

ActiveMQ Artemis How to control the multicast queue name?

When a consumer subscribes to a topic, a multicast queue is automatically created with a system generated name. I'd like to know if it's possible to control this name generation to make it more friendly (like consumer_id + session_id + idx).
I was using the web console to monitor, and with the previous version of ActiveMQ (prior to Artemis) I used to see the consumer names for each subscription to a topic which was very convenient.
What I used to see in the web console with ActiveMQ 5.0:
What I see now in the console with Artemis:
These UUID named queues are temporary subscriptions that will be deleted as soon as the client disconnects.
The classic way of having named durable subscriptions of the form clientId.subscriptionName is to set clientId and subscriptionName properties on your client. Note that durable subscriptions will continue to get messages also when the subscriber disconnects.
With Artemis, you can also use the fully qualified queue names (FQQN) feature to achieve the same, but with the additional benefit of full control on the durable subscription name:
First, create a multicast address like this:
<address name="example.foo">
<multicast>
<queue name="q1"></queue>
<queue name="q2"></queue>
</multicast>
</address>
At this point, you can send messages to example.foo topic and consume them from example.foo::q1 and example.foo::q2 queues (note the :: separator).
It appears to me that you're not looking in the right place for consumer information in the ActiveMQ Artemis web console. Currently you're looking in the main navigation tree which shows "major" components like acceptors, addresses, queues, etc. Consumers do not appear here by design. Your screenshot of the ActiveMQ Artemis web console simply shows the multicast queues on an address. In the JMS topic use-case each subscriber gets their own queue typically called a "subscription queue". However, a subscription queue is not the same as a consumer. The consumer consumes from the subscription queue. If you want to see the corresponding consumers then you need to open the "Consumers" tab.
For example, here is a screen shot when 3 non-durable JMS subscribers are connected to a JMS topic named myTopic:
As you note, the names of the subscription queues don't really tell you much. However, if you click on the "Consumers" tab you will see a wealth of information, e.g.:
From the "Consumers" tab you can see where consumers are connecting from, what queue & address they're using, when they were created, their client ID, etc. If there are lots of consumers you can filter them based on, for example, the address or queue they're using.
It's important to note that ActiveMQ Artemis does not represent every consumer with an underlying JMX MBean. This is what ActiveMQ 5.x does and this can cause resource utilization problems with a large number of consumers since MBeans are fairly "heavy" objects.
Note: These screenshots were taken with the latest release (i.e. 2.16.0) which includes a newer version of the web console than the one you appear to be using in your screenshot.

How to read value of max-delivery-attempts from Java in a MessageListener

I have configured the redelivery settings in Wildfly 10 configuration some thing like below.
<address-setting name = "jms.queue.MyQueue"
redelivery-delay="2000" max-redelivery-delay="10000" max-delivery-attempts="5"
max-size-bytes="10485760" address-full-policy="FAIL"/>
I haven't configured the DLQ which I want to do myself.
When a message fails , I would like to move it to certain queue with the error in it. Unfortunately if I configure the DLQ, I only get the original message but not the reason why it failed.
For that I would like to read the JMSXDeliveryCount and decide if this is the last attempt. If so then Move it to some other queue myself with additional information.
is it possible to read the original setting as done in standalone-full.xml from my Queue while consuming the message?
The max-delivery-attempts setting is not defined in the JMS specification so in order to retrieve it from the server you'll need to use the Wildfly management API. There are a couple of ways to do this - native or HTTP. To be clear, this will make your application difficult to port to other potential JMS providers and/or Java application servers.
To avoid having to use the Wildfly management API you might consider setting a special property on the message from the producer to indicate how many times it should be delivered. Then you could just read this property in your consumer application and compare it to JMXSDeliveryCount. If you don't want to change the producer application you could probably accomplish the same thing using an Artemis outgoing interceptor to set the property on the message as it's being delivered to the consumer.

Hornetq Core Bridge - one publisher, multiple consumers

Server A publishes data to the topic source/topic and two durable subscribers sub-b and sub-c are configured to listen to the topic. Subscribers sub-b and sub-c will receive the identical data.
Is there a way to configure in HornetQ using multiple core bridges to publish message from sub-b channel to server B and from sub-c channel to server C.
As per the Horentq documentation they suggest to use core bridge instead of JMS bridge if possible.
It's always preferable to use a core bridge if you can.
bridgeType Schema definition does not seem to support to use subscriber name as in the case of JMS bridge bean definition.
The workaround I came up with is to use JMS but I was wondering if anyone came across this issue before and would you mind sharing your thoughts on this?
A JMS topic (i.e. source/topic) is represented in the broker simply as an address. A JMS subscription (i.e. sub-b and sub-c) is represented in the broker as a queue associated with the relevant address (source/topic in this case). The queues internal name is a combination of details from the JMS subscriber (e.g. client ID, subscription name, etc.). When a message is sent to the JMS topic the broker routes a reference to that message to each subscription so that every subscription gets every message (assuming their selectors match).
A core bridge listens for messages arriving in an queue and then forwards those messages to an address either locally or on a remote broker.
In your case, you can create a bridge which listens on the queue of the JMS subscription and then forwards that message to a remote broker of your choosing.

Apache Artemis: How to move JMS messages to a different queue

The new version of Artemis removed the class JMSQueueControl and all classes associated with it.
Our project uses the JMS API to send/receive/listen, as well as manage. We need to manage the queues, including moving messages from one queue to another by JMS message ID, which a GUID type of a String.
The new version of Artemis 2.2.0 has a QueueControl#moveMessage(long), which, apparently operates on an internal message ID (not the JMS message ID).
The question is: How to move messages from one queue to another using JMS message ID in Artemis version 2.X ?
You can use the management method:
org.apache.activemq.artemis.api.core.management.QueueControl#moveMessages(java.lang.String, java.lang.String)
It takes a "filter" as the first parameter. You can use the filter:
AMQUserID='<jmsMessageId>'
AMQUserID: This refers to an ID set by the user. In this case, it's the JMS message ID (i.e. an ID set by the JMS client). It doesn't refer to security credentials.
<jmsMessageId>: This is the message ID of the JMS message you want to move. This is what JMSQueueControl did behind the scenes in the first place.
To be clear, after adding support for AMQP, STOMP, and MQTT the JMSQueueControl (as well as all other JMS-specific management & configuration classes) was pulled out because it no longer made sense to have separate JMS-specific ways of doing the same things already offered by the core management API.