Skip to content

Commit

Permalink
Updates to (standalone) Quickstart SE to use Nima and @servertest (#6770
Browse files Browse the repository at this point in the history
)

* Port of (standalone) quickstart-se app to Nima. Includes updates to pom.xml, build.gradle, Dockerfile, etc.

* Copyright updates.

Signed-off-by: Santiago Pericasgeertsen <santiago.pericasgeertsen@oracle.com>

* Fixed checkstyle problem.

Signed-off-by: Santiago Pericasgeertsen <santiago.pericasgeertsen@oracle.com>

* Common snippet to install mvn.

Signed-off-by: Santiago Pericasgeertsen <santiago.pericasgeertsen@oracle.com>

* Common snippet to install mvn.

* Use default creation for ObserveFeature.

Signed-off-by: Santiago Pericasgeertsen <santiago.pericasgeertsen@oracle.com>

---------

Signed-off-by: Santiago Pericasgeertsen <santiago.pericasgeertsen@oracle.com>
  • Loading branch information
spericas authored May 5, 2023
1 parent b55a3d1 commit 32b9849
Show file tree
Hide file tree
Showing 9 changed files with 125 additions and 232 deletions.
15 changes: 12 additions & 3 deletions examples/quickstarts/helidon-standalone-quickstart-se/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#
# Copyright (c) 2018, 2022 Oracle and/or its affiliates.
# Copyright (c) 2018, 2023 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.
Expand All @@ -15,7 +15,16 @@
#

# 1st stage, build the app
FROM maven:3.8.4-openjdk-17-slim as build
FROM container-registry.oracle.com/java/openjdk:20 as maven

# Install maven
WORKDIR /usr/share
RUN set -x && \
curl -O https://archive.apache.org/dist/maven/maven-3/3.8.4/binaries/apache-maven-3.8.4-bin.tar.gz && \
tar -xvf apache-maven-*-bin.tar.gz && \
rm apache-maven-*-bin.tar.gz && \
mv apache-maven-* maven && \
ln -s /usr/share/maven/bin/mvn /bin/

WORKDIR /helidon

Expand All @@ -33,7 +42,7 @@ RUN mvn package -DskipTests
RUN echo "done!"

# 2nd stage, build the runtime image
FROM openjdk:17-jdk-slim
FROM container-registry.oracle.com/java/openjdk:20
WORKDIR /helidon

# Copy the binary built in the 1st stage
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#
# Copyright (c) 2020, 2022 Oracle and/or its affiliates.
# Copyright (c) 2020, 2023 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.
Expand All @@ -15,7 +15,16 @@
#

# 1st stage, build the app
FROM maven:3.8.4-openjdk-17-slim as build
FROM container-registry.oracle.com/java/openjdk:20 as maven

# Install maven
WORKDIR /usr/share
RUN set -x && \
curl -O https://archive.apache.org/dist/maven/maven-3/3.8.4/binaries/apache-maven-3.8.4-bin.tar.gz && \
tar -xvf apache-maven-*-bin.tar.gz && \
rm apache-maven-*-bin.tar.gz && \
mv apache-maven-* maven && \
ln -s /usr/share/maven/bin/mvn /bin/

WORKDIR /helidon

Expand Down
39 changes: 22 additions & 17 deletions examples/quickstarts/helidon-standalone-quickstart-se/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
limitations under the License.
-->

<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
Expand Down Expand Up @@ -63,43 +64,47 @@

