Create repo

This commit is contained in:
Julien Lengrand-Lambert
2021-06-07 21:20:49 +02:00
commit 0c7e31bb39
21 changed files with 875 additions and 0 deletions

1
.dockerignore Normal file
View File

@@ -0,0 +1 @@
target/*

29
.gitignore vendored Normal file
View File

@@ -0,0 +1,29 @@
# Compiled class file
*.class
# Log file
*.log
# BlueJ files
*.ctxt
# Mobile Tools for Java (J2ME)
.mtj.tmp/
# Package Files #
*.jar
*.war
*.nar
*.ear
*.zip
*.tar.gz
*.rar
# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
hs_err_pid*
.idea
target
.classpath
.project
.settings

30
Dockerfile Normal file
View File

@@ -0,0 +1,30 @@
# 1st stage, build the app
FROM maven:3.6-jdk-11 as build
WORKDIR /helidon
# Create a first layer to cache the "Maven World" in the local repository.
# Incremental docker builds will always resume after that, unless you update
# the pom
ADD pom.xml .
RUN mvn package -Dmaven.test.skip -Declipselink.weave.skip
# Do the Maven build!
# Incremental docker builds will resume here when you change sources
ADD src src
RUN mvn package -DskipTests
RUN echo "done!"
# 2nd stage, build the runtime image
FROM openjdk:11-jre-slim
WORKDIR /helidon
# Copy the binary built in the 1st stage
COPY --from=build /helidon/target/helidon-quickstart-se.jar ./
COPY --from=build /helidon/target/libs ./libs
CMD ["java", "-jar", "helidon-quickstart-se.jar"]
EXPOSE 8080

25
Dockerfile.jlink Normal file
View File

@@ -0,0 +1,25 @@
# 1st stage, build the app
FROM maven:3.6.3-jdk-11-slim as build
WORKDIR /helidon
# Create a first layer to cache the "Maven World" in the local repository.
# Incremental docker builds will always resume after that, unless you update
# the pom
ADD pom.xml .
RUN mvn package -Dmaven.test.skip -Declipselink.weave.skip
# Do the Maven build to create the custom Java Runtime Image
# Incremental docker builds will resume here when you change sources
ADD src src
RUN mvn -Ddocker.build=true package -Pjlink-image -DskipTests
RUN echo "done!"
# 2nd stage, build the final image with the JRI built in the 1st stage
FROM debian:stretch-slim
WORKDIR /helidon
COPY --from=build /helidon/target/helidon-quickstart-se-jri ./
ENTRYPOINT ["/bin/bash", "/helidon/bin/start"]
EXPOSE 8080

29
Dockerfile.native Normal file
View File

@@ -0,0 +1,29 @@
# 1st stage, build the app
FROM helidon/jdk11-graalvm-maven:21.0.0 as build
WORKDIR /helidon
# Create a first layer to cache the "Maven World" in the local repository.
# Incremental docker builds will always resume after that, unless you update
# the pom
ADD pom.xml .
RUN mvn package -Pnative-image -Dnative.image.skip -Dmaven.test.skip -Declipselink.weave.skip
# Do the Maven build!
# Incremental docker builds will resume here when you change sources
ADD src src
RUN mvn package -Pnative-image -Dnative.image.buildStatic -DskipTests
RUN echo "done!"
# 2nd stage, build the runtime image
FROM scratch
WORKDIR /helidon
# Copy the binary built in the 1st stage
COPY --from=build /helidon/target/helidon-quickstart-se .
ENTRYPOINT ["./helidon-quickstart-se"]
EXPOSE 8080

175
README.md Normal file
View File

@@ -0,0 +1,175 @@
# Helidon Quickstart SE
Sample Helidon SE project that includes multiple REST operations.
## Build and run
With JDK11+
```bash
mvn package
java -jar target/helidon-quickstart-se.jar
```
## Exercise the application
```
curl -X GET http://localhost:8080/greet
{"message":"Hello World!"}
curl -X GET http://localhost:8080/greet/Joe
{"message":"Hello Joe!"}
curl -X PUT -H "Content-Type: application/json" -d '{"greeting" : "Hola"}' http://localhost:8080/greet/greeting
curl -X GET http://localhost:8080/greet/Jose
{"message":"Hola Jose!"}
```
## Try health and metrics
```
curl -s -X GET http://localhost:8080/health
{"outcome":"UP",...
. . .
# Prometheus Format
curl -s -X GET http://localhost:8080/metrics
# TYPE base:gc_g1_young_generation_count gauge
. . .
# JSON Format
curl -H 'Accept: application/json' -X GET http://localhost:8080/metrics
{"base":...
. . .
```
## Build the Docker Image
```
docker build -t helidon-quickstart-se .
```
## Start the application with Docker
```
docker run --rm -p 8080:8080 helidon-quickstart-se:latest
```
Exercise the application as described above
## Deploy the application to Kubernetes
```
kubectl cluster-info # Verify which cluster
kubectl get pods # Verify connectivity to cluster
kubectl create -f app.yaml # Deploy application
kubectl get pods # Wait for quickstart pod to be RUNNING
kubectl get service helidon-quickstart-se # Get service info
```
Note the PORTs. You can now exercise the application as you did before but use the second
port number (the NodePort) instead of 8080.
After youre done, cleanup.
```
kubectl delete -f app.yaml
```
## Build a native image with GraalVM
GraalVM allows you to compile your programs ahead-of-time into a native
executable. See https://www.graalvm.org/docs/reference-manual/aot-compilation/
for more information.
You can build a native executable in 2 different ways:
* With a local installation of GraalVM
* Using Docker
### Local build
Download Graal VM at https://www.graalvm.org/downloads, the versions
currently supported for Helidon are `20.1.0` and above.
```
# Setup the environment
export GRAALVM_HOME=/path
# build the native executable
mvn package -Pnative-image
```
You can also put the Graal VM `bin` directory in your PATH, or pass
`-DgraalVMHome=/path` to the Maven command.
See https://github.com/oracle/helidon-build-tools/tree/master/helidon-maven-plugin#goal-native-image
for more information.
Start the application:
```
./target/helidon-quickstart-se
```
### Multi-stage Docker build
Build the "native" Docker Image
```
docker build -t helidon-quickstart-se-native -f Dockerfile.native .
```
Start the application:
```
docker run --rm -p 8080:8080 helidon-quickstart-se-native:latest
```
## Build a Java Runtime Image using jlink
You can build a custom Java Runtime Image (JRI) containing the application jars and the JDK modules
on which they depend. This image also:
* Enables Class Data Sharing by default to reduce startup time.
* Contains a customized `start` script to simplify CDS usage and support debug and test modes.
You can build a custom JRI in two different ways:
* Local
* Using Docker
### Local build
```
# build the JRI
mvn package -Pjlink-image
```
See https://github.com/oracle/helidon-build-tools/tree/master/helidon-maven-plugin#goal-jlink-image
for more information.
Start the application:
```
./target/helidon-quickstart-se-jri/bin/start
```
### Multi-stage Docker build
Build the JRI as a Docker Image
```
docker build -t helidon-quickstart-se-jri -f Dockerfile.jlink .
```
Start the application:
```
docker run --rm -p 8080:8080 helidon-quickstart-se-jri:latest
```
See the start script help:
```
docker run --rm helidon-quickstart-se-jri:latest --help
```

53
app.yaml Normal file
View File

@@ -0,0 +1,53 @@
#
# Copyright (c) 2018, 2019 Oracle and/or its affiliates. All rights reserved.
#
# 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.
#
kind: Service
apiVersion: v1
metadata:
name: helidon-quickstart-se
labels:
app: helidon-quickstart-se
spec:
type: NodePort
selector:
app: helidon-quickstart-se
ports:
- port: 8080
targetPort: 8080
name: http
---
kind: Deployment
apiVersion: apps/v1
metadata:
name: helidon-quickstart-se
spec:
replicas: 1
selector:
matchLabels:
app: helidon-quickstart-se
template:
metadata:
labels:
app: helidon-quickstart-se
version: v1
spec:
containers:
- name: helidon-quickstart-se
image: helidon-quickstart-se
imagePullPolicy: IfNotPresent
ports:
- containerPort: 8080
---

62
helidon-quickstart-se.iml Normal file
View File

@@ -0,0 +1,62 @@
<?xml version="1.0" encoding="UTF-8"?>
<module org.jetbrains.idea.maven.project.MavenProjectsManager.isMavenModule="true" type="JAVA_MODULE" version="4">
<component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_11">
<output url="file://$MODULE_DIR$/target/classes" />
<output-test url="file://$MODULE_DIR$/target/test-classes" />
<content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/src/main/java" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/main/resources" type="java-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/test/java" isTestSource="true" />
<excludeFolder url="file://$MODULE_DIR$/target" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="library" name="Maven: io.helidon.webserver:helidon-webserver:2.3.0" level="project" />
<orderEntry type="library" name="Maven: io.helidon.common:helidon-common-reactive:2.3.0" level="project" />
<orderEntry type="library" name="Maven: io.helidon.common:helidon-common-mapper:2.3.0" level="project" />
<orderEntry type="library" name="Maven: io.helidon.common:helidon-common:2.3.0" level="project" />
<orderEntry type="library" name="Maven: io.helidon.common:helidon-common-http:2.3.0" level="project" />
<orderEntry type="library" name="Maven: io.helidon.media:helidon-media-common:2.3.0" level="project" />
<orderEntry type="library" name="Maven: io.helidon.config:helidon-config:2.3.0" level="project" />
<orderEntry type="library" name="Maven: io.helidon.common:helidon-common-media-type:2.3.0" level="project" />
<orderEntry type="library" name="Maven: io.helidon.common:helidon-common-key-util:2.3.0" level="project" />
<orderEntry type="library" name="Maven: io.helidon.common:helidon-common-configurable:2.3.0" level="project" />
<orderEntry type="library" name="Maven: io.opentracing:opentracing-util:0.33.0" level="project" />
<orderEntry type="library" name="Maven: io.opentracing:opentracing-api:0.33.0" level="project" />
<orderEntry type="library" name="Maven: io.opentracing:opentracing-noop:0.33.0" level="project" />
<orderEntry type="library" name="Maven: io.helidon.tracing:helidon-tracing-config:2.3.0" level="project" />
<orderEntry type="library" name="Maven: io.netty:netty-codec-http:4.1.63.Final" level="project" />
<orderEntry type="library" name="Maven: io.netty:netty-common:4.1.63.Final" level="project" />
<orderEntry type="library" name="Maven: io.netty:netty-transport:4.1.63.Final" level="project" />
<orderEntry type="library" name="Maven: io.netty:netty-codec:4.1.63.Final" level="project" />
<orderEntry type="library" name="Maven: io.netty:netty-codec-http2:4.1.63.Final" level="project" />
<orderEntry type="library" name="Maven: io.netty:netty-handler:4.1.63.Final" level="project" />
<orderEntry type="library" name="Maven: io.netty:netty-resolver:4.1.63.Final" level="project" />
<orderEntry type="library" name="Maven: io.helidon.media:helidon-media-jsonp:2.3.0" level="project" />
<orderEntry type="library" name="Maven: org.glassfish:jakarta.json:1.1.6" level="project" />
<orderEntry type="library" name="Maven: io.helidon.config:helidon-config-yaml:2.3.0" level="project" />
<orderEntry type="library" name="Maven: org.yaml:snakeyaml:1.27" level="project" />
<orderEntry type="library" name="Maven: jakarta.annotation:jakarta.annotation-api:1.3.5" level="project" />
<orderEntry type="library" name="Maven: org.eclipse.microprofile.config:microprofile-config-api:1.4" level="project" />
<orderEntry type="library" name="Maven: io.helidon.health:helidon-health:2.3.0" level="project" />
<orderEntry type="library" name="Maven: io.helidon.fault-tolerance:helidon-fault-tolerance:2.3.0" level="project" />
<orderEntry type="library" name="Maven: org.eclipse.microprofile.health:microprofile-health-api:2.2" level="project" />
<orderEntry type="library" name="Maven: io.helidon.webserver:helidon-webserver-cors:2.3.0" level="project" />
<orderEntry type="library" name="Maven: io.helidon.health:helidon-health-checks:2.3.0" level="project" />
<orderEntry type="library" name="Maven: io.helidon.health:helidon-health-common:2.3.0" level="project" />
<orderEntry type="library" name="Maven: io.helidon.metrics:helidon-metrics:2.3.0" level="project" />
<orderEntry type="library" name="Maven: io.helidon.config:helidon-config-mp:2.3.0" level="project" />
<orderEntry type="library" name="Maven: io.helidon.common:helidon-common-service-loader:2.3.0" level="project" />
<orderEntry type="library" name="Maven: org.eclipse.microprofile.metrics:microprofile-metrics-api:2.3.2" level="project" />
<orderEntry type="library" name="Maven: io.helidon.service-common:helidon-service-common-rest:2.3.0" level="project" />
<orderEntry type="library" scope="TEST" name="Maven: org.junit.jupiter:junit-jupiter-api:5.7.0" level="project" />
<orderEntry type="library" scope="TEST" name="Maven: org.apiguardian:apiguardian-api:1.1.0" level="project" />
<orderEntry type="library" scope="TEST" name="Maven: org.opentest4j:opentest4j:1.2.0" level="project" />
<orderEntry type="library" scope="TEST" name="Maven: org.junit.platform:junit-platform-commons:1.7.0" level="project" />
<orderEntry type="library" scope="TEST" name="Maven: io.helidon.webclient:helidon-webclient:2.3.0" level="project" />
<orderEntry type="library" name="Maven: io.helidon.common:helidon-common-context:2.3.0" level="project" />
<orderEntry type="library" name="Maven: io.netty:netty-buffer:4.1.63.Final" level="project" />
<orderEntry type="library" scope="TEST" name="Maven: io.netty:netty-handler-proxy:4.1.63.Final" level="project" />
<orderEntry type="library" scope="TEST" name="Maven: io.netty:netty-codec-socks:4.1.63.Final" level="project" />
</component>
</module>

23
jreleaser.yml Normal file
View File

@@ -0,0 +1,23 @@
project:
name: helidon-quickstart-se
version: 1.0.0-SNAPSHOT
description: helidon-quickstart-se
longDescription: A simple helidon-quickstart-se quickstart
website: https://acme.com/app
authors:
- jlengrand
license: Apache-2
java:
groupId: io.helidon.examples.quickstart.se
version: 8
extraProperties:
inceptionYear: 2021
release:
github:
owner: jlengrand
distributions:
app:
artifacts:
- path: target/helidon-quickstart-se.jar

View File

@@ -0,0 +1 @@
18d8e2a55406eb15cfe3da97abfd49b041be168adad8dcd1cb619667b61a992b

View File

@@ -0,0 +1 @@
18d8e2a55406eb15cfe3da97abfd49b041be168adad8dcd1cb619667b61a992b app/helidon-quickstart-se.jar

View File

@@ -0,0 +1,16 @@
#JReleaser 0.4.0
#Mon Jun 07 21:19:42 CEST 2021
commitFullHash=ea792e845c2583781817fec4f7286cb0fa2bcce5
commitShortHash=ea792e8
javaVersion=11.0.10
milestoneName=early-access
projectName=helidon-quickstart-se
projectSnapshot=true
projectVersion=1.0.0-SNAPSHOT
projectVersionMajor=1
projectVersionMinor=0
projectVersionPatch=0
projectVersionTag=SNAPSHOT
releaseName=Release early-access
tagName=early-access
timestamp=2021-06-07T21\:19\:39.915208+02\:00

View File

@@ -0,0 +1,2 @@
## Changelog

80
pom.xml Normal file
View File

@@ -0,0 +1,80 @@
<?xml version="1.0" encoding="UTF-8"?>
<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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>io.helidon.applications</groupId>
<artifactId>helidon-se</artifactId>
<version>2.3.0</version>
<relativePath/>
</parent>
<groupId>io.helidon.examples</groupId>
<artifactId>helidon-quickstart-se</artifactId>
<version>1.0-SNAPSHOT</version>
<name>myproject</name>
<properties>
<mainClass>io.helidon.examples.quickstart.se.Main</mainClass>
</properties>
<dependencies>
<dependency>
<groupId>io.helidon.webserver</groupId>
<artifactId>helidon-webserver</artifactId>
</dependency>
<dependency>
<groupId>io.helidon.media</groupId>
<artifactId>helidon-media-jsonp</artifactId>
</dependency>
<dependency>
<groupId>io.helidon.config</groupId>
<artifactId>helidon-config-yaml</artifactId>
</dependency>
<dependency>
<groupId>io.helidon.health</groupId>
<artifactId>helidon-health</artifactId>
</dependency>
<dependency>
<groupId>io.helidon.health</groupId>
<artifactId>helidon-health-checks</artifactId>
</dependency>
<dependency>
<groupId>io.helidon.metrics</groupId>
<artifactId>helidon-metrics</artifactId>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.helidon.webclient</groupId>
<artifactId>helidon-webclient</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<id>copy-libs</id>
</execution>
</executions>
</plugin>
<plugin>
<groupId>io.helidon.build-tools</groupId>
<artifactId>helidon-maven-plugin</artifactId>
<executions>
<execution>
<id>third-party-license-report</id>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>

View File

@@ -0,0 +1,137 @@
package io.helidon.examples.quickstart.se;
import java.util.Collections;
import java.util.concurrent.atomic.AtomicReference;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.json.Json;
import javax.json.JsonBuilderFactory;
import javax.json.JsonException;
import javax.json.JsonObject;
import io.helidon.common.http.Http;
import io.helidon.config.Config;
import io.helidon.webserver.Routing;
import io.helidon.webserver.ServerRequest;
import io.helidon.webserver.ServerResponse;
import io.helidon.webserver.Service;
/**
* A simple service to greet you. Examples:
*
* Get default greeting message:
* curl -X GET http://localhost:8080/greet
*
* Get greeting message for Joe:
* curl -X GET http://localhost:8080/greet/Joe
*
* 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
*/
public class GreetService implements Service {
/**
* 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"));
}
/**
* 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);
}
/**
* Return a worldly greeting message.
* @param request the server request
* @param response the server response
*/
private void getDefaultMessageHandler(ServerRequest request, 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");
sendResponse(response, name);
}
private void sendResponse(ServerResponse response, String name) {
String msg = String.format("%s %s!", greeting.get(), name);
JsonObject returnObject = JSON.createObjectBuilder()
.add("message", msg)
.build();
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")
.build();
response.status(Http.Status.BAD_REQUEST_400)
.send(jsonErrorObject);
return;
}
greeting.set(jo.getString("greeting"));
response.status(Http.Status.NO_CONTENT_204).send();
}
/**
* 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));
}
}

View File

@@ -0,0 +1,86 @@
package io.helidon.examples.quickstart.se;
import io.helidon.common.LogConfig;
import io.helidon.common.reactive.Single;
import io.helidon.config.Config;
import io.helidon.health.HealthSupport;
import io.helidon.health.checks.HealthChecks;
import io.helidon.media.jsonp.JsonpSupport;
import io.helidon.metrics.MetricsSupport;
import io.helidon.webserver.Routing;
import io.helidon.webserver.WebServer;
/**
* The application main class.
*/
public final class Main {
/**
* Cannot be instantiated.
*/
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() {
// load logging configuration
LogConfig.configureRuntime();
// By default this will pick up application.yaml from the classpath
Config config = Config.create();
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;
}
/**
* Creates new {@link Routing}.
*
* @return routing configured with JSON support, a health check, and a service
* @param config configuration of this server
*/
private static Routing createRouting(Config config) {
MetricsSupport metrics = MetricsSupport.create();
GreetService greetService = new GreetService(config);
HealthSupport health = HealthSupport.builder()
.addLiveness(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();
}
}

View File

@@ -0,0 +1,2 @@
package io.helidon.examples.quickstart.se;

View File

@@ -0,0 +1 @@
[]

View File

@@ -0,0 +1,7 @@
app:
greeting: "Hello"
server:
port: 8080
host: 0.0.0.0

View File

@@ -0,0 +1,19 @@
# Example Logging Configuration File
# For more information see $JAVA_HOME/jre/lib/logging.properties
# Send messages to the console
handlers=io.helidon.common.HelidonConsoleHandler
# HelidonConsoleHandler uses a SimpleFormatter subclass that replaces "!thread!" with the current thread
java.util.logging.SimpleFormatter.format=%1$tY.%1$tm.%1$td %1$tH:%1$tM:%1$tS %4$s %3$s !thread!: %5$s%6$s%n
# Global logging level. Can be overridden by specific loggers
.level=INFO
# Component specific log levels
#io.helidon.webserver.level=INFO
#io.helidon.config.level=INFO
#io.helidon.security.level=INFO
#io.helidon.common.level=INFO
#io.netty.level=INFO

View File

@@ -0,0 +1,96 @@
package io.helidon.examples.quickstart.se;
import java.util.Collections;
import java.util.concurrent.TimeUnit;
import javax.json.Json;
import javax.json.JsonBuilderFactory;
import javax.json.JsonObject;
import io.helidon.media.jsonp.JsonpSupport;
import io.helidon.webclient.WebClient;
import io.helidon.webclient.WebClientResponse;
import io.helidon.webserver.WebServer;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertEquals;
public class MainTest {
private static WebServer webServer;
private static WebClient webClient;
private static final JsonBuilderFactory JSON_BUILDER = Json.createBuilderFactory(Collections.emptyMap());
private static final JsonObject TEST_JSON_OBJECT;
static {
TEST_JSON_OBJECT = JSON_BUILDER.createObjectBuilder()
.add("greeting", "Hola")
.build();
}
@BeforeAll
public static void startTheServer() {
webServer = Main.startServer().await();
webClient = WebClient.builder()
.baseUri("http://localhost:" + webServer.port())
.addMediaSupport(JsonpSupport.create())
.build();
}
@AfterAll
public static void stopServer() throws Exception {
if (webServer != null) {
webServer.shutdown()
.toCompletableFuture()
.get(10, TimeUnit.SECONDS);
}
}
@Test
public void testHelloWorld() {
JsonObject jsonObject;
WebClientResponse response;
jsonObject = webClient.get()
.path("/greet")
.request(JsonObject.class)
.await();
assertEquals("Hello World!", jsonObject.getString("message"));
jsonObject = webClient.get()
.path("/greet/Joe")
.request(JsonObject.class)
.await();
assertEquals("Hello Joe!", jsonObject.getString("message"));
response = webClient.put()
.path("/greet/greeting")
.submit(TEST_JSON_OBJECT)
.await();
assertEquals(204, response.status().code());
jsonObject = webClient.get()
.path("/greet/Joe")
.request(JsonObject.class)
.await();
assertEquals("Hola Joe!", jsonObject.getString("message"));
response = webClient.get()
.path("/health")
.request()
.await();
assertEquals(200, response.status().code());
response = webClient.get()
.path("/metrics")
.request()
.await();
assertEquals(200, response.status().code());
}
}