[
https://issues.apache.org/jira/browse/CAMEL-25724?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
]
Work on CAMEL-25724 started by shashank.
----------------------------------------
> camel-jms - with preserveMessageQos=true a message without JMSExpiration is
> sent with no time to live, ignoring the endpoint timeToLive and, for
> request/reply, the requestTimeout, so stale messages never expire
> ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
>
> Key: CAMEL-25724
> URL: https://issues.apache.org/jira/browse/CAMEL-25724
> Project: Camel
> Issue Type: Bug
> Components: camel-jms
> Reporter: shashank
> Assignee: shashank
> Priority: Major
>
> The {{preserveMessageQos}} option is documented as: "The following three
> headers are considered JMSPriority, JMSDeliveryMode, and JMSExpiration. You
> can provide all or only some of them. If not provided, Camel will fall back
> to use the values from the endpoint instead."
> {{JmsConfiguration.CamelJmsTemplate.doSend}} (main e339a2e9019f) does that
> for the priority, but not for the time to live:
> {code:java}
> if (config.isPreserveMessageQos()) {
> long ttl = message.getJMSExpiration();
> if (ttl != 0) {
> ttl = ttl - System.currentTimeMillis();
> if (ttl <= 0) {
> ttl = 1;
> }
> }
> int priority = message.getJMSPriority();
> if (priority < 0 || priority > 9) {
> // use priority from endpoint if not provided on a message with a
> valid range
> priority = this.getPriority();
> }
> ...
> producer.send(message, deliveryMode, priority, ttl);
> {code}
> A message without a {{JMSExpiration}} header has expiration 0, so it is sent
> with time to live 0, which in JMS means "never expires". The time to live of
> the template is never used on this path:
> * InOnly: {{to("jms:queue:orders?preserveMessageQos=true&timeToLive=60000")}}
> sends messages that never expire.
> * InOut: {{createInOutTemplate}} sets the {{requestTimeout}} (default 20 s)
> as time to live of the template ("About time to live" in the component page),
> but with {{preserveMessageQos=true}} the requests are sent without it. A
> request whose caller already timed out stays on the queue and is processed
> later, and requests pile up when the server is down.
> There is no error and no log. Messages that come from another JMS endpoint
> usually carry their own {{JMSExpiration}}; the defect hits messages created
> by Camel (from a file, HTTP, timer, ...) and the typical reason to use the
> option, setting only a {{JMSPriority}} header.
> Trigger: {{preserveMessageQos=true}} and a message without {{JMSExpiration}}
> (or 0), with {{timeToLive}} set (InOnly) or with request/reply (any
> {{requestTimeout}} > 0, the default) and {{disableTimeToLive=false}} (the
> default).
> h3. Reproduction
> New test {{JmsPreserveMessageQosTimeToLiveTest}} (6 tests, embedded Artemis
> and a mocked {{MessageProducer}}). Three fail on main:
> * {{jms:queue:qos?preserveMessageQos=true&timeToLive=5000}}, message without
> expiration: {{MessageProducer.send}} gets time to live 0, expected 5000;
> * InOut template of {{jms:queue:qos?preserveMessageQos=true}} (default
> requestTimeout 20000): time to live 0, expected 20000;
> * a route
> {{from("direct:start").to("activemq:queue:X?preserveMessageQos=true&timeToLive=600000")}}
> on the embedded broker: the received message has {{JMSExpiration}} 0,
> expected about now + 10 minutes.
> Three more pass on main and guard the parts that must not change: a message
> with an expiration keeps its remaining time; {{disableTimeToLive=true}} sends
> 0; an endpoint without timeToLive sends 0.
> A Z3 model of the chain (template time to live, header, {{exp - now}} with
> the {{<= 0}} clamp, 64-bit) gives the counterexamples above and shows that
> the fix meets the documented fallback for every input in realistic ranges,
> and changes nothing when the message has an expiration or the InOnly endpoint
> has no time to live.
> h3. Proposed fix
> When the message has no expiration, use the time to live of the template
> ({{this.getTimeToLive()}}), which is the endpoint {{timeToLive}} (InOnly),
> {{timeToLive}}/{{requestTimeout}} (InOut), and 0 when none is configured or
> {{disableTimeToLive=true}}. Four lines in {{doSend}}; the camel-jms tests
> pass with it (452 + 16 + 6 run in the three surefire executions, 0 failures,
> 0 errors, 11 skipped). Note for the 4.24 upgrade guide: such messages now
> expire; {{disableTimeToLive=true}} keeps the old behaviour. A message bridged
> from another JMS endpoint with expiration 0 also gets the endpoint value,
> because the producer cannot tell a 0 header from a missing one (the priority
> has the same limit).
> Same code, not changed here: camel-sjms {{SjmsTemplate.send}} (the
> {{preserveMessageQos}} branch ignores the endpoint {{timeToLive}} the same
> way).
> Affected: main (tested); camel-4.23.x, camel-4.22.x, camel-4.18.x and
> camel-4.14.x have the same lines (read, not run).
> Duplicate check (2026-10-17): JIRA text "preserveMessageQos timeToLive",
> "preserveMessageQos JMSExpiration", "requestTimeout header time to live",
> summaries with "time to live": CAMEL-3743, CAMEL-4124, CAMEL-17912 (delivery
> mode and priority), CAMEL-7026 (request timeout header), none about this.
> GitHub pull requests "preserveMessageQos", "camel-jms timeToLive": none about
> this.
> _Filed with Claude Code on behalf of allthingssecurity._
--
This message was sent by Atlassian Jira
(v8.20.10#820010)