Federico Mariani created CAMEL-24177:
----------------------------------------

             Summary: camel-cxfrs - DefaultCxfRsBinding.contentLanguage latches 
first request's value and races under concurrency
                 Key: CAMEL-24177
                 URL: https://issues.apache.org/jira/browse/CAMEL-24177
             Project: Camel
          Issue Type: Bug
          Components: camel-cxfrs
            Reporter: Federico Mariani
            Assignee: Federico Mariani


*Severity:* High  *[reproducer attached]*

h3. Problem
{{contentLanguage}} is an *instance field* on {{DefaultCxfRsBinding}} (one 
binding per endpoint, shared by all exchanges/threads). 
{{bindCamelMessageToRequestEntity}} guards the per-request lookup with {{if 
(webClient != null && contentLanguage == null)}} and always falls through to 
{{contentLanguage = Locale.US.getLanguage()}}:

{code:java}
if (webClient != null && contentLanguage == null) {
    ... contentLanguage = 
clientState.getRequestHeaders().getFirst(CONTENT_LANGUAGE);
        if (contentLanguage != null) { return Entity.entity(body, new 
Variant(..., new Locale(contentLanguage), ...)); }
}
contentLanguage = Locale.US.getLanguage();
return Entity.entity(body, new Variant(..., Locale.US, ...));
{code}

After the first request the field is non-null forever, so:
* the CAMEL-16460 feature only works for the *first* exchange through the 
endpoint;
* every later request is sent as {{Locale.US}} regardless of its own 
{{Content-Language}};
* concurrent first requests race on the null check (first-write-wins, 
nondeterministic).

This is a regression from the CAMEL-16460 "polish up" commit ({{e96225adbabe}}) 
which turned a local variable into an instance field.

h3. Location
{{components/camel-cxf/camel-cxf-rest/src/main/java/org/apache/camel/component/cxf/jaxrs/DefaultCxfRsBinding.java}}
 field at ~67, logic at ~274-298.

h3. Fix
Make {{contentLanguage}} a local variable (read the client state per request), 
or read {{Content-Language}} from the Camel message header. The 
{{AbstractClient.getState()}} reflection with {{setAccessible(true)}} can also 
be replaced by {{webClient.getHeaders()}}.

h3. Reproducer
{{DefaultCxfRsBindingContentLanguageReproducerTest}} (attached): two sequential 
calls on one binding, first declaring {{fr}} then {{de}}; the second returns 
{{en}} (latched) instead of {{de}}. Fails on current {{main}}.

----
_Filed by Claude Code (Claude Fable) on behalf of Federico Mariani (GitHub: 
Croway). Findings from an AI-assisted code review of the camel-cxf component 
family; each item was verified against the current source and git history. 
Items marked *[reproducer attached]* include a failing JUnit test that 
demonstrates the defect._



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

Reply via email to