[ 
https://issues.apache.org/jira/browse/CAMEL-24107?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
 ]

Claus Ibsen resolved CAMEL-24107.
---------------------------------
    Resolution: Fixed

> camel-xslt: stylesheet reload (contentCache=false / clearCachedStylesheet) is 
> not thread-safe - stale pooled transformers keep serving the old stylesheet
> ---------------------------------------------------------------------------------------------------------------------------------------------------------
>
>                 Key: CAMEL-24107
>                 URL: https://issues.apache.org/jira/browse/CAMEL-24107
>             Project: Camel
>          Issue Type: Bug
>          Components: camel-xslt
>    Affects Versions: 4.21.0
>            Reporter: Federico Mariani
>            Assignee: Claus Ibsen
>            Priority: Major
>              Labels: code-review
>             Fix For: 4.22.0
>
>         Attachments: XsltReloadStalePooledTransformerTest.java
>
>
> h3. Problem
> With {{contentCache=false}}, {{XsltEndpoint.onExchange()}} calls 
> {{loadResource()}} -> {{XsltBuilder.setTransformerSource()}} -> 
> {{setTemplate()}} on *every exchange* with no synchronization. The same code 
> path runs once after the managed {{clearCachedStylesheet}} JMX operation, 
> which is advertised for production use. Several problems, in decreasing order 
> of impact:
> # *Stale pooled transformers survive the reload.* With {{transformerCacheSize 
> > 0}}, a {{Transformer}} polled from the pool before {{setTemplate()}} 
> cleared it is re-offered to the pool in {{XsltBuilder.releaseTransformer()}} 
> *after* the transform completes. Transformers compiled from the OLD 
> stylesheet re-enter the pool and keep serving messages - the reload silently 
> does not take effect for them.
> # {{XsltBuilder.template}} is a plain non-volatile field written per message 
> and read by every processing thread - no visibility guarantee.
> # Concurrent {{factory.newTemplates()}} on the single shared 
> {{TransformerFactory}} - JAXP does not guarantee {{TransformerFactory}} 
> thread safety.
> # {{cacheCleared}} is reset only after the load completes, so concurrent 
> messages trigger redundant parallel reloads.
> h3. Failure scenario
> Any route using {{transformerCacheSize > 0}} together with 
> {{contentCache=false}} (or an operator invoking {{clearCachedStylesheet}} 
> while traffic is flowing): messages processed *after* the reload still 
> produce output from the old stylesheet, indefinitely, as long as the stale 
> transformer keeps cycling through the pool.
> h3. Reproducer
> Attached {{XsltReloadStalePooledTransformerTest.java}} - deterministic, no 
> sleeps: message 1 blocks inside {{transformer.transform()}} while the 
> stylesheet is reloaded (pool cleared), then completes and re-offers its 
> old-stylesheet transformer; message 2 polls the pool and produces {{<one/>}} 
> instead of {{<two/>}}.
> h3. Fix direction
> Guard reload with a lock (reload-once semantics), make {{template}} volatile, 
> and invalidate pooled transformers generation-consistently with the template 
> swap (e.g. tag transformers with the template generation and drop re-offered 
> transformers from an older generation).
> ----
> _This issue was researched and filed by Claude Code on behalf of [~fmariani] 
> (GitHub: Croway), as part of a code review of camel-xslt and 
> camel-xslt-saxon. The attached JUnit reproducer fails deterministically on 
> current main (4.22.0-SNAPSHOT); place it in 
> {{components/camel-xslt-saxon/src/test/java/org/apache/camel/component/xslt/saxon/}}._



--
This message was sent by Atlassian Jira
(v8.20.10#820010)

Reply via email to