Why need messageId in AMQP? - amqp

In the Spring AMQP Project,
if messageProperties does not have messageId, they always create messageId.
Like This..
if (this.createMessageIds && messageProperties.getMessageId()==null) {
messageProperties.setMessageId(UUID.randomUUID().toString());
}
I want to know what messageId is. So, I try to find out where messageId is used. But I couldn't find it in Spring AMQP Source.
What happens if messageId does not exist?
Why is messageId needed in AMQP?

The message id is only created if the converter's createMessageIds is true - it is false by default.
It is normally not required, unless you are using stateful retry on the consumer side.
When using stateful retry and a delivery fails, the message is rejected and redelivered by the broker. Since RabbitMQ does not include the number of retries in a header, we have to keep track of how many times the delivery has been attempted so that we can give up after the maxAttempts is reached. The message id is used to look up the retry state for this message.

Related

How to set expiry for specific ActiveMQ queue

the documentation of ActiveMQ is giving me a hard time so you are my last hope :D
What i want:
An expiration date on messages in the outgoing queue. Messages in the incoming, DLQ and RTS Queue should stay for ever.
So expiration is always 0 except when a message is put in the outgoing queue. Then ActiveMQ has to set a new expiration day. Alternatively this could also be set by the Application
Or alternatively (maybe easier):
An expiration date on messages in the outgoing and incoming queue. Messages in the DLQ and RTS Queue should stay for ever.
So expiration is always 12345 (or so) except when a message is transfer to RTS or DLQ. Then ActiveMQ has to set the new expiration day to 0
What i tried:
Setting an expiry date for the outgoing messages explicitly in the
application message.setJMSExpiration(XYZ); however, the
expiration date was then always set to 0. Probably because of the
spring jms lib
Configure the deadLetterStrategy so all messages in the DLQ get a expiration of 0. But seems to have no effect. probably misconfigured
<deadLetterStrategy>
<individualDeadLetterStrategy
processNonPersistent="true"
queuePrefix="DLQ."
useQueueForQueueMessages="true"
processExpired="false"
expiration="0"/>
</deadLetterStrategy>
Maybe you can help me :)
Thank you in advance
Spring-jms:5.3.20
ActiveMQ:5.15.15
The JMS Message setJMSExpiration is explicitly documented as bit being meant for use by the user so that explains why calling it isn't working for you.
This method is for use by JMS providers only to set this field when a message is sent. This message cannot be used by clients to configure the expiration time of the message. This method is public to allow a JMS provider to set this field when sending a message whose implementation is not its own.
To define a time to live for the message you either need to use the JMS Producer method setTimeToLive or the send method that allows you to provide the TTL value on a per message basis.
Alternatively you can configure the ActiveMQ Timestamp Plugin to apply a TTL value to each incoming message.
If you want expired messages to go into the DLQ then I'd suggest not configuring the broker to not do that as you've done above by setting processExpired="false" as that is specifically telling the broker not to DLQ expired messages.

Retroactive Consumers in ActiveMQ JMS API

