///////////////////////////////////////////////////////////////////////////////

    Copyright (c) 2020 Oracle and/or its affiliates.

    Licensed under the Apache License, Version 2.0 (the "License");
    you may not use this file except in compliance with the License.
    You may obtain a copy of the License at

        http://www.apache.org/licenses/LICENSE-2.0

    Unless required by applicable law or agreed to in writing, software
    distributed under the License is distributed on an "AS IS" BASIS,
    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    See the License for the specific language governing permissions and
    limitations under the License.

///////////////////////////////////////////////////////////////////////////////

= WebSocket Introduction
:pagename: websocket-introduction
:description: Helidon WebSocket Introduction
:keywords: helidon, webserver, websocket, mp

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 both servers and clients. The server API supports two flavors: annotated and
programmatic endpoints.

Annotated endpoints, as suggested by their name, use Java annotations to provide
the necessary meta-data to define WebSocket handlers; programmatic endpoints
implement API interfaces and are annotation free. Annotated endpoints tend to be
more flexible since they allow different method signatures depending on the
application needs, whereas programmatic endpoints must implement an interface
and are, therefore, bounded to its definition.

Helidon MP support is centered around annotations and bean discovery using
CDI. Developers can choose between annotated and programmatic endpoints or use
any combination of them. Using annotated endpoints is recommended in MP as
they usually result in more succinct and easier-to-read code.

== Helidon MP Example

This section describes the implementation of a simple application
that uses a REST resource to push messages into a shared queue and a
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 application.

The Helidon MP application shown here takes full advantage of
CDI and class scanning and does not require any additional code
given that the necessary information is available from the
code annotations.

The REST endpoint is implemented as a JAX-RS resource, and the shared
queue (in application scope) is directly injected:

[source,java]
----
@Path("rest")
public class MessageQueueResource {

    @Inject
    private MessageQueue messageQueue;

    @POST
    @Consumes("text/plain")
    public void push(String s) {
        messageQueue.push(s);
    }
}
----

Here we opt for the use of an annotated WebSocket endpoint decorated
by `@ServerEndpoint` that provides all the meta-data necessary
for Helidon to create the endpoint.

[source,java]
----
@ServerEndpoint(
        value = "/websocket",
        encoders = { UppercaseEncoder.class })
public class MessageBoardEndpoint {

    @Inject
    private MessageQueue messageQueue;

    @OnMessage
    public void onMessage(Session session, String message) {
        if (message.equals("SEND")) {
            while (!messageQueue.isEmpty()) {
                session.getBasicRemote().sendObject(messageQueue.pop());
            }
        }
    }
}
----

Since `MessageBoardEndpoint` is just a POJO, it uses additional
annotations for event handlers such as `@OnMessage`. One advantage of
this approach, much like in the JAX-RS API, is that method
signatures are not fixed. In the snipped above, the parameters
(which could be specified in any order!) include the WebSocket
session and the message received that triggered the call.

So what else is needed to run this Helidon MP app? Nothing else
other than the supporting classes `MessageQueue` and `UppercaseEncoder`.
Helidon MP declares both `@Path` and `@ServerEndpoint` as
bean defining annotation, so all that is needed is for CDI
discovery to be enabled --typically in your `beans.xml` file.

By default, both JAX-RS resources and WebSocket endpoints will
be available under the _root path_ `"/"`. This default value can be
overridden by providing subclasses/implementations for `jakarta.ws.rs.Application`
and `jakarta.websocket.server.ServerApplicationConfig`, respectively.
JAX-RS uses `@ApplicationPath` on application subclasses to provide
this root path, but since there is no equivalent in the WebSocket
API, Helidon MP uses its own annotation `@RoutingPath`
on `jakarta.websocket.server.ServerApplicationConfig` implementations.

For instance, if in our example we include the following class:

[source,java]
----
@ApplicationScoped
@RoutingPath("/web")
public class MessageBoardApplication implements ServerApplicationConfig {
    @Override
    public Set<ServerEndpointConfig> getEndpointConfigs(
            Set<Class<? extends Endpoint>> endpoints) {
        assert endpoints.isEmpty();
        return Collections.emptySet();      // No programmatic endpoints
    }

    @Override
    public Set<Class<?>> getAnnotatedEndpointClasses(Set<Class<?>> endpoints) {
        return endpoints;       // Returned scanned endpoints
    }
}
----

the root path for WebSocket endpoints will be  `"/web"` instead of the default
`"/"`. Note that `@RoutingPath` is _not_ a bean defining annotation,
thus the need to use `@ApplicationScoped` --which, as before, requires CDI
bean discovery mode to be `annotated`. In addition to `@RoutingPath`, these
classes can be annotated with `@RoutingName` to associate an endpoint
with a Helidon named socket. Please refer to the Javadoc of that annotation
for additional information.

All endpoint methods in Helidon MP are executed in a separate thread pool,
independently of Netty. Therefore, there is no need to create additional threads
for blocking or long-running operations as these will not affect Netty's ability
to process networking data.

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/microprofile/websocket