Skip to content

fix: let WebSocketClient borrow a client created without a context - #1607

Merged
jlouvel merged 1 commit into
3.0from
fix/websocket-borrow-client-without-context
Nov 2, 2026
Merged

jlouvel merged 1 commit into
3.0from
fix/websocket-borrow-client-without-context

Conversation

@jlouvel

@jlouvel jlouvel commented Oct 30, 2026

Copy link
Copy Markdown
Collaborator

Fixes #1599.

Stacked on #1568 (itself on #1566). Merge those first; this PR's base then moves to 3.0. It could also be folded into #1568.

Summary

WebSocketClient.setClient found the borrowed client's NettyClientHelper through the org.restlet.engine.helper context attribute. A client created with new Client(Protocol.HTTP) has no context, so it couldn't be borrowed, and the error didn't say what to change.

  • Client.getHelper() is now public, documented as an engine extension point for extensions that share the connector's resources. It was private, and it doesn't depend on a context.
  • WebSocketClient uses client.getHelper(). The context requirement is removed from the setClient Javadoc and from the error message, which now reads "The borrowed client must use the Netty HTTP connector".

Server keeps its helper private. It could get the same accessor later if an extension needs it.

Testing

  • New WebSocketSharedEventLoopTestCase.acceptsAClientWithoutContext: a started new Client(Protocol.HTTP) is borrowed and serves a session. The existing tests still reject unstarted clients and clients without a Netty HTTP connector.
  • org.restlet.ext.websocket tests pass locally: 33 tests. SpotBugs and the full core suite couldn't run locally because the machine was short of memory; CI runs them.

🤖 Generated with Claude Code

@jlouvel
jlouvel force-pushed the fix/websocket-client-shared-event-loop branch from c24fe96 to eec9acc Compare October 31, 2026 07:17
@jlouvel jlouvel self-assigned this Oct 31, 2026
@jlouvel
jlouvel requested a balanced review from Copilot October 31, 2026 07:19

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

A critical connect/stop race allows a late-registered channel to remain open on a borrowed event loop, leaving a WebSocket session active after the client stops.

1 open issue
What changed in this PR

This PR lets WebSocketClient borrow a started Netty HTTP client without requiring a context, addressing #1599. It builds on the shared-event-loop support from #1568.

Changes:

  • Exposes Client.getHelper() and uses it to access the borrowed client's connector directly.
  • Adds shared event-loop ownership and WebSocket session cleanup.
  • Adds lifecycle and context-free borrowing tests, plus changelog entries.
File Description
org.restlet/​src/​main/​java/​org/​restlet/​engine/​netty/​NettyClientHelper.java Exposes the connector's event loop for extensions.
org.restlet/​src/​main/​java/​org/​restlet/​Client.java Makes helper access public and updates context registration.
org.restlet.ext.websocket/​src/​test/​java/​org/​restlet/​ext/​websocket/​WebSocketSharedEventLoopTestCase.java Tests borrowing, lifecycle behavior, and unsuitable clients.
org.restlet.ext.websocket/​src/​main/​java/​org/​restlet/​ext/​websocket/​WebSocketClient.java Supports borrowing through direct helper access.
org.restlet.ext.websocket/​src/​main/​java/​org/​restlet/​ext/​websocket/​internal/​NettyWebSocketConnector.java Tracks connections and distinguishes owned from borrowed event loops.
changes.md Documents borrowing support and core extension points.

Review effort: Balanced

@jlouvel
jlouvel force-pushed the fix/websocket-client-shared-event-loop branch 3 times, most recently from 033346c to 21d34cb Compare November 1, 2026 13:36
Base automatically changed from fix/websocket-client-shared-event-loop to 3.0 November 1, 2026 13:41
@jlouvel
jlouvel force-pushed the fix/websocket-borrow-client-without-context branch from cfa7696 to d285169 Compare November 1, 2026 15:03
WebSocketClient.setClient found the borrowed client's NettyClientHelper
through the "org.restlet.engine.helper" context attribute, so a client
created with new Client(Protocol.HTTP), which has no context, couldn't
be borrowed.

Client.getHelper() is now public, as an engine extension point, and the
WebSocket client uses it. The context requirement is removed from the
setClient Javadoc and the error message.

Fixes #1599.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Signed-off-by: Jerome Louvel <[email protected]>
@jlouvel
jlouvel force-pushed the fix/websocket-borrow-client-without-context branch from d285169 to 9350b1f Compare November 1, 2026 21:29
@sonarqubecloud

sonarqubecloud Bot commented Nov 1, 2026

Copy link
Copy Markdown

@jlouvel
jlouvel merged commit 5bb754a into 3.0 Nov 2, 2026
3 checks passed
@jlouvel
jlouvel deleted the fix/websocket-borrow-client-without-context branch November 2, 2026 00:07
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants