How to set expiry for specific ActiveMQ queue - spring

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.

Related

How to clear messages from a JMS Topic based on age of messages

We have an application that publishes event notifications to a JMS Topic. The issue noticed here is that after a considerable amount of time, the message store in Weblogic reaches more that 10GB in size. Is there a way to implement a component that can remove messages from a JMS Topic which have crossed a certain age (say 30 days)?
Currently in place is a process, during downtime activity the message store is deleted. The process however, has a prerequisite check from the owners of the subscribing applications whether actions based on last message have been processed or not.
Thanks
Message accumulation for a JMS topic indicates there is at least one inactive durable subscription or perhaps slow subscription consumers. In general, you can prevent this by removing inactive durable subscriptions, speeding up slow subscription consumers, slowing down message production so that consumers can keep up, etc.
If you don't want to retain messages older than 30 days then you can try using the "Message Time-To-Live" functionality defined by the JMS specification. Section 4.8 of the JMS 1.1 spec states:
A client can specify a time-to-live value in milliseconds for each message it
sends. This value defines a message expiration time that is the sum of the
message’s time-to-live and the GMT it is sent (for transacted sends, this is the
time the client sends the message, not the time the transaction is committed).
A JMS provider should do its best to expire messages accurately; however, JMS
does not define the accuracy provided. It is not acceptable to simply ignore
time-to-live.
For more information on message expiration, see Section 3.4.9
"JMSExpiration."
The message's time-to-live can be set when the message is sent using either javax.jms.MessageProducer.setTimeToLive(long) or one of the overloaded send() methods. This will, of course, require changing the sending application's code.
Many brokers support setting the message's time-to-live or expiration time on the broker so that client modifications aren't strictly necessary. I'm not familiar enough with Weblogic to know if it supports this functionality or not, but it's worth investigating if you want to use this solution and don't want to modify your clients.
Came across the following code, which can help in clearing the messages by browsing thru the queue.
queue browser

Apache ActiveMQ Artemis Durable Subscription TTL

I would like to configure a durable topic, but I want to configure how long Apache ActiveMQ Artemis will hold onto a message for an inactive durable subscriber to the topic.
For example, something like "Save durable messages for up to 30 seconds for inactive durable subscribers". If the subscriber does not become active within 30 seconds, the message is no longer available for them when they do become active.
Is this something that can be done? If not, does Artemis or JMS provide an alternative way to accomplish this or something similar.
ActiveMQ Artemis doesn't have exactly the functionality you're looking for, but you can get close using the expiry-delay address-setting which will apply an expiration time to message which don't already have their expiration time set. See the configuration details in the documentation. This will ensure that messages expire rather than accumulating in the inactive durable subscription.

How can I make sure that if a message is not consumed from a JMS queue, it should get deleted after a certain time?

I want the messages to get deleted from the JMS queue if they are not consumed within a certain time limit. What attribute or setting should I configure in while creating the queue?
I have tried expiry but even after the expiry time, I can see the message in the queue
Some JMS implementations will expire messages on queue, but some drop expired messages when consumed. So even though you can see an expired message in the queue, it should not be received by any messages receiver.

Removing a message that is being redelivered

I have a set up of an ActiveMQ broker and a single consumer. Consumer gets a message that he is not able to process because a service that it depends has a bug (once fixed it will be fine). So the message keeps being redelivered (consumer redelivery) - we use JMS sessions. With our current configuration it will keep redelivering it every 10 minutes for 1 day. That obviously causes a problem because other messages are not being consumed.
In order to solve this problem I have accessed the queue through JMX and tried to delete that message but it is not there. I guess it is cached on the consumer and not visible at the broker.
Is there any way to delete this message other than restarting the application?
Is it possible to configure the redelivery mechanism so that such message (that causes a live lock eventually) is put at the end of the queue so that other messages can be processed?
The 10 minutes for 1 day redelivery policy should stay as is.
I think you're right that the messages are stuck in the consumer's prefetch buffer, and I don't know of a way to delete them from there.
I'd change your redelivery policy to send to the DLQ after the second failure, with a much shorter interval between them, like 30 seconds, and I'd configure the DLQ strategy as an individualDeadLetterStrategy so you get a separate DLQ containing only messages from this particular queue. Then set up a consumer on this DLQ to move the messages to (the end of) the main queue whenever your reprocessing condition is met (whether that's after a certain delay, or based on reading some flag value from a database, or whatever). This consumer is where you'd implement "every 10 minutes for 1 day" logic, instead of in the redelivery policy where you currently have it.
That will keep the garbage ones out of the main queue so they don't delay other messages from being consumed, but still ensure that they will be reprocessed later. And it will put them on the broker instead of in the consumer's prefetch buffer, where you can view and delete them.
The only way to get it to the back of the queue is to reproduce it to the queue. Redelivery polices can only be configured down to the destination on the connection factory.
Given that you already have a connection, it shouldn't be to hard to create a producer that can either move the given message to a DLQ or produce it back to the queue when you run into that particular bug.
Setting jms.nonBlockingRedelivery=true on the connection factory resolved the problem. Now even if there is a message redelivered it does not block processing of other Messages.

Blocking competing clients to take message from ActiveMQ

We have a JMS queue and multiple competing clients are reading from this queue.
Once the message is taken and successfully processed, we want to send the acknowledge to delete ( i.e. CLIENT ACKNOWLEDGE )
However, we want to make sure that if one client has picked the message another client should not take it from the queue.
Does activeMQ provide this feature out of the box using some configuration ?
Moreover:
If the message processing failed after picking the message, so it could not be acknowledged back, in this scenario we should like other client thread to pickup the message. Is it possible out of the box with configuration , may be specifying timeout values ?
Regards,
JE
You need to take some time to understand the difference between a Topic and a Qeueue in order to understand why the first question is not an issue.
For the second question it depends a bit on the ACK mode you are using and how you are processing messages sync or async. Normally for processing where you want to control redeliveries you would do the work inside of a transaction and if the processing fails the message would be redelivered when the TX is rolled back. ActiveMQ supports redelivery policies both client side and broker side that control how many time a message will be redelivered before sent to a DLQ.

Resources