You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by "Croway (via GitHub)" <gi...@apache.org> on 2026/10/01 13:22:26 UTC

[PR] CAMEL-25197: camel-cli-connector - pluggable WebSocket client for the websocket transport [camel]

Croway opened a new pull request, #27210:
URL: https://github.com/apache/camel/pull/27210

   _Claude Code on behalf of Croway_
   
   Follow-up of #27145 ([CAMEL-25197](https://issues.apache.org/jira/browse/CAMEL-25197)).
   
   The websocket transport of `camel-cli-connector` was hard-wired to the JDK WebSocket client. This puts the socket I/O behind a small SPI, so that runtimes can use their own WebSocket client when the application already has one (Camel Quarkus: the WebSockets Next client; Camel Spring Boot: Spring's client), and fall back to the JDK client otherwise, without adding dependencies.
   
   ## Changes
   
   - New `org.apache.camel.cli.connector.CliWebSocketClient` (`@since 4.23`): `connect(URI, headers, Listener)` returning a `Channel` (`sendText`, `sendPing`, `close`, `abort`), plus `getName()` and `MAX_MESSAGE_SIZE` (16 MB).
   - `CliWebSocketHandshakeException`: the HTTP status of a rejected handshake (401/403 still logged as a token problem).
   - `JdkCliWebSocketClient`: the previous JDK code, moved (partial frames reassembly with the 16 MB cap, `request(1)` flow, automatic pong).
   - Everything protocol-related stays in the transport, so every client gets it: envelope, hello, actions, snapshots and their splitting, single writer, send timeout, lone surrogates, heartbeat, backoff with jitter, inbound cap, `prod` profile / token / `allow-insecure` checks.
   - Client selection: the single `CliWebSocketClient` in the registry if any, otherwise the JDK client. New option `camel.cli.websocket.client` (`auto` default, `jdk` to always use the JDK client). The client in use is logged and reported in `hello.transport`.
   - Incoming frames are now parsed on the transport thread instead of the client callback thread, which can be an event loop (Vert.x).
   - A close or error reported before the client completes `connect()` is handled (the transport reconnects).
   - Docs: "WebSocket client" section and the new option in `cli-connector.adoc`.
   
   ## Tests
   
   - `mvn verify -pl dsl/camel-cli-connector`: 31 tests, 0 failures (the 24 existing ones unchanged, plus 7 new: registry client used, `jdk` forces the JDK client, default client, unknown client refused, close frame `1000` on stop, liveness by pongs only, close before the client reports the connection open).
   - Soak test (5 Camel Main apps over the WebSocket transport for 240 s, with the tool closing connections, a network blackhole, the tool down and the token rejected): all disruptions recovered, actions and snapshots fine, no unexpected errors. The only reported failure is one trace counted as "received twice or out of order", which also occurs on the code before this change; the harness tracks traces per application rather than per connection.
   - Also exercised by the Camel Quarkus (WebSockets Next) and Camel Spring Boot clients built on this SPI (separate PRs).
   


-- 
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: commits-unsubscribe@camel.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] CAMEL-25197: camel-cli-connector - pluggable WebSocket client for the websocket transport [camel]

Posted by "Croway (via GitHub)" <gi...@apache.org>.
Croway commented on code in PR #27210:
URL: https://github.com/apache/camel/pull/27210#discussion_r4156021844


##########
dsl/camel-cli-connector/src/main/java/org/apache/camel/cli/connector/WebSocketCliConnectorTransport.java:
##########
@@ -661,75 +694,52 @@ private static boolean isLoopback(String host) {
     }
 
     /**
-     * One WebSocket connection, and what has been sent on it.
+     * One WebSocket connection, and what has been sent on it. The callbacks come from the client, on any thread.
      */
