mirror of
https://github.com/jlengrand/helidon-jereleaser.git
synced 2026-03-10 00:11:19 +00:00
Create repo
This commit is contained in:
1
.dockerignore
Normal file
1
.dockerignore
Normal file
@@ -0,0 +1 @@
|
||||
target/*
|
||||
29
.gitignore
vendored
Normal file
29
.gitignore
vendored
Normal 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
30
Dockerfile
Normal 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
25
Dockerfile.jlink
Normal 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
29
Dockerfile.native
Normal 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
175
README.md
Normal 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 you’re 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
53
app.yaml
Normal 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
62
helidon-quickstart-se.iml
Normal 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
23
jreleaser.yml
Normal 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
|
||||
@@ -0,0 +1 @@
|
||||
18d8e2a55406eb15cfe3da97abfd49b041be168adad8dcd1cb619667b61a992b
|
||||
1
out/jreleaser/checksums/checksums_sha256.txt
Normal file
1
out/jreleaser/checksums/checksums_sha256.txt
Normal file
@@ -0,0 +1 @@
|
||||
18d8e2a55406eb15cfe3da97abfd49b041be168adad8dcd1cb619667b61a992b app/helidon-quickstart-se.jar
|
||||
16
out/jreleaser/output.properties
Normal file
16
out/jreleaser/output.properties
Normal 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
|
||||
2
out/jreleaser/release/CHANGELOG.md
Normal file
2
out/jreleaser/release/CHANGELOG.md
Normal file
@@ -0,0 +1,2 @@
|
||||
## Changelog
|
||||
|
||||
80
pom.xml
Normal file
80
pom.xml
Normal 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>
|
||||
@@ -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));
|
||||
}
|
||||
}
|
||||
86
src/main/java/io/helidon/examples/quickstart/se/Main.java
Normal file
86
src/main/java/io/helidon/examples/quickstart/se/Main.java
Normal 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();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
|
||||
package io.helidon.examples.quickstart.se;
|
||||
@@ -0,0 +1 @@
|
||||
[]
|
||||
7
src/main/resources/application.yaml
Normal file
7
src/main/resources/application.yaml
Normal file
@@ -0,0 +1,7 @@
|
||||
|
||||
app:
|
||||
greeting: "Hello"
|
||||
|
||||
server:
|
||||
port: 8080
|
||||
host: 0.0.0.0
|
||||
19
src/main/resources/logging.properties
Normal file
19
src/main/resources/logging.properties
Normal 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
|
||||
@@ -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());
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user