Eduard Gomoliako created CAMEL-24062:
----------------------------------------
Summary: UseOriginalAggregationStrategy silently ignored under
Multicast (original never bound) — inconsistent with Splitter
Key: CAMEL-24062
URL: https://issues.apache.org/jira/browse/CAMEL-24062
Project: Camel
Issue Type: Improvement
Components: camel-core
Affects Versions: 4.18.2
Reporter: Eduard Gomoliako
{{UseOriginalAggregationStrategy}} works as documented under the Splitter EIP
but is silently ignored under Multicast. {{Splitter.process(...)}} binds the
per-invocation _original_ exchange onto the strategy; {{MulticastProcessor}}
does not — even though the shared base already contains the mechanism to honor
it. So {{multicast().aggregationStrategy(new
UseOriginalAggregationStrategy())}} does *not* restore the original
pre-multicast exchange; it degrades to "use latest" with no error or warning.
Please unify the two EIPs, or document why they differ.
h3. Current behavior (4.18.2)
* *{{Splitter.process(Exchange, AsyncCallback)}}* — if the strategy is a
{{{}UseOriginalAggregationStrategy{}}}, creates a per-invocation instance via
{{{}newInstance(exchange){}}}, optionally wraps in
{{ShareUnitOfWorkAggregationStrategy}} when {{{}isShareUnitOfWork(){}}}, and
installs it via {{{}setAggregationStrategyOnExchange(...){}}}; also falls back
to {{new UseOriginalAggregationStrategy(exchange, true)}} when no strategy is
set.
* *{{MulticastProcessor}}* — overrides {{process(...)}} but has *no*
{{UseOriginalAggregationStrategy}} handling. Yet its own
{{getAggregationStrategy(Exchange)}} already reads the per-exchange,
per-processor {{AGGREGATION_STRATEGY}} map ({{{}map.get(this){}}}) before the
shared field — so the binding hook lives in the shared base and is functional;
only {{Splitter}} ever writes to it.
* *{{UseOriginalAggregationStrategy}}* — holds {{original}} (set via
constructor / {{{}newInstance{}}}), implements only the 2-arg
{{{}aggregate(old, new){}}}, does *not* override the 3-arg {{aggregate(old,
new, inputExchange)}} from CAMEL-13287 (so the forwarded {{inputExchange}} is
dropped), and returns the accumulated exchange when {{original}} is null.
*Root cause:* Multicast never binds {{{}original{}}}, so it stays {{null}} and
the strategy returns the last/aggregated exchange instead of the original —
silently. CAMEL-13287's {{inputExchange}} doesn't help because this strategy
never consults it.
h3. Reproduce
{code:java}
// A) Splitter — works: mock:out receives the ORIGINAL body
from("direct:split")
.split(constant(java.util.List.of("only-element")))
.aggregationStrategy(new UseOriginalAggregationStrategy())
.setBody(constant("MUTATED"))
.end()
.to("mock:out");{code}
{code:java}
// B) Multicast — broken: mock:out receives "MUTATED", not the original
from("direct:multicast")
.multicast()
.aggregationStrategy(new UseOriginalAggregationStrategy())
.to("direct:mutate")
.end()
.to("mock:out");from("direct:mutate").setBody(constant("MUTATED"));
// Send body "ORIGINAL" to each entry point. {code}
*Expected:* route (B) {{mock:out}} receives the original ({{{}"ORIGINAL"{}}}),
like (A). *Actual:* (B) receives the aggregated/last exchange; the strategy is
a no-op.
h3. Suggested resolutions (any one)
# *Unify* — move the {{UseOriginalAggregationStrategy}} binding block from
{{Splitter.process}} into {{MulticastProcessor.process}} (the base already
reads what would be written). Don't copy Splitter's null-strategy fallback
verbatim — Multicast's non-aggregating default differs.
# *Alternative* — have {{UseOriginalAggregationStrategy}} override the 3-arg
{{aggregate(old, new, inputExchange)}} to fall back to {{inputExchange}} when
{{original}} is null; that fixes every EIP that forwards the input exchange, no
per-EIP {{process()}} change.
# *Document / fail fast* — if intentional, say so in the Multicast docs +
Javadoc and error when it's configured on a multicast.
h3. Question
Is this divergence intentional? If so, what's the rationale and can it be
documented / made to fail fast? If not, can the behavior be unified?
h3. Related
CAMEL-13287 (added 3-arg {{aggregate}} with {{{}inputExchange{}}}) — related
but does not resolve this.
--
This message was sent by Atlassian Jira
(v8.20.10#820010)