Federico Mariani created CAMEL-24184:
----------------------------------------

             Summary: camel-cxf - Umbrella: medium-severity findings from July 
2026 code review
                 Key: CAMEL-24184
                 URL: https://issues.apache.org/jira/browse/CAMEL-24184
             Project: Camel
          Issue Type: Task
          Components: camel-cxf
            Reporter: Federico Mariani
            Assignee: Federico Mariani


Umbrella tracking the *medium-severity* findings from the July 2026 AI-assisted 
code review of the {{components/camel-cxf/}} component family. The 
high-severity findings are filed as separate linked issues. Each item below has 
been verified against current source and git history; items marked *[verified]* 
were additionally re-read line-by-line on {{main}}.

h2. camel-cxf-soap / camel-cxf-common
# *replaceMultiPartContentType strips 5 extra characters* _[verified]_ - 
{{DefaultCxfBinding.java:~869}}: for an unquoted {{type=}} parameter the value 
has {{type=}} removed, then {{substring(5)}} is applied again, so 
{{type=text/xml}} becomes {{xml}}. Corrupts the propagated {{Content-Type}} for 
unquoted MTOM/multipart responses. Fix: {{result = part;}} in the else branch.
# *CxfClientCallback NPE when out message absent* - 
{{CxfClientCallback.java:~88-97}}: with a failover {{ConduitSelector}} and a 
transport error before the out message exists, 
{{cxfExchange.getOutMessage().getContent(..)}} NPEs and replaces the real 
exception. Fix: null-guard the out message.
# *populateCxfHeaderFromCamelExchangeBeforeCheckError is a no-op* - 
{{DefaultCxfBinding.java:~456-479}}: called before the out message is created, 
so its guarded {{put}} is skipped and response protocol headers are never 
propagated onto a fault response. Fix: create/lookup the out (or fault) message 
first, or move propagation into the fault path.
# *Unsynchronized lazy Bus creation* - {{CxfEndpoint.java:~1015-1047}}: the 
{{bus}} field is non-volatile; concurrent producer/consumer {{doStart}} can 
each create a Bus and leak one. Fix: volatile + double-checked locking, or init 
in {{doInit}}.

h2. camel-cxf-rest
# *Void.class vs Void.TYPE in CxfRsInvoker* _[verified]_ - 
{{CxfRsInvoker.java:~165}}: {{method.getReturnType() == Void.class}} is false 
for {{void}} methods ({{void.class}}), so {{InOnly}} is never selected; a 
{{void}} resource method's route result leaks back as a response body. Fix: 
test {{Void.TYPE || Void.class}} (verify the MEP change before shipping).
# *Void.class confusion in SubResourceClassInvocationHandler* - 
{{SubResourceClassInvocationHandler.java:~33}}: {{void}} methods fall into 
{{findResourceConstructor(void.class)}} -> NPE instead of returning null. Fix: 
{{returnType != Void.TYPE && returnType != Void.class}}.
# *Async http-API leaks the JAX-RS Response for InOnly exchanges* - 
{{CxfRsProducer.java:~708-710}}: the sync path closes the {{Response}} for 
non-out-capable exchanges; the async {{completed()}} returns without closing, 
pinning connections under keep-alive. Fix: {{response.close()}} in the InOnly 
branch.
# *Multi-valued Camel headers flattened via toString()* - 
{{CxfHeaderHelper.java:~105}} (via 
{{DefaultCxfRsBinding.bindCamelHeadersToRequestHeaders}}): a {{List}}-valued 
header is serialized as the literal {{"[a, b]"}}. The sibling 
{{propagateCamelToCxf}} handles {{List}} correctly. Fix: add each list element 
to the multivalued map.
# *Inbound protocol headers keep only the first value* - 
{{DefaultCxfRsBinding.java:~333}}; producer error headers 
{{CxfRsProducer.java:~655}}: {{get(0)}} drops repeated headers (e.g. multiple 
{{Set-Cookie}}) into {{CxfOperationException.headers}} and the consumer header 
map. Fix: reuse {{convertCxfProtocolHeaderValues}}.
# *setProtocolHeaders NPE when CXF out message absent* - 
{{DefaultCxfRsBinding.java:~127-146}}: the null-guard covers only the 
{{putIfAbsent}}; the following {{getOutMessage().get(..)}} is unguarded 
(oneway/fault paths). Also {{ObjectHelper.isEmpty(cxfExchange)}} tests 
map-emptiness, not nullness. Fix: hoist a single out-message null check.
# *CxfConverter fallback NPEs on a Response with null entity* - 
{{CxfConverter.java:~221-232}}: {{entity.getClass()}} with no null check; a 
204/empty {{Response}} throws inside the type converter. Separately, 
{{toStreamCache}} ({{~135}}) never closes the {{Response}} -> connection held 
until GC. Fix: null-check entity -> return {{MISS_VALUE}}; close the 
{{Response}} after caching.

