From 35654cd2a38420e3c3971bd48631aa6d28085f99 Mon Sep 17 00:00:00 2001 From: Paulo Lopes Date: Thu, 29 Jul 2021 12:22:00 +0200 Subject: [PATCH 1/2] Modernize the vert.x template Signed-off-by: Paulo Lopes --- template/java11-vert-x/README.md | 31 ++++++------ .../java11-vert-x/entrypoint/build.gradle | 4 +- .../java/com/openfaas/entrypoint/App.java | 48 ++++++++++++------- template/java11-vert-x/function/build.gradle | 4 +- .../com/openfaas/function/FaaSFunction.java | 32 +++++++++++++ .../java/com/openfaas/function/Handler.java | 17 ------- .../src/test/java/FaaSFunctionTest.java | 10 ++++ .../function/src/test/java/HandlerTest.java | 11 ----- 8 files changed, 93 insertions(+), 64 deletions(-) create mode 100644 template/java11-vert-x/function/src/main/java/com/openfaas/function/FaaSFunction.java delete mode 100644 template/java11-vert-x/function/src/main/java/com/openfaas/function/Handler.java create mode 100644 template/java11-vert-x/function/src/test/java/FaaSFunctionTest.java delete mode 100644 template/java11-vert-x/function/src/test/java/HandlerTest.java diff --git a/template/java11-vert-x/README.md b/template/java11-vert-x/README.md index a407c0c5..1435442f 100644 --- a/template/java11-vert-x/README.md +++ b/template/java11-vert-x/README.md @@ -11,21 +11,17 @@ There are two projects which make up a single gradle build: - function - (Library) your function code as a developer, you will only ever see this folder - entrypoint - (App) Vert.x HTTP server -### Handler +### FaaSFunction -The handler is written in the `./src/main/java/com/openfaas/function/Handler.java` folder +The function is written in the `./src/main/java/com/openfaas/function/FaaSFunction.java` folder -Tests are supported with junit via files in `./src/test` - -### External dependencies +The function can optionally implement the interface `Handler`. When this is true, the entrypoint will mount the function on any HTTP verb at the end of the router. -External dependencies can be specified in ./build.gradle in the normal way using jcenter, a local JAR or some other remote repository. - -### Serve a "pure" static html web application +Helper handlers can be added to the router in the `setUp()` method. This is useful for example to enable the `BodyHandler` which will parse request body of requests. -This template allow you to serve static html assets (eg: single page application) +#### Serve a "pure" static html web application -#### First, update your yaml deployment file: +This template can serve static html assets (eg: single page application). This is an example of using the `setUp()` example. You only need to add to the `environment` key, a `FRONTAPP` variable (with a value set to `true`) @@ -34,14 +30,19 @@ environment: FRONTAPP: true ``` -#### Then add assets in the webroot directory - Put your static assets in this directory: `/src/main/resources/webroot` -> If `FRONTAPP` is set to `false` (or does not exist), it's the `Handler` instance that serves the data. +> If `FRONTAPP` is set to `false` (or does not exist), it's the `FaaSFunction` instance that serves the data. +#### Testing the function + +Tests are supported with junit via files in `./src/test` + +### External dependencies + +External dependencies can be specified in ./build.gradle in the normal way using jcenter, a local JAR or some other remote repository. -#### Deployment yaml file sample: +### Deployment yaml file sample: ```yaml provider: @@ -51,7 +52,7 @@ functions: hello-vert-x: lang: java11-vert-x environment: - FRONTAPP: true + FRONTAPP: false handler: ./function image: registry.test:5000/hello-vert-x:latest ``` diff --git a/template/java11-vert-x/entrypoint/build.gradle b/template/java11-vert-x/entrypoint/build.gradle index e4514524..1f2c261b 100644 --- a/template/java11-vert-x/entrypoint/build.gradle +++ b/template/java11-vert-x/entrypoint/build.gradle @@ -20,10 +20,10 @@ mainClassName = 'App' dependencies { // Vert.x project - compile 'io.vertx:vertx-web:3.5.4' + compile 'io.vertx:vertx-web:4.1.2' // Use JUnit test framework - testCompile 'junit:junit:4.12' + testCompile 'junit:junit:4.13.1' compile project(':function') } diff --git a/template/java11-vert-x/entrypoint/src/main/java/com/openfaas/entrypoint/App.java b/template/java11-vert-x/entrypoint/src/main/java/com/openfaas/entrypoint/App.java index 84c41bed..594a3f6b 100644 --- a/template/java11-vert-x/entrypoint/src/main/java/com/openfaas/entrypoint/App.java +++ b/template/java11-vert-x/entrypoint/src/main/java/com/openfaas/entrypoint/App.java @@ -2,6 +2,8 @@ // Licensed under the MIT license. See LICENSE file in the project root for full license information. package com.openfaas.entrypoint; +import com.openfaas.function.FaaSFunction; +import io.vertx.core.Handler; import io.vertx.core.http.HttpServer; import io.vertx.core.Vertx; import io.vertx.ext.web.Router; @@ -10,26 +12,38 @@ import java.util.Optional; public class App { - public static void main(String[] args) throws Exception { + public static void main(String[] args) { Vertx vertx = Vertx.vertx(); - Integer httpPort = Integer.parseInt(Optional.ofNullable(System.getenv("PORT")).orElse("8082")); - HttpServer server = vertx.createHttpServer(); Router router = Router.router(vertx); - - if (Boolean.parseBoolean(Optional.ofNullable(System.getenv("FRONTAPP")).orElse("false"))) { - // serve static assets, see /resources/webroot directory - router.route("/*").handler(StaticHandler.create()); - } else { - io.vertx.core.Handler handler = new com.openfaas.function.Handler(); - router.route().handler(handler); + try { + final FaaSFunction fn = new FaaSFunction(); + fn.setUp(router) + .onFailure(App::fail) + .onSuccess(ready -> { + Object ref = fn; + if (ref instanceof Handler) { + router.route() + .handler((Handler) ref); + } + listen(vertx, router); + }); + } catch (RuntimeException e) { + fail(e); } + } + + private static void listen(Vertx vertx, Router router) { + int httpPort = Integer.parseInt(Optional.ofNullable(System.getenv("PORT")).orElse("8082")); + HttpServer server = vertx.createHttpServer(); + + server.requestHandler(router) + .listen(httpPort) + .onFailure(App::fail) + .onSuccess(res -> System.out.println("Listening on port " + httpPort)); + } - server.requestHandler(router::accept).listen(httpPort, result -> { - if(result.succeeded()) { - System.out.println("Listening on port " + httpPort); - } else { - System.out.println("Unable to start server: " + result.cause().getMessage()); - } - }); + private static void fail(Throwable err) { + err.printStackTrace(); + System.exit(1); } } diff --git a/template/java11-vert-x/function/build.gradle b/template/java11-vert-x/function/build.gradle index 2e8b4339..88a5fb7f 100644 --- a/template/java11-vert-x/function/build.gradle +++ b/template/java11-vert-x/function/build.gradle @@ -13,10 +13,10 @@ plugins { dependencies { // Vert.x project - compile 'io.vertx:vertx-web:3.5.4' + compile 'io.vertx:vertx-web:4.1.2' // Use JUnit test framework - testImplementation 'junit:junit:4.12' + testImplementation 'junit:junit:4.13.1' } // In this section you declare where to find the dependencies of your project diff --git a/template/java11-vert-x/function/src/main/java/com/openfaas/function/FaaSFunction.java b/template/java11-vert-x/function/src/main/java/com/openfaas/function/FaaSFunction.java new file mode 100644 index 00000000..3056ad08 --- /dev/null +++ b/template/java11-vert-x/function/src/main/java/com/openfaas/function/FaaSFunction.java @@ -0,0 +1,32 @@ +package com.openfaas.function; + +import io.vertx.core.Future; +import io.vertx.core.Handler; +import io.vertx.ext.web.Router; +import io.vertx.ext.web.RoutingContext; +import io.vertx.core.json.JsonObject; +import io.vertx.ext.web.handler.StaticHandler; + +import java.util.Optional; + +public class FaaSFunction implements Handler { + + public Future setUp(Router router) { + // allow customization of the router + // for example, mount extra handlers like BodyHandler, CORS, etc... + + if (Boolean.parseBoolean(Optional.ofNullable(System.getenv("FRONTAPP")).orElse("false"))) { + // serve static assets, see /resources/webroot directory + router.route() + .handler(StaticHandler.create()); + } + + return Future.succeededFuture(); + } + + public void handle(RoutingContext ctx) { + ctx.json( + new JsonObject() + .put("status", "ok")); + } +} diff --git a/template/java11-vert-x/function/src/main/java/com/openfaas/function/Handler.java b/template/java11-vert-x/function/src/main/java/com/openfaas/function/Handler.java deleted file mode 100644 index 6736fc28..00000000 --- a/template/java11-vert-x/function/src/main/java/com/openfaas/function/Handler.java +++ /dev/null @@ -1,17 +0,0 @@ -package com.openfaas.function; - -import io.vertx.ext.web.RoutingContext; -import io.vertx.core.json.JsonObject; - -public class Handler implements io.vertx.core.Handler { - - public void handle(RoutingContext routingContext) { - routingContext.response() - .putHeader("content-type", "application/json;charset=UTF-8") - .end( - new JsonObject() - .put("status", "ok") - .encodePrettily() - ); - } -} diff --git a/template/java11-vert-x/function/src/test/java/FaaSFunctionTest.java b/template/java11-vert-x/function/src/test/java/FaaSFunctionTest.java new file mode 100644 index 00000000..5c9a8ffe --- /dev/null +++ b/template/java11-vert-x/function/src/test/java/FaaSFunctionTest.java @@ -0,0 +1,10 @@ +import com.openfaas.function.FaaSFunction; +import org.junit.Test; +import static org.junit.Assert.*; + +public class FaaSFunctionTest { + @Test public void handlerIsNotNull() { + FaaSFunction function = new FaaSFunction(); + assertTrue("Expected function not to be null", function != null); + } +} diff --git a/template/java11-vert-x/function/src/test/java/HandlerTest.java b/template/java11-vert-x/function/src/test/java/HandlerTest.java deleted file mode 100644 index 99ab40a7..00000000 --- a/template/java11-vert-x/function/src/test/java/HandlerTest.java +++ /dev/null @@ -1,11 +0,0 @@ -import org.junit.Test; -import static org.junit.Assert.*; - -import com.openfaas.function.Handler; - -public class HandlerTest { - @Test public void handlerIsNotNull() { - Handler handler = new Handler(); - assertTrue("Expected handler not to be null", handler != null); - } -} From ede48ca606d57ce08c0c939928e2728afd7bd20e Mon Sep 17 00:00:00 2001 From: Paulo Lopes Date: Thu, 29 Jul 2021 12:37:15 +0200 Subject: [PATCH 2/2] Pass vertx to setup so async IO operations can be performed during setup Signed-off-by: Paulo Lopes --- .../src/main/java/com/openfaas/entrypoint/App.java | 7 ++++--- .../src/main/java/com/openfaas/function/FaaSFunction.java | 3 ++- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/template/java11-vert-x/entrypoint/src/main/java/com/openfaas/entrypoint/App.java b/template/java11-vert-x/entrypoint/src/main/java/com/openfaas/entrypoint/App.java index 594a3f6b..d8379a27 100644 --- a/template/java11-vert-x/entrypoint/src/main/java/com/openfaas/entrypoint/App.java +++ b/template/java11-vert-x/entrypoint/src/main/java/com/openfaas/entrypoint/App.java @@ -13,11 +13,12 @@ public class App { public static void main(String[] args) { - Vertx vertx = Vertx.vertx(); - Router router = Router.router(vertx); + final Vertx vertx = Vertx.vertx(); + final Router router = Router.router(vertx); + try { final FaaSFunction fn = new FaaSFunction(); - fn.setUp(router) + fn.setUp(vertx, router) .onFailure(App::fail) .onSuccess(ready -> { Object ref = fn; diff --git a/template/java11-vert-x/function/src/main/java/com/openfaas/function/FaaSFunction.java b/template/java11-vert-x/function/src/main/java/com/openfaas/function/FaaSFunction.java index 3056ad08..b9fdc47f 100644 --- a/template/java11-vert-x/function/src/main/java/com/openfaas/function/FaaSFunction.java +++ b/template/java11-vert-x/function/src/main/java/com/openfaas/function/FaaSFunction.java @@ -2,6 +2,7 @@ import io.vertx.core.Future; import io.vertx.core.Handler; +import io.vertx.core.Vertx; import io.vertx.ext.web.Router; import io.vertx.ext.web.RoutingContext; import io.vertx.core.json.JsonObject; @@ -11,7 +12,7 @@ public class FaaSFunction implements Handler { - public Future setUp(Router router) { + public Future setUp(Vertx vertx, Router router) { // allow customization of the router // for example, mount extra handlers like BodyHandler, CORS, etc...