<dependencies>
<dependency>
<groupId>io.helidon.bundles</groupId>
<artifactId>helidon-bundles-webserver</artifactId>
<groupId>io.helidon.nima.webserver</groupId>
<artifactId>helidon-nima-webserver</artifactId>
</dependency>
<dependency>
<groupId>io.helidon.config</groupId>
<artifactId>helidon-config-yaml</artifactId>
<groupId>io.helidon.nima.http.media</groupId>
<artifactId>helidon-nima-http-media-jsonp</artifactId>
</dependency>
<dependency>
<groupId>io.helidon.reactive.health</groupId>
<artifactId>helidon-reactive-health</artifactId>
<groupId>io.helidon.nima.observe</groupId>
<artifactId>helidon-nima-observe-health</artifactId>
</dependency>
<dependency>
<groupId>io.helidon.health</groupId>
<artifactId>helidon-health-checks</artifactId>
<groupId>io.helidon.config</groupId>
<artifactId>helidon-config-yaml</artifactId>
</dependency>
<dependency>
<groupId>io.helidon.reactive.metrics</groupId>
<artifactId>helidon-reactive-metrics</artifactId>
<groupId>io.helidon.health</groupId>
<artifactId>helidon-health-checks</artifactId>
</dependency>
<dependency>
<groupId>io.helidon.metrics</groupId>
<artifactId>helidon-metrics</artifactId>
<scope>runtime</scope>
<groupId>jakarta.json</groupId>
<artifactId>jakarta.json-api</artifactId>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.hamcrest</groupId>
<artifactId>hamcrest-all</artifactId>
<groupId>io.helidon.nima.testing.junit5</groupId>
<artifactId>helidon-nima-testing-junit5-webserver</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.helidon.nima.webclient</groupId>
<artifactId>helidon-nima-webclient</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.helidon.reactive.webclient</groupId>
<artifactId>helidon-reactive-webclient</artifactId>
<groupId>org.hamcrest</groupId>
<artifactId>hamcrest-all</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2018, 2022 Oracle and/or its affiliates.
* Copyright (c) 2018, 2023 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.
Expand All @@ -18,81 +18,76 @@

import java.util.Collections;
import java.util.concurrent.atomic.AtomicReference;
import java.util.logging.Level;
import java.util.logging.Logger;

import io.helidon.common.http.Http;
import io.helidon.config.Config;
import io.helidon.reactive.webserver.Routing;
import io.helidon.reactive.webserver.ServerRequest;
import io.helidon.reactive.webserver.ServerResponse;
import io.helidon.reactive.webserver.Service;
import io.helidon.nima.webserver.http.HttpRules;
import io.helidon.nima.webserver.http.HttpService;
import io.helidon.nima.webserver.http.ServerRequest;
import io.helidon.nima.webserver.http.ServerResponse;

import jakarta.json.Json;
import jakarta.json.JsonBuilderFactory;
import jakarta.json.JsonException;
import jakarta.json.JsonObject;

