Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Routing 3 doc update #4506

Merged
merged 2 commits into from
Jul 14, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 34 additions & 0 deletions docs/se/webserver.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,9 @@ include::{rootdir}/includes/se.adoc[]
- <<Configuration, Configuration>>
- <<Routing, Routing>>
- <<Request Handling, Request Handling>>
- <<Protocol Specific Routing, Protocol Specific Routing>>
- <<Error Handling, Error Handling>>
- <<Http/2 Support, Http/2 Support>>
- <<Static Content Support, Static Content Support>>
- <<Jersey (JAX-RS) Support, Jersey (JAX-RS) Support>>
- <<JSON Support, JSON Support>>
Expand Down Expand Up @@ -299,6 +301,22 @@ To complete the request handling, you must send a response by calling the `res.s
<1> handler that terminates the request handling for any HTTP method using the `/hello` path
<2> send the response

== Protocol Specific Routing
Handling routes based on the protocol version is possible by registering specific routes
on routing builder.

[source,java]
.Routing based on HTTP version
----
.routing(r -> r
.get("/any-version", (req, res) -> res.send("HTTP Version " + req.version()))
.route(Http1Route.route(GET, "/version-specific", (req, res) -> res.send("HTTP/1.1 route")))
.route(Http2Route.route(GET, "/version-specific", (req, res) -> res.send("HTTP/2 route")))
)
----

While `Http1Route` for Http/1 is always available with Helidon webserver,
other routes like `Http2Route` for <<Http/2 Support, Http/2>> needs to be added as additional dependency.

== Error Handling

Expand Down Expand Up @@ -377,6 +395,22 @@ exception called `req.next()`, then the exception is translated to an HTTP respo
* Otherwise, the exceptions are translated to an Internal Server Error HTTP
error code `500`.

== Http/2 Support

Helidon supports Http/2 upgrade from Http/1, Http/2 without prior knowledge
and Http/2 with ALPN over TLS.
Http/2 support is enabled in webserver by default when it's artefact is available on classpath.

=== Maven Coordinates
To enable Http/2 support add the following dependency to your project's `pom.xml`.

[source,xml]
----
<dependency>
<groupId>io.helidon.webserver</groupId>
<artifactId>helidon-webserver-http2</artifactId>
</dependency>
----

== Static Content Support

Expand Down
74 changes: 55 additions & 19 deletions docs/se/websocket.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,19 @@
:keywords: helidon, webserver, websocket, se
:rootdir: {docdir}/..


include::{rootdir}/includes/se.adoc[]

== ToC

- <<Overview, Overview>>
- <<maven-coordinates, Maven Coordinates>>
- <<Example, Example>>
- <<Reference, Reference>>

== Overview
Helidon integrates with link:https://projects.eclipse.org/projects/ee4j.tyrus[Tyrus] to provide support for the
{jakarta-websocket-spec-url}[Jakarta WebSocket API].
{jakarta-websocket-spec-url}[Jakarta WebSocket API].
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.
Expand All @@ -36,11 +45,21 @@ 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 SE support is based on the `TyrusSupport` class which is
akin to `JerseySupport`, and enables Helidon application to
defined both annotated and programmatic WebSocket endpoints.
Helidon SE support is based on the `WebSocketRouting` class which enables Helidon application to
configure routing for both annotated and programmatic WebSocket endpoints.


include::{rootdir}/includes/dependencies.adoc[]

== Helidon SE Example
[source,xml]
----
<dependency>
<groupId>io.helidon.webserver</groupId>
<artifactId>helidon-webserver-websocket</artifactId>
</dependency>
----

== Example

This section describes the implementation of a simple application
that uses a REST resource to push messages into a shared queue and a
Expand All @@ -64,8 +83,12 @@ public class MessageQueueService implements Service {
}

private void handlePost(ServerRequest request, ServerResponse response) {
request.content().as(String.class).thenAccept(messageQueue::push);
response.status(204).send();
request.content()
.as(String.class)
.thenAccept(it -> {
messageQueue.push(it);
response.status(204).send();
});
}
}
----
Expand All @@ -89,6 +112,7 @@ public class MessageBoardEndpoint extends Endpoint {
@Override
public void onMessage(String message) {
try {
// Send all messages in the queue
if (message.equals("SEND")) {
while (!messageQueue.isEmpty()) {
session.getBasicRemote().sendObject(messageQueue.pop());
Expand All @@ -114,20 +138,27 @@ the web server. This is accomplished via a `Routing` builder:

[source,java]
----
List<Class<? extends Encoder>> encoders =
Collections.singletonList(UppercaseEncoder.class);

Routing.builder()
.register("/rest", new MessageQueueService())
.register("/websocket",
TyrusSupport.builder().register(
ServerEndpointConfig.Builder.create(
MessageBoardEndpoint.class, "/board").encoders(
encoders).build()).build())
.build();
List<Class<? extends Encoder>> encoders =
Collections.singletonList(UppercaseEncoder.class);

WebServer server = WebServer.builder()
.port(8080)
.routing(r -> r
.register("/web", StaticContentSupport.builder("/WEB")
.welcomeFileName("index.html")
.build())
.register("/rest", new MessageQueueService())
)
.addRouting(WebSocketRouting.builder()
.endpoint("/websocket", ServerEndpointConfig.Builder.create(MessageBoardEndpoint.class, "/board")
.encoders(encoders)
.build())
.build()
)
.build()
----

This code snippet uses multiple builders for `Routing`, `TyrusSupport` and `ServerEndpointConfig`.
This code snippet uses multiple builders for `Routing`, `WebSocketRouting` and `ServerEndpointConfig`.
In particular, it registers `MessageBoardEndpoint.class` at `"/websocket/board"` and associates
with it a _message encoder_. For more information on message encoders and decoders the
reader see the {jakarta-websocket-spec-url}[websocket specification]; in this
Expand All @@ -138,3 +169,8 @@ Endpoint methods in Helidon SE are executed in Netty's worker thread pool. Threa
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. See the documentation for `io.helidon.common.configurable.ThreadPoolSupplier`.

== Reference

* link:{javadoc-base-url}/io.helidon.webserver.websocket/module-summary.html[Helidon WebSocket JavaDoc]
* link:{jakarta-websocket-spec-url}[Jakarta WebSocket Specification]