diff --git a/archetypes/helidon/src/main/archetype/common/files/README.md.mustache b/archetypes/helidon/src/main/archetype/common/files/README.md.mustache index 2e13680e1b3..5f424a76984 100644 --- a/archetypes/helidon/src/main/archetype/common/files/README.md.mustache +++ b/archetypes/helidon/src/main/archetype/common/files/README.md.mustache @@ -8,10 +8,10 @@ {{.}} {{/run-comment}} -With JDK17+ +With JDK19+ ```bash mvn package -java -jar target/{{artifactId}}.jar +java --enable-preview -jar target/{{artifactId}}.jar ``` ## Exercise the application diff --git a/archetypes/helidon/src/main/archetype/flavor.xml b/archetypes/helidon/src/main/archetype/flavor.xml index fd1381cac41..f007298207e 100644 --- a/archetypes/helidon/src/main/archetype/flavor.xml +++ b/archetypes/helidon/src/main/archetype/flavor.xml @@ -1,7 +1,7 @@ + + + + + + ${package}.Main + helidon-nima + + + io.helidon.nima.webserver + helidon-nima-webserver + + + org.junit.jupiter + junit-jupiter-api + test + + + org.hamcrest + hamcrest-all + test + + + io.helidon.nima.testing.junit5 + helidon-nima-testing-junit5-webserver + test + + + + io.helidon.logging.common.LogConfig + io.helidon.nima.webserver.WebServer + io.helidon.nima.webserver.http.HttpRouting + + + io.helidon.common.http.Http + io.helidon.nima.testing.junit5.webserver.SetUpRoute + io.helidon.nima.webclient.http1.Http1Client + io.helidon.nima.webclient.http1.Http1ClientResponse + io.helidon.nima.webserver.http.HttpRouting + + + org.junit.jupiter.api.Test + + + static org.hamcrest.MatcherAssert.assertThat + static org.hamcrest.Matchers.is + + + + diff --git a/archetypes/helidon/src/main/archetype/nima/common/files/src/main/java/__pkg__/Main.java.mustache b/archetypes/helidon/src/main/archetype/nima/common/files/src/main/java/__pkg__/Main.java.mustache new file mode 100644 index 00000000000..20f323a5fb1 --- /dev/null +++ b/archetypes/helidon/src/main/archetype/nima/common/files/src/main/java/__pkg__/Main.java.mustache @@ -0,0 +1,55 @@ +package {{package}}; + +{{#Main-java-imports}} +import {{.}}; +{{/Main-java-imports}} + +{{#Main-helidon-imports}} +import {{.}}; +{{/Main-helidon-imports}} + +{{#Main-other-imports}} +import {{.}}; +{{/Main-other-imports}} + +{{#Main-static-imports}} +import {{.}}; +{{/Main-static-imports}} + +/** + * 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) { + // load logging configuration + LogConfig.configureRuntime(); + + WebServer server = WebServer.builder() + .routing(Main::routing) + .start(); + + System.out.println("WEB server is up! http://localhost:" + server.port() + "/greet"); + } + + /** + * Updates HTTP Routing. + */ + static void routing(HttpRouting.Builder routing) { + {{#Main-routing}}{{.}} + {{/Main-routing}} + + routing{{#Main-routing-builder}}{{.}}{{#last}}; {{/last}} + {{/Main-routing-builder}} + } +} diff --git a/archetypes/helidon/src/main/archetype/nima/common/files/src/main/java/__pkg__/package-info.java.mustache b/archetypes/helidon/src/main/archetype/nima/common/files/src/main/java/__pkg__/package-info.java.mustache new file mode 100644 index 00000000000..7f3c8c7a43c --- /dev/null +++ b/archetypes/helidon/src/main/archetype/nima/common/files/src/main/java/__pkg__/package-info.java.mustache @@ -0,0 +1 @@ +package {{package}}; diff --git a/archetypes/helidon/src/main/archetype/nima/common/files/src/main/resources/application.yaml.mustache b/archetypes/helidon/src/main/archetype/nima/common/files/src/main/resources/application.yaml.mustache new file mode 100644 index 00000000000..65cf9a33b3c --- /dev/null +++ b/archetypes/helidon/src/main/archetype/nima/common/files/src/main/resources/application.yaml.mustache @@ -0,0 +1,6 @@ +server: + port: 8080 + host: 0.0.0.0 + +{{#application-yaml-entries}}{{.}} +{{/application-yaml-entries}} \ No newline at end of file diff --git a/archetypes/helidon/src/main/archetype/nima/common/files/src/main/resources/logging.properties.mustache b/archetypes/helidon/src/main/archetype/nima/common/files/src/main/resources/logging.properties.mustache new file mode 100644 index 00000000000..f494a314705 --- /dev/null +++ b/archetypes/helidon/src/main/archetype/nima/common/files/src/main/resources/logging.properties.mustache @@ -0,0 +1,5 @@ +handlers=java.util.logging.ConsoleHandler +java.util.logging.SimpleFormatter.format=%1$tY.%1$tm.%1$td %1$tH:%1$tM:%1$tS.%1$tL %5$s%6$s%n +# Global logging level. Can be overridden by specific loggers +.level=INFO +io.helidon.nima.level=INFO diff --git a/archetypes/helidon/src/main/archetype/nima/common/files/src/test/java/__pkg__/AbstractMainTest.java.mustache b/archetypes/helidon/src/main/archetype/nima/common/files/src/test/java/__pkg__/AbstractMainTest.java.mustache new file mode 100644 index 00000000000..0906190e7b8 --- /dev/null +++ b/archetypes/helidon/src/main/archetype/nima/common/files/src/test/java/__pkg__/AbstractMainTest.java.mustache @@ -0,0 +1,34 @@ +package {{package}}; + +{{#MainTest-java-imports}} +import {{.}}; +{{/MainTest-java-imports}} + +{{#MainTest-helidon-imports}} +import {{.}}; +{{/MainTest-helidon-imports}} + +{{#MainTest-other-imports}} +import {{.}}; +{{/MainTest-other-imports}} + +{{#MainTest-static-imports}} +import {{.}}; +{{/MainTest-static-imports}} + +abstract class AbstractMainTest { + private final Http1Client client; + + protected AbstractMainTest(Http1Client client) { + this.client = client; + } + + @SetUpRoute + static void routing(HttpRouting.Builder builder) { + Main.routing(builder); + } + + {{#Abstract-tests}}{{.}} + {{/Abstract-tests}} + +} diff --git a/archetypes/helidon/src/main/archetype/nima/common/files/src/test/java/__pkg__/MainIT.java.mustache b/archetypes/helidon/src/main/archetype/nima/common/files/src/test/java/__pkg__/MainIT.java.mustache new file mode 100644 index 00000000000..fd40620f90d --- /dev/null +++ b/archetypes/helidon/src/main/archetype/nima/common/files/src/test/java/__pkg__/MainIT.java.mustache @@ -0,0 +1,11 @@ +package {{package}}; + +import io.helidon.nima.testing.junit5.webserver.ServerTest; +import io.helidon.nima.webclient.http1.Http1Client; + +@ServerTest +class MainIT extends AbstractMainTest { + MainIT(Http1Client client) { + super(client); + } +} \ No newline at end of file diff --git a/archetypes/helidon/src/main/archetype/nima/common/files/src/test/java/__pkg__/MainTest.java.mustache b/archetypes/helidon/src/main/archetype/nima/common/files/src/test/java/__pkg__/MainTest.java.mustache new file mode 100644 index 00000000000..5d3ce19fc5e --- /dev/null +++ b/archetypes/helidon/src/main/archetype/nima/common/files/src/test/java/__pkg__/MainTest.java.mustache @@ -0,0 +1,11 @@ +package {{package}}; + +import io.helidon.nima.testing.junit5.webserver.DirectClient; +import io.helidon.nima.testing.junit5.webserver.RoutingTest; + +@RoutingTest +class MainTest extends AbstractMainTest { + MainTest(DirectClient client) { + super(client); + } +} \ No newline at end of file diff --git a/archetypes/helidon/src/main/archetype/nima/common/files/src/test/resources/application.yaml.mustache b/archetypes/helidon/src/main/archetype/nima/common/files/src/test/resources/application.yaml.mustache new file mode 100644 index 00000000000..5c583c0e652 --- /dev/null +++ b/archetypes/helidon/src/main/archetype/nima/common/files/src/test/resources/application.yaml.mustache @@ -0,0 +1,7 @@ +server: + port: 8080 + host: 0.0.0.0 + +{{#config-test}} +{{.}} +{{/config-test}} \ No newline at end of file diff --git a/archetypes/helidon/src/main/archetype/nima/nima.xml b/archetypes/helidon/src/main/archetype/nima/nima.xml new file mode 100644 index 00000000000..1dc8eeaf8b7 --- /dev/null +++ b/archetypes/helidon/src/main/archetype/nima/nima.xml @@ -0,0 +1,43 @@ + + + + + + + + + + + + + + ${app-type} + + + diff --git a/archetypes/helidon/src/main/archetype/nima/quickstart/files/src/main/java/__pkg__/GreetClientHttp.java.mustache b/archetypes/helidon/src/main/archetype/nima/quickstart/files/src/main/java/__pkg__/GreetClientHttp.java.mustache new file mode 100644 index 00000000000..98ffd1121db --- /dev/null +++ b/archetypes/helidon/src/main/archetype/nima/quickstart/files/src/main/java/__pkg__/GreetClientHttp.java.mustache @@ -0,0 +1,36 @@ +package {{package}}; + +import io.helidon.common.http.Http; +import io.helidon.nima.webclient.WebClient; +import io.helidon.nima.webclient.http1.Http1Client; + +/** + * Executable class that invokes HTTP/1 requests against the server. + */ +public class GreetClientHttp { + private GreetClientHttp() { + } + + /** + * Main method. + * + * @param args ignored + */ + public static void main(String[] args) { + Http1Client client = WebClient.builder() + .baseUri("http://localhost:8080/greet") + .build(); + + String response = client.method(Http.Method.GET) + .request() + .as(String.class); + + System.out.println(response); + + response = client.get("Nima") + .request() + .as(String.class); + + System.out.println(response); + } +} diff --git a/archetypes/helidon/src/main/archetype/nima/quickstart/files/src/main/java/__pkg__/GreetService.java.mustache b/archetypes/helidon/src/main/archetype/nima/quickstart/files/src/main/java/__pkg__/GreetService.java.mustache new file mode 100644 index 00000000000..ab71e8b130e --- /dev/null +++ b/archetypes/helidon/src/main/archetype/nima/quickstart/files/src/main/java/__pkg__/GreetService.java.mustache @@ -0,0 +1,114 @@ +package {{package}}; + +import java.util.Collections; +import java.util.concurrent.atomic.AtomicReference; + +import io.helidon.common.http.Http; +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.JsonObject; + +/** + * A simple service to greet you. Examples: + *

