Federico Mariani created CAMEL-24160:
----------------------------------------

             Summary: camel-salesforce - Umbrella: high-severity findings from 
July 2026 review (auth, streaming/pubsub, REST/bulk/composite)
                 Key: CAMEL-24160
                 URL: https://issues.apache.org/jira/browse/CAMEL-24160
             Project: Camel
          Issue Type: Bug
          Components: camel-salesforce
            Reporter: Federico Mariani
         Attachments: camel-salesforce-review-2026-07.md

Umbrella for the high-severity findings of a deep code review of 
camel-salesforce-component on main (4.22.0-SNAPSHOT). The full findings 
document is attached. External behavior was verified against decompiled jars 
(Jetty 12.1.11, CometD 9.0.1, grpc-api 1.82.2). The critical finding 
(streamQueryResult iterator hanging the route thread forever on queryMore 
failure) is tracked separately with a failing reproducer test. Individual 
findings can be split out into their own issues as they are picked up.

*Auth / session / HTTP client*
# {{SalesforceSecurityHandler:176,181,218}} — 401 handling unconditionally 
dereferences the nullable conversation client attribute; CometD streaming 
requests (no attribute) NPE inside the listener, so handler-level transparent 
re-login for streaming is dead (regression from CAMEL-17346; transport stalls 
until maxNetworkDelay).
# {{SalesforceSession:112-131}} — attemptLoginUntilSuccessful latch race: the 
winning thread replaces the already-counted-down latch only after the CAS, so 
concurrent waiters proceed with the stale token on every login cycle after the 
first (code carries a "TODO: This is janky").

*Streaming (CometD) / Pub/Sub (gRPC)*
# {{SubscriptionHelper:147-149}} — handshake failures retry in a tight loop 
({{client.handshake()}} immediately, no backoff, no maxBackoff abort — 
machinery exists but is only applied to subscription failures; pre-rewrite code 
had it).
# {{PubSubApiClient:341-344}} — onError logs trailers via 
{{Metadata.Key.of(name, ASCII_STRING_MARSHALLER)}}, which throws 
IllegalArgumentException for {{-bin}} keys (e.g. standard 
{{grpc-status-details-bin}}) before resubscribeOnError() is reached — 
reconnection permanently dead, no exception-handler notification.
# {{PubSubApiClient:380-398}} — resubscribeOnError() has no stop/channel-state 
check; a stop racing an in-flight error loops forever (UNAVAILABLE -> sleep -> 
resubscribe) on a gRPC callback thread.

*REST / Bulk / Composite processors*
# {{SalesforceEndpointConfig.toValueMap}} — the documented {{allOrNone}} URI 
option is never put into the endpoint config map, so it can never take effect; 
batches lose the requested atomicity silently (only the header works).
# {{DefaultBulkApiV2Client:111-125,235-249}} — 
changeJobState/changeQueryJobState error branch is missing a return, invoking 
the AsyncCallback twice; a 400 on bulk2CloseJob/AbortJob makes the remainder of 
the route execute twice for one input.
# {{JsonRestProcessor:202-260}} — deferred SObject-type detection: when no 
"type" property is found (zero-record query, aggregate query, apexCall), the 
resulting RuntimeException escapes the IOException-only catch, 
callback.done(false) still runs without setting an exception, and the exchange 
completes *successfully* with the request body as the "result".
# {{JsonRestProcessor:244}} — {{while (parser.nextToken() != END_OBJECT)}} 
never terminates for non-object JSON (bare scalar/array); a Jetty worker thread 
spins at 100% CPU forever and the exchange never completes (apexCall with 
deferred detection).

_This issue was researched and filed by Claude Code (AI) on behalf of Federico 
Mariani (fmariani). Full findings document from the review is attached to the 
umbrella issues._



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

Reply via email to