/**
* A simple service to greet you. Examples:
*
* <p>
* Get default greeting message:
* curl -X GET http://localhost:8080/greet
*
* {@code curl -X GET http://localhost:8080/greet}
* <p>
* Get greeting message for Joe:
* curl -X GET http://localhost:8080/greet/Joe
*
* {@code curl -X GET http://localhost:8080/greet/Joe}
* <p>
* Change greeting
* curl -X PUT -H "Content-Type: application/json" -d '{"greeting" : "Howdy"}' http://localhost:8080/greet/greeting
*
* The message is returned as a JSON object
* {@code curl -X PUT -H "Content-Type: application/json" -d '{"greeting" : "Howdy"}' http://localhost:8080/greet/greeting}
* <p>
* The message is returned as a JSON object.
*/
public class GreetService implements HttpService {

public class GreetService implements Service {
private static final JsonBuilderFactory JSON = Json.createBuilderFactory(Collections.emptyMap());

/**
* The config value for the key {@code greeting}.
*/
private final AtomicReference<String> greeting = new AtomicReference<>();

private static final JsonBuilderFactory JSON = Json.createBuilderFactory(Collections.emptyMap());

private static final Logger LOGGER = Logger.getLogger(GreetService.class.getName());

GreetService(Config config) {
greeting.set(config.get("app.greeting").asString().orElse("Ciao"));
GreetService() {
greeting.set("Hello");
}

/**
* A service registers itself by updating the routing rules.
*
* @param rules the routing rules.
*/
@Override
public void update(Routing.Rules rules) {
rules
.get("/", this::getDefaultMessageHandler)
.get("/{name}", this::getMessageHandler)
.put("/greeting", this::updateGreetingHandler);
public void routing(HttpRules rules) {
rules.get("/", this::getDefaultMessageHandler)
.get("/{name}", this::getMessageHandler)
.put("/greeting", this::updateGreetingHandler);
}

/**
* Return a worldly greeting message.
*
* @param request the server request
* @param response the server response
*/
private void getDefaultMessageHandler(ServerRequest request,
ServerResponse response) {
ServerResponse response) {
sendResponse(response, "World");
}

/**
* Return a greeting message using the name that was provided.
*
* @param request the server request
* @param response the server response
*/
private void getMessageHandler(ServerRequest request,
ServerResponse response) {
String name = request.path().param("name");
ServerResponse response) {
String name = request.path().pathParameters().value("name");
sendResponse(response, name);
}

Expand All @@ -105,29 +100,7 @@ private void sendResponse(ServerResponse response, String name) {
response.send(returnObject);
}

private static <T> T processErrors(Throwable ex, ServerRequest request, ServerResponse response) {

if (ex.getCause() instanceof JsonException){

LOGGER.log(Level.FINE, "Invalid JSON", ex);
JsonObject jsonErrorObject = JSON.createObjectBuilder()
.add("error", "Invalid JSON")
.build();
response.status(Http.Status.BAD_REQUEST_400).send(jsonErrorObject);
} else {

LOGGER.log(Level.FINE, "Internal error", ex);
JsonObject jsonErrorObject = JSON.createObjectBuilder()
.add("error", "Internal error")
.build();
response.status(Http.Status.INTERNAL_SERVER_ERROR_500).send(jsonErrorObject);
}

return null;
}

private void updateGreetingFromJson(JsonObject jo, ServerResponse response) {

if (!jo.containsKey("greeting")) {
JsonObject jsonErrorObject = JSON.createObjectBuilder()
.add("error", "No greeting provided")
Expand All @@ -143,14 +116,12 @@ private void updateGreetingFromJson(JsonObject jo, ServerResponse response) {

/**
* Set the greeting to use in future messages.
*
* @param request the server request
* @param response the server response
*/
private void updateGreetingHandler(ServerRequest request,
ServerResponse response) {
request.content().as(JsonObject.class)
.thenAccept(jo -> updateGreetingFromJson(jo, response))
.exceptionally(ex -> processErrors(ex, request, response));
updateGreetingFromJson(request.content().as(JsonObject.class), response);
}

}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2018, 2022 Oracle and/or its affiliates.
* Copyright (c) 2018, 2023 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.
Expand All @@ -16,15 +16,10 @@

package io.helidon.examples.quickstart.se;

import io.helidon.common.reactive.Single;
import io.helidon.config.Config;
import io.helidon.health.checks.HealthChecks;
import io.helidon.logging.common.LogConfig;
import io.helidon.reactive.health.HealthSupport;
import io.helidon.reactive.media.jsonp.JsonpSupport;
import io.helidon.reactive.metrics.MetricsSupport;
import io.helidon.reactive.webserver.Routing;
import io.helidon.reactive.webserver.WebServer;
import io.helidon.nima.observe.ObserveFeature;
import io.helidon.nima.webserver.WebServer;
import io.helidon.nima.webserver.http.HttpRouting;

/**
* The application main class.
Expand All @@ -39,63 +34,26 @@ private Main() {

/**
* Application main entry point.
*
* @param args command line arguments.
*/
public static void main(final String[] args) {
startServer();
}

/**
* Start the server.
* @return the created {@link WebServer} instance
*/
static Single<WebServer> startServer() {

public static void main(String[] args) {
// load logging configuration
LogConfig.configureRuntime();

// By default this will pick up application.yaml from the classpath
Config config = Config.create();
WebServer server = WebServer.builder()
.routing(Main::routing)
.start();

WebServer server = WebServer.builder(createRouting(config))
.config(config.get("server"))
.addMediaSupport(JsonpSupport.create())
.build();

Single<WebServer> webserver = server.start();

// Try to start the server. If successful, print some info and arrange to
// print a message at shutdown. If unsuccessful, print the exception.
webserver.thenAccept(ws -> {
System.out.println("WEB server is up! http://localhost:" + ws.port() + "/greet");
ws.whenShutdown().thenRun(() -> System.out.println("WEB server is DOWN. Good bye!"));
})
.exceptionallyAccept(t -> {
System.err.println("Startup failed: " + t.getMessage());
t.printStackTrace(System.err);
});

return webserver;
System.out.println("WEB server is up! http://localhost:" + server.port() + "/greet");
}

/**
* Creates new {@link Routing}.
*
* @return routing configured with JSON support, a health check, and a service
* @param config configuration of this server
* Updates HTTP Routing and registers observe providers.
*/
private static Routing createRouting(Config config) {

MetricsSupport metrics = MetricsSupport.create();
GreetService greetService = new GreetService(config);
HealthSupport health = HealthSupport.builder()
.add(HealthChecks.healthChecks()) // Adds a convenient set of checks
.build();

return Routing.builder()
.register(health) // Health at "/health"
.register(metrics) // Metrics at "/metrics"
.register("/greet", greetService)
.build();
static void routing(HttpRouting.Builder routing) {
GreetService greetService = new GreetService();
routing.register("/greet", greetService)
.addFeature(ObserveFeature.create());
}
}
Loading

0 comments on commit 32b9849

Please sign in to comment.