[
https://issues.apache.org/jira/browse/CAMEL-25544?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
]
Claus Ibsen resolved CAMEL-25544.
---------------------------------
Resolution: Fixed
Fixed by https://github.com/apache/camel/pull/27692 (merged to main as
064fff3be18e, 4.24.0).
_Claude Code on behalf of Claus Ibsen_
> camel-jira - the addComment, addIssueLink, addWorkLog, attach, deleteIssue,
> transitionIssue and watchers producers do not wait for the answer of Jira, so
> a rejected request is not noticed and the exchange completes as if it had
> succeeded
> ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
>
> Key: CAMEL-25544
> URL: https://issues.apache.org/jira/browse/CAMEL-25544
> Project: Camel
> Issue Type: Bug
> Components: camel-jira
> Reporter: shashank
> Assignee: shashank
> Priority: Major
> Fix For: 4.24.0
>
>
> The Jira REST client is asynchronous: the methods of {{IssueRestClient}}
> return a {{Promise}}, and {{claim()}} waits for the answer and throws
> {{RestClientException}} when Jira rejected the request. {{AddIssueProducer}}
> ({{createIssue(...).claim()}}) and {{UpdateIssueProducer}}
> ({{updateIssue(...).claim()}}) do that. The other producers that change an
> issue drop the promise (lines at main 9432ba16d026):
> {code:java}
> issueClient.transition(issue, transitionInput); //
> TransitionIssueProducer:57
> issueClient.addComment(commentsUri, Comment.valueOf(commentStr)); //
> TransitionIssueProducer:63
> issueClient.addComment(commentsUri, comment); //
> AddCommentProducer:57
> issueClient.linkIssue(linkIssuesInput); //
> AddIssueLinkProducer:63
> issueClient.addWorklog(issue.getWorklogUri(), worklogInput); //
> AddWorkLogProducer:60
> issueClient.addAttachments(attachmentsUri, file); //
> AttachFileProducer:70
> issueClient.addAttachment(attachmentsUri, is, name); //
> AttachFileProducer:72
> issueClient.deleteIssue(issueKey, true); //
> DeleteIssueProducer:42
> issueClient.addWatcher(...); issueClient.removeWatcher(...); //
> WatcherProducer:57,66 and AddIssueProducer:125
> {code}
> So {{process()}} returns at once, and:
> * a request that Jira rejects (no permission, a transition that is not
> allowed in the workflow, a missing mandatory field, an unknown link type or
> user, an attachment that is too large, HTTP 401/403/5xx, a network error) is
> not noticed: the exchange completes successfully, nothing is logged, and the
> comment, link, work log, attachment, transition or deletion is missing in
> Jira;
> * the route continues before Jira has done the work, so a following step
> ({{fetchIssue}}, a second {{transitionIssue}}) can see the old state, and the
> comment of {{transitionIssue}} is not ordered after the transition;
> * for {{attach}}, the route continues before the upload has finished.
> h3. Reproduction
> New {{DeleteIssueProducerFailureTest}} uses the real Jira client against a
> local HTTP server that answers the {{DELETE}} with 403 and a Jira error body:
> on main the exchange has no exception, and the request has not even reached
> the server when the exchange is done:
> {noformat}
> DeleteIssueProducerFailureTest.failsTheExchangeWhenJiraRejectsTheRequest:
> expected: <[DELETE /rest/api/latest/issue/TST-1]> but was: <[]>
> {noformat}
> New {{JiraProducerRejectedRequestTest}} (mocked {{IssueRestClient}} as in the
> other producer tests; every request that changes the issue returns a rejected
> promise): one test per producer ({{addComment}}, {{addIssueLink}},
> {{addWorkLog}}, {{attach}} with a file and with a stream,
> {{transitionIssue}}, {{watchers}} add and remove, {{addIssue}} with a
> watcher) expects the {{RestClientException}} on the exchange. On main, twice,
> all 11 new tests fail (the 9 mocked ones with {{expected:
> <RestClientException...> but was: <null>}}).
> h3. Proposed fix
> The producers claim the promise of each request, as {{AddIssueProducer}} and
> {{UpdateIssueProducer}} do. A rejected request then fails the exchange with
> the {{RestClientException}} of the client, and the route continues when Jira
> has answered (for {{attach}}: when the upload has finished).
> {{AddIssueProducer}} sets the created issue on the exchange before it adds
> the watchers, so that it is there when adding a watcher fails. The mocks of
> the existing producer tests returned {{null}} for these calls and now return
> a completed promise. 4.23 upgrade guide note added (routes that relied on
> failures being ignored must handle the exception). camel-jira with the fix:
> 58 tests, 0 failures.
> Found by reading the producers next to each other ({{updateIssue}} claims,
> {{transitionIssue}} does not) and with a small TLA+ model of one exchange
> (send, answer by Jira, return of {{process()}}, close of the body): on main
> "a successful exchange did not have its request rejected" is violated in 4
> steps, "the route continues only when Jira has answered" in 3 steps; with the
> fix both properties hold. Confirmed with the real client. (The model also has
> a property about an attachment that is read after the exchange released it,
> violated in 5 steps; no test with the real client shows it, so it is not
> claimed here.)
> Affected: main, camel-4.22.x, camel-4.18.x, camel-4.14.x (same code, GitHub
> contents API).
> Duplicate check (2026-10-11): JIRA component camel-jira with text "claim",
> "Promise", "asynchronous", "silently" or "swallow" (2, unrelated), component
> camel-jira since 2022 (15, none about producer results; CAMEL-23539, the open
> upgrade of the Jira client, does not change these calls); GitHub pull
> requests with "jira" in the title: none open. No open pull request changes
> the camel-jira producers.
> _Filed with Claude Code on behalf of allthingssecurity._
--
This message was sent by Atlassian Jira
(v8.20.10#820010)