I'm investigating ActiveMQ to see if it will work for a project. The current use case I need to demonstrate is that late-joining subscribers will receive topics published prior to the creation of the subscription. It seemed that ActiveMQ Retroactive Consumers would satisfy this need, but I can't get the code to work.
ActiveMQConnectionFactory connectionFactory = new ActiveMQConnectionFactory("[url]");
Connection connection = connectionFactory.createConnection();
connection.start();
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
Destination destination = session.createTopic("testAddress?consumer.retroactive=true");
MessageProducer producer = session.createProducer(destination);
TextMessage message = session.createTextMessage("Hello, World!");
producer.send(message);
Thread.sleep(5000);
session.createConsumer(destination).setMessageListener(message2 -> processMessage(message2));
session.close();
connection.close();
connectionFactory.close();
All I'm trying to demonstrate here is that a topic can be published, and then some arbitrary amount of time later (eg. 5 seconds) a consumer can subscribe to the topic and receive the previous message.
As far as I can tell, the issue seems to be that creating the topic creates an address but doesn't create any associated queues. If I send a topic to the address before the queue is made (either in code or manually via the web interface to the broker), the message seems to be ignored and the "un routed message count" is immediately incremented.
The ActiveMQ documentation ( https://activemq.apache.org/retroactive-consumer ) doesn't provide any greater detail on how to set up a retroactive consumer than appending "?consumer.retroactive=true" when making the topic, so I wonder if there are some other configuration aspects I'm missing.
To my knowledge ActiveMQ Artemis doesn't support the retroactive consumer feature that 5.x does. The client side option just tells the broker you want it, but since Artemis doesn't handle that you won't see any difference from sending it. The feature itself in 5.x shouldn't be relied upon as a 100% stand in for a durable consumer, broker restart for instance will cause all those messages (of which the amount stored is finite) to be lost.
If you want to guarantee that you get messages sent when the topic consumer is offline then a durable consumer is the safe way to do this
To accomplish the desired behavior (a subscriber receives topics that were published before the subscription was made) in ActiveMQ Artemis, I used a Last Value Queue with non-destructive reads. This has the limitation that I'm only receiving only the most recent copy of a topic published, but that will work for my situation.

Do messages get deleted from the queue after a read operation in IBM MQ?

I am using Nifi to get data from IBM MQ. It is working fine. My question is once the message is read from an MQ queue, does it get deleted from the queue? How to just read messages from the queue without deleting them from the queue?
My question is once the message is read from an MQ queue, does it get
deleted from the queue?
Yes, that is the default behavior.
How to just read messages from the queue without deleting them from
the queue?
You use the option: MQGMO_BROWSE_FIRST followed by MQGMO_BROWSE_NEXT on the MQGET API calls.
You can also open the queue for browse only. i.e. MQOO_BROWSE option for MQOPEN API call.
It sounds as if you would like to use a "publish/subscribe" model rather than a "point-to-point" model.
From ActiveMQ:
Topics In JMS a Topic implements publish and subscribe semantics. When
you publish a message it goes to all the subscribers who are
interested - so zero to many subscribers will receive a copy of the
message. Only subscribers who had an active subscription at the time
the broker receives the message will get a copy of the message.
Queues A JMS Queue implements load balancer semantics. A single
message will be received by exactly one consumer. If there are no
consumers available at the time the message is sent it will be kept
until a consumer is available that can process the message. If a
consumer receives a message and does not acknowledge it before closing
then the message will be redelivered to another consumer. A queue can
have many consumers with messages load balanced across the available
consumers.
If you have a queue, when a consumer consumes that message, it is removed from the queue so that the next consumer consumes the next message. With a topic, multiple consumers can be subscribed to that topic and retrieve the same message without being exclusive.
If neither of these work for you, I'm not sure what semantics you're looking for -- a "queue" which doesn't delete the message when it is consumed will never let a consumer access any but the first message.

JMS topic time dependency

I don't quite understand what this means:
Each message may have multiple subscribers. There are time
dependencies that exist between publishers and subscribers;
subscribers to a topic may only consume messages
published after a subscription was created.
What does it mean that there exists "time dependencies"? The above says that "subscribers may only consume messages after a subscription was created", I think I'm missing something vital here because I understood that as a subscriber cannot consume a message that is not yet created (but isn't this common sense).
I couldn't find any explanation on Google, so thank you for any help!
Edit: I found an excellent channel on youtube explaining spring boot and other technologies. In particular, this video helped me understand the difference between Queue and Topic (also what durable subscriber is).
What does it mean that there exists "time dependencies"?
To understand this better, compare it with a JMS Queue in which the message broker preserves all the messages (till TimeToLive expiration) published by the producer even if there are NO consumers CREATED.
Now, coming to a JMS topic, the message broker DOES NOT preserve the messages published by the producer if there are NO subscribers CREATED.
During the creation of topic subscription, you can tell the Message Broker that I don't want to loose the messages for this topic published FROM NOW ON by creating the Topic subscription as non-durable (using topicSession.createDurableSubscriber() method). Again, even in the case of non-durable subscription, the broker preserves the messages published after (subscription creation time) till TimeToLive expiration.
Simply that if you publish messages in to the topic before the consumer has subscribed, they will not see the messages.
Similarly, this is related to persistent subscribers. Normal subscribers only see messages while they are connected to the broker. Any messages before or after the subscriber has disconnected, will not be see by the subscriber.
However, with a persistent subscription, a subscriber can disconnect, yet the broker will continue to keep messages destined for that subscriber. When the subscriber reconnects, it will fetch all of those stored messages as well as any new ones.

Spring integration - message store recovery/resend

I have a question regarding the behavior of a jdbc message store. I notice that if a failure occurs for instance if the following sequence is followed:
1)inbound-channel-adapter - Creates a message payload and sends it to a channel
2)The channel is polled for the payload by a jms:outbound-channel-adapter which adds an entry in the JMS queue. I am using ActiveMQ.
When I test for a situation like shutting down the MOM I would like to persist the message in the message-store, but this is not the default behavior. Looks like SI processes the payload in the channel and then pushes it out (deletes it from the store). I can see the message being inserted in the message-store in the database.
Am I wrong in understanding the function of a message-store? I thought that the message would persist until a successful run. Thanks for any feedback.
You need to set up durable subscriptions for that. I think most of the SI JMS components do support that.

Resources