allthingssecurity opened a new pull request, #27692: URL: https://github.com/apache/camel/pull/27692
# Description [CAMEL-25544](https://issues.apache.org/jira/browse/CAMEL-25544) 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` and `UpdateIssueProducer` claim the promise, but the other producers that change an issue dropped it: `addComment`, `addIssueLink`, `addWorkLog`, `attach`, `deleteIssue`, `transitionIssue` (the transition and its comment), `watchers`, and `addIssue` for its watchers. So `process()` returned at once. A request that Jira rejected (no permission, a transition the workflow does not allow, a missing field, HTTP 401/403/5xx, a network error) was not noticed: the exchange completed successfully, nothing was logged, and the change was missing in Jira. The route also continued before Jira had done the work; for `attach`, the route continued before the upload finished. Now these producers claim the promise of each request. A rejected request fails the exchange with the `RestClientException` of the client, and the route continues when Jira has answered. The 4.23 upgrade guide has a note (routes that relied on such failures being ignored must handle the exception). Partial failure: a producer that sends several requests can now fail after some of them were done. `transitionIssue` can fail on its comment after the transition was made, and `watchers` and `addIssue` can fail after some of the watchers were changed; a retry or redelivery repeats the earlier requests. For `addIssue` a redelivery would create a second issue, so it now sets the created issue as the message body before it adds the watchers (it did that after them): when adding a watcher fails, the created issue is on the exchange for the error handling of the route. The upgrade guide note says this too. Timeout: `claim()` waits without a timeout on the Camel side. How long a producer can block is bounded only by the timeouts of the Jira client's HTTP client, which camel-jira does not set or expose. This is the same for `addIssue`, `updateIssue` and the fetch producers today. Tests: - New `DeleteIssueProducerFailureTest` uses the real Jira client against a local HTTP server: a `DELETE` answered with 403 fails the exchange with a `RestClientException` (status 403), and one answered with 204 completes it. Without the change the 403 test fails in any case (the exchange has no exception). The 204 test, `completesTheExchangeWhenJiraDeletedTheIssue`, fails on main only through timing: its assertion on the received requests runs before the request has reached the server (`expected: <[DELETE /rest/api/latest/issue/TST-1]> but was: <[]>`), which was the case in both runs on main but is not guaranteed. It is not a deterministic reproducer; it is there to cover the successful path with the real client. - New `JiraProducerRejectedRequestTest` (mocked `IssueRestClient`, as the other producer tests; every changing request returns a rejected promise): one test per producer, 9 in total. Without the change all fail with `expected: <RestClientException...> but was: <null>`. A 10th test, `addIssueKeepsTheCreatedIssueWhenAWatcherFails`, checks that the created issue is the message body when adding a watcher is rejected; with the old order it fails (the body is still the description). - The mocks of nine existing producer tests returned `null` for these calls and now return a completed promise. - With the change: camel-jira 58 tests, 0 failures. The cost is that these producers now block the calling thread until Jira answers, like `addIssue`, `updateIssue` and the fetch producers already do. Found by comparing the producers and with a small TLA+ model of one exchange (send, answer, return of `process()`, close of the body): on main "a successful exchange did not have its request rejected" and "the route continues only when Jira has answered" are violated in 3 to 4 steps; with the fix they hold. I then reproduced it with the real client. (The model also has a property about an attachment being read after the exchange released it; no test shows that with the real client, so I do not claim it here.) # Target - [x] I checked that the commit is targeting the correct branch (Camel 4 uses the `main` branch) # Tracking - [x] If this is a large change, bug fix, or code improvement, I checked there is a [JIRA issue](https://issues.apache.org/jira/browse/CAMEL) filed for the change (usually before you start working on it). # Apache Camel coding standards and style - [x] I checked that each commit in the pull request has a meaningful subject line and body. - [ ] I have run `mvn clean install -DskipTests` locally from root folder and I have committed all auto-generated changes. (I built and tested camel-jira, including the formatter and import-sort plugins. I did not run the full root build.) # AI-assisted contributions - [x] If this PR includes AI-generated code, commits have proper co-authorship attribution (e.g., `Co-authored-by` trailers) and the PR description identifies the AI tool used. This PR was prepared with Claude Code (Claude Opus 5.5). The commit carries a `Co-Authored-By` trailer. _Claude Code on behalf of allthingssecurity_ 🤖 Generated with [Claude Code](https://claude.com/claude-code) -- This is an automated message from the Apache Git Service. To respond to the message, please log on to GitHub and use the URL above to go to the specific comment. To unsubscribe, e-mail: [email protected] For queries about this service, please contact Infrastructure at: [email protected]
