[
https://issues.apache.org/jira/browse/CAMEL-16039?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=18117998#comment-18117998
]
Federico Mariani edited comment on CAMEL-16039 at 9/22/26 12:03 PM:
--------------------------------------------------------------------
Design agreed on the dev list (thread "Batch processing JMS messages", Sept
2026), superseding the original 2021 request for a port of the removed
{{sjms-batch}} component.
*Shape*: a {{batching}} option on the existing {{camel-sjms}} consumer, not a
new component, following the camel-kafka batching consumer (CAMEL-16064).
{{camel-sjms2}} inherits it for free, since {{Sjms2Endpoint extends
SjmsEndpoint}}.
{code:java}
from("sjms:queue:orders?batching=true&batchSize=500&batchTimeout=1000&transacted=true")
.process(this::toRows) // List<Exchange> -> rows
.to("sql:INSERT INTO orders (id, payload) VALUES (:#id,
:#payload)?batch=true");
{code}
*Mechanics*: a new {{MessageListenerContainer}} (camel-sjms already has that
SPI alongside {{SimpleMessageListenerContainer}}) creates a session and a
{{MessageConsumer}} once and holds both for the consumer's lifetime. On its own
thread it loops {{consumer.receive(...)}}, accumulating exchanges until
{{batchSize}} or {{batchTimeout}}, then dispatches one batch exchange to the
route synchronously and commits or rolls back the same session on the same
thread. {{SjmsHelper.commitIfNeeded}} already handles both {{session.commit()}}
and {{CLIENT_ACKNOWLEDGE -> message.acknowledge()}}, so the new part is really
the receive loop.
*Options*:
* {{batching}} (boolean, default false) - same name as camel-kafka.
* {{batchSize}} (int) - camel-kafka calls this {{maxPollRecords}}, which is a
verbatim passthrough of the Kafka client property and means nothing in JMS.
* {{batchTimeout}} (duration) - camel-kafka needs two knobs ({{pollTimeoutMs}}
+ {{batchingIntervalMs}}) because Camel is not in control during {{poll()}}.
JMS does not have that problem: {{receive(timeout)}} returns on a deadline of
our choosing, so one knob gives an exact bound.
* Body is {{List<Exchange>}}, as in camel-kafka, so {{.split(body())}} works
the same way. An optional {{aggregationStrategy}} may be added later for routes
written against the old {{sjms-batch}}.
*Deliberately not included*: {{breakOnFirstError}} and {{allowManualCommit}}.
In camel-kafka's batching mode {{breakOnFirstError}} commits the failed batch
so the consumer can move forward; in JMS that means acknowledging a batch you
failed to process, i.e. losing it. On failure the session is rolled back and
the broker redelivers all N with {{JMSRedelivered=true}}, so routes need to be
idempotent. A single-message fallback for poison batches can come later.
*Scope*: limited to InOnly exchanges. {{AUTO_ACKNOWLEDGE}} with batching is
at-most-once for the whole batch and should be rejected or warned about. No XA
- camel-sjms does not support JTA.
*Status*: [~mionker] has a working implementation (three classes in
{{org.apache.camel.component.sjms.consumer}} plus tests) and intends to
contribute it. Reviewed against current {{main}}: it applies cleanly and its
tests pass. Open points being worked: recovery of the session/consumer and the
receive loop after a {{JMSException}}, routing errors to the consumer's
{{ExceptionHandler}}, guarding a non-positive {{batchTimeout}}, and component
documentation.
Related: CAMEL-24797 (Splitter unwraps {{Exchange}} parts) is resolved, so
{{.split(body())}} over the batch body now yields child exchanges with the
record body and headers.
was (Author: JIRAUSER298805):
Design agreed on the dev list (thread "Batch processing JMS messages", Sept
2026), superseding the original 2021 request for a port of the removed
{{sjms-batch}} component.
*Shape*: a {{batching}} option on the existing {{camel-sjms}} consumer, not a
new component, following the camel-kafka batching consumer (CAMEL-16064).
{{camel-sjms2}} inherits it for free, since {{Sjms2Endpoint extends
SjmsEndpoint}}.
{code:java}
from("sjms:queue:orders?batching=true&batchSize=500&batchTimeout=1000&transacted=true")
.process(this::toRows) // List<Exchange> -> rows
.to("sql:INSERT INTO orders (id, payload) VALUES (:#id,
:#payload)?batch=true");
{code}
*Mechanics*: a new {{MessageListenerContainer}} (camel-sjms already has that
SPI alongside {{SimpleMessageListenerContainer}}) creates a session and a
{{MessageConsumer}} once and holds both for the consumer's lifetime. On its own
thread it loops {{consumer.receive(...)}}, accumulating exchanges until
{{batchSize}} or {{batchTimeout}}, then dispatches one batch exchange to the
route synchronously and commits or rolls back the same session on the same
thread. {{SjmsHelper.commitIfNeeded}} already handles both {{session.commit()}}
and {{CLIENT_ACKNOWLEDGE -> message.acknowledge()}}, so the new part is really
the receive loop.
*Options*:
* {{batching}} (boolean, default false) - same name as camel-kafka.
* {{batchSize}} (int) - camel-kafka calls this {{maxPollRecords}}, which is a
verbatim passthrough of the Kafka client property and means nothing in JMS.
* {{batchTimeout}} (duration) - camel-kafka needs two knobs ({{pollTimeoutMs}}
+ {{batchingIntervalMs}}) because Camel is not in control during {{poll()}}.
JMS does not have that problem: {{receive(timeout)}} returns on a deadline of
our choosing, so one knob gives an exact bound.
* Body is {{List<Exchange>}}, as in camel-kafka, so {{.split(body())}} works
the same way. An optional {{aggregationStrategy}} may be added later for routes
written against the old {{sjms-batch}}.
*Deliberately not included*: {{breakOnFirstError}} and {{allowManualCommit}}.
In camel-kafka's batching mode {{breakOnFirstError}} commits the failed batch
so the consumer can move forward; in JMS that means acknowledging a batch you
failed to process, i.e. losing it. On failure the session is rolled back and
the broker redelivers all N with {{JMSRedelivered=true}}, so routes need to be
idempotent. A single-message fallback for poison batches can come later.
*Scope*: limited to InOnly exchanges. {{AUTO_ACKNOWLEDGE}} with batching is
at-most-once for the whole batch and should be rejected or warned about. No XA
- camel-sjms does not support JTA.
*Status*: [~mionker] has a working implementation (three classes in
{{org.apache.camel.component.sjms.consumer}} plus tests) and intends to
contribute it. Reviewed against current {{main}}: it applies cleanly and its
tests pass. Open points being worked: recovery of the session/consumer and the
receive loop after a {{JMSException}}, routing errors to the consumer's
{{ExceptionHandler}}, guarding a non-positive {{batchTimeout}}, and component
documentation.
Related: CAMEL-24797 (Splitter unwraps {{Exchange}} parts) is resolved, so
{{.split(body())}} over the batch body now yields child exchanges with the
record body and headers.
_Claude Code on behalf of Federico Mariani_
> Reinstate Batch JMS Processing
> ------------------------------
>
> Key: CAMEL-16039
> URL: https://issues.apache.org/jira/browse/CAMEL-16039
> Project: Camel
> Issue Type: New Feature
> Components: camel-sjms
> Affects Versions: 3.8.0
> Reporter: Brad Harvey
> Priority: Major
> Fix For: Future
>
>
> Please provide a means of receiving multiple JMS messages as a batch in a
> single transaction.
> Our use case is to exchange JMS messages in order, quickly, with at least
> once delivery guarantee, but over a link with 10 to 15 ms latency.
> Processing multiple JMS messages in a single transaction is the way to meet
> this requirement as it greatly reduces the chatter over the wire:
> * For sending, we use the normal JMS component with a loop (using <split/>)
> inside the transaction.
> * For receiving (in 3.4.5) we use sjms-batch with an aggregation strategy.
> Example
> ** from
> sjms-batch:myqueue?aggregationStrategy=#groupedBodyAggregationStrategy&completionSize=300&asyncStartListener=true&keepAliveDelay=5000
> The sjms-batch component was removed as part of the overhaul of sjms, but
> there appears to be no alternative to the functionality it provided.
>
>
--
This message was sent by Atlassian Jira
(v8.20.10#820010)