WebSockets in Helidon SE
Helidon integrates with Tyrus [1] to provide support for the Jakarta WebSocket API [2]. The WebSocket API enables Java applications to participate in WebSocket interactions as servers or clients.
Helidon SE support is based on the TyrusSupport
class which is akin to JerseySupport
, and enables Helidon applications to defined both annotated and programmatic WebSocket endpoints.
Project Dependencies
To use the WebSocket extension in your Helidon SE application, simply add the following dependency to your POM file:
WebSocket Example
Let us explore an implementation of a simple application that uses a REST resource to push messages into a shared queue and a programmatic WebSocket endpoint to download messages from the queue, one at a time, over a connection. The example will show how REST and WebSocket connections can be seamlessly combined into a Helidon SE application.
Let us start by looking at MessageQueueService
:
This class exposes a REST resource where messages can be posted. Upon receiving a message, it simply pushes it into a shared queue and returns 204 (no content). Note that the queue is implemented by the singleton class MessageQueue
.
Messages pushed into the queue can be obtained by opening a WebSocket connection served by MessageBoardEndpoint
:
This is a programmatic endpoint that extends classEndpoint
. The method onOpen
is invoked for every new connection. In this example, the application registers a message handler for strings, and when the special SEND
message is received, it empties the shared queue sending messages over the WebSocket connection.
In Helidon SE, REST and WebSocket classes need to be manually registered into the web server. This is accomplished during the creation of theRouting
instance as shown next:
This code snippet uses multiple builders for Routing
, TyrusSupport
and ServerEndpointConfig
. In particular, it registers MessageBoardEndpoint.class
at /websocket
and associates with it a message encoder. For more information on message encoders and decoders see [2]; in this example, UppercaseEncoder.class
simply uppercases every message sent from the server.
Endpoint methods in Helidon SE are executed in Netty’s worker thread pool. Threads in this pool are intended to be non-blocking, thus it is recommended for any blocking or long-running operation triggered by an endpoint method to be executed using a separate thread pool. Helidon includes a configurable thread pool supplier for cases such as this, see io.helidon.common.configurable.ThreadPoolSupplier
.
For more information about this example, the reader is referred to [3].
[1]https://projects.eclipse.org/projects/ee4j.tyrus
[2]https://projects.eclipse.org/projects/ee4j.websocket
[3]https://github.com/oracle/helidon/tree/master/examples/webserver/websocket