+ * Get default greeting message: + * {@code curl -X GET http://localhost:8080/greet} + *

+ * Get greeting message for Joe: + * {@code curl -X GET http://localhost:8080/greet/Joe} + *

+ * Change greeting + * {@code curl -X PUT -H "Content-Type: application/json" -d '{"greeting" : "Howdy"}' http://localhost:8080/greet/greeting} + *

+ * The message is returned as a JSON object + */ +class GreetService implements HttpService { + + private static final JsonBuilderFactory JSON = Json.createBuilderFactory(Collections.emptyMap()); + + /** + * The config value for the key {@code greeting}. + */ + private final AtomicReference greeting = new AtomicReference<>(); + + GreetService() { + greeting.set("Hello"); + } + + /** + * A service registers itself by updating the routing rules. + * + * @param rules the routing rules. + */ + @Override + 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) { + 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().pathParameters().value("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 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) { + updateGreetingFromJson(request.content().as(JsonObject.class), response); + } + +} diff --git a/archetypes/helidon/src/main/archetype/nima/quickstart/quickstart-nima.xml b/archetypes/helidon/src/main/archetype/nima/quickstart/quickstart-nima.xml new file mode 100644 index 00000000000..7ddfdc0ddc9 --- /dev/null +++ b/archetypes/helidon/src/main/archetype/nima/quickstart/quickstart-nima.xml @@ -0,0 +1,128 @@ + + + + + + + + + + + + + io.helidon.nima.webclient + helidon-nima-webclient + + + io.helidon.nima.http.media + helidon-nima-http-media-jsonp + + + io.helidon.nima.observe + helidon-nima-observe-health + + + io.helidon.config + helidon-config-yaml + + + io.helidon.health + helidon-health-checks + + + jakarta.json + jakarta.json-api + + + + io.helidon.health.checks.DeadlockHealthCheck + io.helidon.health.checks.DiskSpaceHealthCheck + io.helidon.health.checks.HeapMemoryHealthCheck + io.helidon.nima.observe.ObserveFeature + io.helidon.nima.observe.health.HealthFeature + io.helidon.nima.observe.health.HealthObserveProvider + + + + + + + + + jakarta.json.JsonObject + + + + + + +