-    private final class Connection implements WebSocket.Listener {
+    private final class Connection implements CliWebSocketClient.Listener {
 
-        private WebSocket ws;
-        private final StringBuilder partial = new StringBuilder();
-        private final long openedAt = System.currentTimeMillis();
+        // set on the scheduler thread, before the connection is used
+        private CliWebSocketClient.Channel channel;
+        private boolean lost;
+        private long openedAt = System.currentTimeMillis();
         private volatile long lastSeen = openedAt;
         private boolean helloSent;
         private long lastTraceUid;
         private long lastReceiveUid;
         private final Map<String, String> lastSent = new HashMap<>();
 
         @Override
-        public void onOpen(WebSocket webSocket) {
-            this.ws = webSocket;
-            webSocket.request(1);
-            execute(() -> opened(this));
-        }
-
-        @Override
-        public CompletionStage<?> onText(WebSocket webSocket, CharSequence data, boolean last) {
+        public void onText(String text) {

Review Comment:
   _Claude Code on behalf of Croway_
   
   Good catch, thanks. Fixed in a72fa1b8e5d0 with the second option: frames received before the connection is reported open are kept (up to 64, as the pending actions) and handled once `opened` runs, after the `hello`. Dropping them would lose a `stop` silently, since no result can be sent yet. Frames of a connection that is already gone are no longer run, as their result cannot be sent either.
   
   `runsActionsReceivedBeforeTheClientReportsTheConnectionOpen` covers it with a client that delivers an action and reports the connection open 500 ms later: it fails without the change (the result was dropped) and passes with it.



-- 
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: commits-unsubscribe@camel.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] CAMEL-25197: camel-cli-connector - pluggable WebSocket client for the websocket transport [camel]

Posted by "Croway (via GitHub)" <gi...@apache.org>.
Croway merged PR #27210:
URL: https://github.com/apache/camel/pull/27210


-- 
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: commits-unsubscribe@camel.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] CAMEL-25197: camel-cli-connector - pluggable WebSocket client for the websocket transport [camel]

Posted by "Croway (via GitHub)" <gi...@apache.org>.
Croway commented on PR #27210:
URL: https://github.com/apache/camel/pull/27210#issuecomment-5932677363

   _Claude Code on behalf of Croway_
   
   Thanks for the review. The inline point is fixed in a72fa1b8e5d0 (details in the thread). I added the liveness note to the PR description: pings sent by the tool no longer count as the tool being alive, only its frames and its pongs to our pings do. The doc validation re-run passed (it was the 504 on `cargo-deadlinks`).


-- 
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: commits-unsubscribe@camel.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] CAMEL-25197: camel-cli-connector - pluggable WebSocket client for the websocket transport [camel]

Posted by "github-actions[bot] (via GitHub)" <gi...@apache.org>.
github-actions[bot] commented on PR #27210:
URL: https://github.com/apache/camel/pull/27210#issuecomment-5932365429

   :star2: Thank you for your contribution to the Apache Camel project! :star2:
     :robot: CI automation will test this PR automatically.
   
     :camel: Apache Camel Committers, please review the following items:
   
     * First-time contributors **require MANUAL approval** for the GitHub Actions to run
     * You can use the command `/component-test (camel-)component-name1 (camel-)component-name2..` to request a test from the test bot although they are normally detected and executed by CI.
     * You can label PRs using `skip-tests` and `test-dependents` to fine-tune the checks executed by this PR.
     * Build and test logs are available in the summary page. **Only** [Apache Camel committers](https://camel.apache.org/community/team/#committers) have access to the summary.
     
     :warning: Be careful when sharing logs. Review their contents before sharing them publicly.


-- 
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: commits-unsubscribe@camel.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] CAMEL-25197: camel-cli-connector - pluggable WebSocket client for the websocket transport [camel]

Posted by "davsclaus (via GitHub)" <gi...@apache.org>.
davsclaus commented on code in PR #27210:
URL: https://github.com/apache/camel/pull/27210#discussion_r4155886066


##########
dsl/camel-cli-connector/src/main/java/org/apache/camel/cli/connector/WebSocketCliConnectorTransport.java:
##########
@@ -661,75 +694,52 @@ private static boolean isLoopback(String host) {
     }
 
     /**
-     * One WebSocket connection, and what has been sent on it.
+     * One WebSocket connection, and what has been sent on it. The callbacks come from the client, on any thread.
      */
-    private final class Connection implements WebSocket.Listener {
+    private final class Connection implements CliWebSocketClient.Listener {
 
-        private WebSocket ws;
-        private final StringBuilder partial = new StringBuilder();
-        private final long openedAt = System.currentTimeMillis();
+        // set on the scheduler thread, before the connection is used
+        private CliWebSocketClient.Channel channel;
+        private boolean lost;
+        private long openedAt = System.currentTimeMillis();
         private volatile long lastSeen = openedAt;
         private boolean helloSent;
         private long lastTraceUid;
         private long lastReceiveUid;
         private final Map<String, String> lastSent = new HashMap<>();
 
         @Override
-        public void onOpen(WebSocket webSocket) {
-            this.ws = webSocket;
-            webSocket.request(1);
-            execute(() -> opened(this));
-        }
-
-        @Override
-        public CompletionStage<?> onText(WebSocket webSocket, CharSequence data, boolean last) {
+        public void onText(String text) {

Review Comment:
   A frame can reach `onFrame` before `opened(c, channel)` has run. The JDK adapter calls `request(1)` in `onOpen`, and `opened` is only queued when the `connect()` future completes, so a frame from a tool that writes right after the handshake can be queued first.
   
   `onFrame` then still runs the action, but `send()` drops the reply because `c != connection`. For a `stop` action, the application stops without telling the tool. Before this PR `opened` was queued inside `onOpen`, so the gap was smaller.
   
   If the tool can send before it gets `hello`, maybe drop frames for a connection that isn't open yet, as `send()` already does:
   
   ```java
   private void onFrame(Connection c, String text) {
       if (c != connection) {
           // not open yet, or already gone
           return;
       }
   ```
   
   Or keep them until `opened` runs. If the tool always waits for `hello`, then this is fine as is.



-- 
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: commits-unsubscribe@camel.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] CAMEL-25197: camel-cli-connector - pluggable WebSocket client for the websocket transport [camel]

Posted by "github-actions[bot] (via GitHub)" <gi...@apache.org>.
github-actions[bot] commented on PR #27210:
URL: https://github.com/apache/camel/pull/27210#issuecomment-5933228956

   <!-- ci-tested-modules -->
   :test_tube: **CI tested the following changed modules:**
   
   - `catalog/camel-catalog`
   - `dsl/camel-cli-connector`
   
   ---
   
   <details><summary>:microscope: Scalpel shadow comparison — Scalpel: 10 of 697 tested, 23 compile-only — current: 10 all tested</summary>
   
   [Maveniverse Scalpel](https://github.com/maveniverse/scalpel) detected **10 affected modules** (current approach: 10).
   
   **Skip-tests mode would test 10 modules** (2 direct + 9 downstream), **skip tests for 23** (generated code, meta-modules)
   
   <details><summary>Modules Scalpel would test (10)</summary>
   
   - `camel-cli-connector` ← dsl/camel-cli-connector/src/main/docs/cli-connector.adoc, dsl/camel-cli-connector/src/main/java/org/apache/camel/cli/connector/CliWebSocketClient.java, dsl/camel-cli-connector/src/main/java/org/apache/camel/cli/connector/CliWebSocketHandshakeException.java, dsl/camel-cli-connector/src/main/java/org/apache/camel/cli/connector/JdkCliWebSocketClient.java, dsl/camel-cli-connector/src/main/java/org/apache/camel/cli/connector/WebSocketCliConnectorTransport.java, dsl/camel-cli-connector/src/test/java/org/apache/camel/cli/connector/WebSocketCliConnectorTransportTest.java
   - `camel-cli-debug` ← downstream of org.apache.camel:camel-cli-connector
   - `camel-jbang-mcp` ← downstream of org.apache.camel:camel-catalog
   - `camel-jbang-plugin-mcp` ← downstream of org.apache.camel:camel-jbang-core
   - `camel-jbang-plugin-route-parser` ← downstream of org.apache.camel:camel-route-parser
   - `camel-jbang-plugin-tui` ← downstream of org.apache.camel:camel-catalog
   - `camel-jbang-plugin-validate` ← downstream of org.apache.camel:camel-yaml-dsl-validator
   - `camel-launcher-container` ← downstream of org.apache.camel:camel-launcher
   - `camel-yaml-dsl-validator` ← downstream of org.apache.camel:camel-catalog
   - `camel-yaml-dsl-validator-maven-plugin` ← downstream of org.apache.camel:camel-yaml-dsl-validator
   
   </details>
   
   <details><summary>Modules with tests skipped (23)</summary>
   
   - `apache-camel`
   - `camel-catalog-console`
   - `camel-catalog-maven`
   - `camel-catalog-suggest`
   - `camel-componentdsl`
   - `camel-endpointdsl`
   - `camel-endpointdsl-support`
   - `camel-itest`
   - `camel-jbang-core`
   - `camel-jbang-it`
   - `camel-jbang-main`
   - `camel-jbang-plugin-edit`
   - `camel-jbang-plugin-generate`
   - `camel-jbang-plugin-kubernetes`
   - `camel-jbang-plugin-test`
   - `camel-kamelet-main`
   - `camel-launcher`
   - `camel-report-maven-plugin`
   - `camel-route-parser`
   - `camel-yaml-dsl`
   - `camel-yaml-dsl-deserializers`
   - `camel-yaml-dsl-maven-plugin`
   - `coverage`
   
   </details>
   
   > :information_source: Shadow mode — Scalpel observes but does not affect test execution. [Learn more](https://github.com/maveniverse/scalpel)
   
   </details>
   
   <details><summary>All tested modules (34 modules, 5m 52s total)</summary>
   
   **Total reactor time:** 5m 52s
   
   | Module | Duration | Status |
   | --- | --- | --- |
   | Camel :: Launcher | 50.0s | SUCCESS |
   | Camel :: JBang :: MCP | 44.6s | SUCCESS |
   | Camel :: JBang :: Plugin :: TUI | 38.6s | SUCCESS |
   | Camel :: DSL :: CLI Connector | 38.5s | SUCCESS |
   | Camel :: Catalog :: Camel Catalog | 30.4s | SUCCESS |
   | Camel :: Component DSL | 21.5s | SUCCESS |
   | Camel :: YAML DSL | 21.3s | SUCCESS |
   | Camel :: YAML DSL :: Validator | 17.2s | SUCCESS |
   | Camel :: JBang :: Plugin :: Kubernetes | 17.1s | SUCCESS |
   | Camel :: Catalog :: Camel Route Parser | 10.9s | SUCCESS |
   | Camel :: Kamelet Main | 10.1s | SUCCESS |
   | Camel :: Catalog :: Camel Report Maven Plugin | 8.6s | SUCCESS |
   | Camel :: YAML DSL :: Deserializers | 7.8s | SUCCESS |
   | Camel :: JBang :: Plugin :: Testing | 7.6s | SUCCESS |
   | Camel :: JBang :: Plugin :: Validate | 5.0s | SUCCESS |
   | Camel :: YAML DSL :: Validator Maven Plugin | 3.0s | SUCCESS |
   | Camel :: Catalog :: Maven | 2.9s | SUCCESS |
   | Camel :: YAML DSL :: Maven Plugins | 2.9s | SUCCESS |
   | Camel :: Catalog :: Suggest (deprecated) | 2.8s | SUCCESS |
   | Camel :: Assembly | 2.0s | SUCCESS |
   | Camel :: Coverage | 1.4s | SUCCESS |
   | Camel :: JBang :: Plugin :: Edit | 1.2s | SUCCESS |
   | Camel :: JBang :: Integration tests | 1.0s | SUCCESS |
   | Camel :: JBang :: Plugin :: Generate | 0.9s | SUCCESS |
   | Camel :: Endpoint DSL :: Support | 0.8s | SUCCESS |
   | Camel :: JBang :: Main | 0.7s | SUCCESS |
   | Camel :: Launcher :: Container | 0.7s | SUCCESS |
   | Camel :: DSL :: CLI Debug | 0.6s | SUCCESS |
   | Camel :: JBang :: Plugin :: MCP | 0.5s | SUCCESS |
   | Camel :: JBang :: Plugin :: Route Parser | 0.5s | SUCCESS |
   | Camel :: Catalog :: Console | 0.4s | SUCCESS |
   | Camel :: Endpoint DSL | n/a |  |
   | Camel :: Integration Tests | n/a |  |
   | Camel :: JBang :: Core | n/a |  |
   
   **Top 20 slowest modules:**
   - `Camel :: Launcher` (50.0s)
   - `Camel :: JBang :: MCP` (44.6s)
   - `Camel :: JBang :: Plugin :: TUI` (38.6s)
   - `Camel :: DSL :: CLI Connector` (38.5s)
   - `Camel :: Catalog :: Camel Catalog` (30.4s)
   - `Camel :: Component DSL` (21.5s)
   - `Camel :: YAML DSL` (21.3s)
   - `Camel :: YAML DSL :: Validator` (17.2s)
   - `Camel :: JBang :: Plugin :: Kubernetes` (17.1s)
   - `Camel :: Catalog :: Camel Route Parser` (10.9s)
   - `Camel :: Kamelet Main` (10.1s)
   - `Camel :: Catalog :: Camel Report Maven Plugin` (8.6s)
   - `Camel :: YAML DSL :: Deserializers` (7.8s)
   - `Camel :: JBang :: Plugin :: Testing` (7.6s)
   - `Camel :: JBang :: Plugin :: Validate` (5.0s)
   - `Camel :: YAML DSL :: Validator Maven Plugin` (3.0s)
   - `Camel :: Catalog :: Maven` (2.9s)
   - `Camel :: YAML DSL :: Maven Plugins` (2.9s)
   - `Camel :: Catalog :: Suggest (deprecated)` (2.8s)
   - `Camel :: Assembly` (2.0s)
   
   </details>
   
   ---
   :gear: [View full build and test results](https://github.com/apache/camel/actions/runs/36870545013)


-- 
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: commits-unsubscribe@camel.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org