h2. camel-cxf-transport
# *CamelConduit producer leak / use-after-stop race* - 
{{CamelConduit.java:~77-84,108-117}}: the producer is created+started in the 
constructor, stopped only in {{close()}}; an abandoned conduit leaks it, and an 
in-flight {{asyncInvokeFromWorkQueue}} can call {{producer.process}} after 
{{close()}} stopped it. Fix: guard against use-after-stop; consider lazy 
producer acquisition.
# *asyncInvokeFromWorkQueue NPE when no fault observer* - 
{{CamelOutputStream.java:~133-140}}: if both {{getFaultObserver()}} and 
{{exchange.get(MessageObserver.class)}} are null, {{mo.onMessage}} NPEs on a 
work-queue thread and loses the original exception; the chain is also cast to 
{{PhaseInterceptorChain}} without a null check. Fix: null-check both.
# *getBasePath regex fallback is fragile* - 
{{DefaultCxfMessageMapper.java:~149-159}}: the second {{replaceFirst}} can 
never fire after the first; non-HTTP front endpoints ({{direct:}}, {{jms:}}) 
leave the raw Camel URI as the SOAP BASE_PATH, breaking {{convertPathInfo}} 
path stripping. Fix: only rewrite when the URI is actually http(s).

h2. camel-cxf-spring-*
# *CAMEL-18528 graceful bus shutdown is dead code in the standard XML path* - 
{{CxfSpringEndpoint.java:~285-299}}: {{enableSpringBusShutdownGracefully}} is 
only reachable from {{getBus()}}'s {{bus == null}} branch, but 
{{setApplicationContext}} always assigns the bus first, so it never runs on the 
first lifecycle; in-flight SOAP calls still fail on abrupt bus shutdown - the 
exact scenario CAMEL-18528 claims to fix.
# *enableSpringBusShutdownGracefully removes an arbitrary listener and spawns a 
thread per event* - {{CxfSpringEndpoint.java:~310-359}}: keeps the last 
matching {{SpringBus}} listener, so with multiple buses it can unhook a 
different bus (leak) and double-fire this one; also starts {{new Thread()}} for 
every {{ApplicationEvent}}. Fix: match by bus identity; only spawn for 
{{ContextClosedEvent}}.
# *performInvocation not propagated to SpringJAXRSServerFactoryBean* - 
{{SpringJAXRSServerFactoryBean.java:~119-133}}: the bean reads its own 
always-false field, not the endpoint's, so interface-model resources aren't 
filtered in the Spring variant. Fix: propagate {{isPerformInvocation()}} before 
server creation.
# *SpringJAXRSServerFactoryBean missing the setProperties merge override* - 
{{SpringJAXRSServerFactoryBean.java:~110-117}}: the client bean merges, the 
server bean uses CXF's replace-semantics, so a {{<cxf:properties>}} element 
wipes the {{NullFaultListener}} installed by {{skipFaultLogging="true"}}. Fix: 
add the same merging override.
# *CxfRsSpringEndpoint hard-casts CamelContext to SpringCamelContext* - 
{{CxfRsSpringEndpoint.java:~51}} (selection in 
{{CxfRsComponent.java:~130-139}}): a camel-main/{{DefaultCamelContext}} app 
with the module on the classpath gets a {{ClassCastException}} instead of 
falling back to the default factory. Fix: gate the Spring factory on 
{{instanceof SpringCamelContext}}.

----
Note: two additional security-flavoured findings from the same review (an 
inbound header-filter prefix gap and a transport header-map bypass) are being 
handled through the ASF private security process and are intentionally not 
listed here.

----
_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