allthingssecurity opened a new pull request, #28590: URL: https://github.com/apache/camel/pull/28590
# Description [CAMEL-26082](https://issues.apache.org/jira/browse/CAMEL-26082) `SjmsEndpoint.createInOnlyTemplate` never calls `template.setPreserveMessageQos(...)`; only `createInOutTemplate` does (since CAMEL-17912 added the option). So with `preserveMessageQos=true` an InOnly send takes the plain `producer.send(message)` branch of `SjmsTemplate.send`, which sends with the defaults of the `MessageProducer` (or the endpoint QoS with `explicitQosEnabled`). The binding does set `JMSPriority`, `JMSDeliveryMode` and `JMSExpiration` on the JMS message, but `MessageProducer.send(Message)` overrides them. The option, documented as "send message using the QoS settings specified on the message", has no effect for InOnly, the common case: a message with a `JMSExpiration` in the past is delivered and processed, `JMSPriority` is ignored, and a message with `JMSDeliveryMode` NON_PERSISTENT is sent persistent. camel-jms and camel-amqp pass the option to both templates and honour the headers (same scenario run against all three with an embedded Artemis broker). Changes: - `SjmsEndpoint.createInOnlyTemplate` passes `preserveMessageQos` to the template, as `createInOutTemplate` does. The InOnly template is also the one a consumer uses for its replies, so the replies of a consumer endpoint with `preserveMessageQos=true` now use the headers of the reply message, as in camel-jms. - `SjmsTemplate.send` (the `preserveMessageQos` branch): a message without `JMSExpiration` (header missing or 0) gets the time to live of the endpoint (`timeToLive`, or the `requestTimeout` for request/reply), which is 0 (never expires) when none is configured. This is the same change CAMEL-25724 made in camel-jms. Without it the first change would drop the `timeToLive` of InOnly endpoints that set both options (`timeToLive` turns on `explicitQosEnabled`, and `preserveMessageQos` wins over it in `send`): such messages would no longer expire. For request/reply it means a request without `JMSExpiration` now expires after `requestTimeout`, as it does without `preserveMessageQos`; `disableTimeToLive=true` (with no `timeToLive` on the endpoint) still sends it without time to live. - `SjmsTemplate.send` (the `preserveMessageQos` branch): without a `JMSPriority` or `JMSDeliveryMode` header, the priority and delivery mode of the endpoint (`priority`, `deliveryPersistent`/`deliveryMode`) are used, as the option description says ("If not provided, Camel will fall back to use the values from the endpoint instead"). Before, the branch took them from the new JMS message, which always has them: the sjms binding sets `JMSDeliveryMode` PERSISTENT on every message it creates, and the priority is the default of the JMS client (4 with Artemis; 0 with the ActiveMQ Classic client, javap of activemq-client 6.3.2: `ActiveMQMessage.getJMSPriority()` returns the `priority` byte of `Message`, which neither its constructor nor `ActiveMQSession.configureMessage` sets). With only the first change, an InOnly endpoint with `preserveMessageQos=true`, `deliveryPersistent=false` and `priority=7` would have sent its messages without headers persistent and with priority 4 (Artemis) or 0 (ActiveMQ Classic). To know whether the route set a header, `SjmsTemplate.send` now gets the Camel message the JMS message was made from (new overload; the old `send(MessageProducer, Message)` keeps the previous behaviour). The producer passes the In message, and the consumer passes the reply message. The sjms binding always creates a new JMS message, so there is no consumed JMS message whose values could be mistaken for headers. - camel-sjms2 inherits all of this: `Sjms2Endpoint` extends `SjmsEndpoint` and does not override the template factories. - Upgrade guide 4.24: `camel-sjms - preserveMessageQos also applies to InOnly sends`, right after the camel-jms entry of CAMEL-25724. It names the fallback to the endpoint for a header that is not set, and the change for request/reply (before, a request without header took the priority of the new JMS message and was always persistent). - No option or generated file change. - Backport: camel-4.22.x, 4.18.x and 4.14.x have the same `createInOnlyTemplate` (read, not run). This changes what users see, so I would keep it on main unless you prefer otherwise. Tests: - New `InOnlyPreserveMessageQosTest` (embedded Artemis through the module's `JmsTestSupport`, the broker and client the module tests with), 9 tests, MockEndpoint expectations as in the module's other producer tests. 7 fail on main (logs: run with the main version of the three changed classes): - `priorityAndDeliveryModeFromTheHeadersAreUsed`: `header(JMSPriority) == 8 evaluated as: 4 == 8`. - `headersWinOverTheEndpoint`: headers `JMSPriority` 2 and `JMSDeliveryMode` PERSISTENT on an endpoint with `priority=7&deliveryPersistent=false`; on main `header(JMSPriority) == 2 evaluated as: 7 == 2`. - `expirationFromTheHeaderIsUsed`: the received `JMSExpiration` is 0 on main. - `anExpiredMessageIsNotDelivered`: a message with a `JMSExpiration` one minute in the past, then a fresh one, are sent before the consumer route starts; only the fresh one may arrive. On main: `Expected: <Fresh> but was: <Stale>`. - `requestTimeoutIsUsedForARequestWithoutExpiration`: InOut with `preserveMessageQos=true` and no `JMSExpiration`; the request must carry the `requestTimeout` as time to live. On main its `JMSExpiration` is 0. - `requestUsesThePriorityAndDeliveryModeOfTheEndpointWithoutHeaders`: InOut with `preserveMessageQos=true&priority=7&deliveryPersistent=false` and no headers; on main `header(JMSPriority) == 7 evaluated as: 4 == 7`. - `replyOfAConsumerUsesThePriorityHeader`: a consumer endpoint with `preserveMessageQos=true` whose route sets `JMSPriority` 9 on the reply; on main the reply arrives with `expected: <9> but was: <4>`. - Two tests pass on main, where an InOnly send uses the endpoint QoS; they are the controls for the fallbacks: - `timeToLiveOfTheEndpointIsUsedForAMessageWithoutExpiration` fails with only the `createInOnlyTemplate` line (`JMSExpiration` 0). - `priorityAndDeliveryModeOfTheEndpointAreUsedWithoutHeaders` (InOnly, `priority=7&deliveryPersistent=false`, no headers) fails with the previous version of this branch, which took them from the JMS message: `header(JMSPriority) == 7 evaluated as: 4 == 7`. - Unit tests with the fix: camel-sjms 148 run, 0 failures, 5 skipped; camel-sjms2 23 run, 0 failures. The formatter and import-sort plugins ran. Not changed (follow-up JIRA I can file): camel-jms has the same gap in its `preserveMessageQos` branch (`JmsConfiguration.CamelJmsTemplate.doSend`): without a `JMSPriority` or `JMSDeliveryMode` header it takes the priority of the JMS message (0 for a new message with the ActiveMQ Classic client) and its delivery mode (PERSISTENT, set by the binding) instead of the endpoint values. Its binding can reuse a consumed JMS message, so the fix there needs more care than here. # Target - [x] I checked that the commit is targeting the correct branch (Camel 4 uses the `main` branch) # Tracking - [x] If this is a large change, bug fix, or code improvement, I checked there is a [JIRA issue](https://issues.apache.org/jira/browse/CAMEL) filed for the change (usually before you start working on it): [CAMEL-26082](https://issues.apache.org/jira/browse/CAMEL-26082). # Apache Camel coding standards and style - [x] I checked that each commit in the pull request has a meaningful subject line and body. - [ ] I have run `mvn clean install -DskipTests` locally from root folder and I have committed all auto-generated changes. (I built camel-sjms and ran its tests, including the formatter and import-sort plugins. No generated file changes. I did not run the full root build.) # AI-assisted contributions - [x] If this PR includes AI-generated code, commits have proper co-authorship attribution (e.g., `Co-authored-by` trailers) and the PR description identifies the AI tool used. This PR was prepared with Claude Code (Claude Opus 5.5). The commit carries a `Co-Authored-By` trailer. _Claude Code on behalf of allthingssecurity_ 🤖 Generated with [Claude Code](https://claude.com/claude-code) -- This is an automated message from the Apache Git Service. To respond to the message, please log on to GitHub and use the URL above to go to the specific comment. To unsubscribe, e-mail: [email protected] For queries about this service, please contact Infrastructure at: [email protected]
