From 6316f2eb7cbc603e4baa4810fc86a3c13bbdbd23 Mon Sep 17 00:00:00 2001 From: gerardnico Date: Thu, 14 Jan 2021 09:37:16 +0100 Subject: [PATCH 1/5] Added Swagger-Core to generate the OpenAPI file on the fly --- resteasy-examples/README.adoc | 16 +++++++++ resteasy-examples/pom.xml | 31 ++++++++++++++++- .../resteasy/asyncresponse/ApplicationRs.java | 21 ++++++++++++ .../resteasy/asyncresponse/Server.java | 33 ++++++++++++++++--- 4 files changed, 95 insertions(+), 6 deletions(-) create mode 100644 resteasy-examples/src/main/java/io/vertx/examples/resteasy/asyncresponse/ApplicationRs.java diff --git a/resteasy-examples/README.adoc b/resteasy-examples/README.adoc index e8015f43f..eb140620f 100644 --- a/resteasy-examples/README.adoc +++ b/resteasy-examples/README.adoc @@ -47,3 +47,19 @@ Add a product:: PUT /products/ Run the server either in your IDE or on the command line, then open your browser and hit link:http://localhost:8080/ + +=== OpenAPI Schema Generation + +Generate and get the openapi specification at: + + * link:http://localhost:8080/openapi.json + * link:http://localhost:8080/openapi.yaml + +Create the https://github.com/swagger-api/swagger-ui[Swagger console (UI)]: + +[source,bash] +---- +docker run -itd --name console --rm -e URL="http://localhost:8080/openapi.json" -p 8888:8080 swaggerapi/swagger-ui +---- + +and navigate to http://localhost:8888 to open the swagger console diff --git a/resteasy-examples/pom.xml b/resteasy-examples/pom.xml index c1af10a08..1fd049626 100644 --- a/resteasy-examples/pom.xml +++ b/resteasy-examples/pom.xml @@ -6,7 +6,7 @@ io.vertx resteasy-examples - 4.0.0 + 3.8.4 resteasy-example @@ -22,12 +22,41 @@ ${project.version} + + io.vertx + vertx-web + ${project.version} + + org.jboss.resteasy resteasy-vertx ${resteasy.version} + + + io.swagger.core.v3 + swagger-jaxrs2 + 2.1.2 + + + io.swagger.core.v3 + swagger-jaxrs2-servlet-initializer-v2 + 2.1.2 + + + javax.servlet + javax.servlet-api + 3.0.1 + + + + com.fasterxml.jackson.core + jackson-core + 2.12.1 + + diff --git a/resteasy-examples/src/main/java/io/vertx/examples/resteasy/asyncresponse/ApplicationRs.java b/resteasy-examples/src/main/java/io/vertx/examples/resteasy/asyncresponse/ApplicationRs.java new file mode 100644 index 000000000..083033f2d --- /dev/null +++ b/resteasy-examples/src/main/java/io/vertx/examples/resteasy/asyncresponse/ApplicationRs.java @@ -0,0 +1,21 @@ +package io.vertx.examples.resteasy.asyncresponse; + + +import javax.ws.rs.core.Application; +import java.util.HashSet; +import java.util.Set; + +/** + * The Application of the JAX-RS interface + * + */ +public class ApplicationRs extends Application { + + private Set singletons = new HashSet<>(); + @Override + public Set getSingletons() { + return singletons; + } + + +} diff --git a/resteasy-examples/src/main/java/io/vertx/examples/resteasy/asyncresponse/Server.java b/resteasy-examples/src/main/java/io/vertx/examples/resteasy/asyncresponse/Server.java index cefe70bba..b1268d21d 100644 --- a/resteasy-examples/src/main/java/io/vertx/examples/resteasy/asyncresponse/Server.java +++ b/resteasy-examples/src/main/java/io/vertx/examples/resteasy/asyncresponse/Server.java @@ -1,6 +1,9 @@ package io.vertx.examples.resteasy.asyncresponse; +import io.swagger.v3.jaxrs2.integration.resources.OpenApiResource; import io.vertx.core.AbstractVerticle; +import org.jboss.resteasy.plugins.interceptors.CorsFilter; +import org.jboss.resteasy.plugins.server.vertx.VertxRegistry; import org.jboss.resteasy.plugins.server.vertx.VertxRequestHandler; import org.jboss.resteasy.plugins.server.vertx.VertxResteasyDeployment; @@ -12,16 +15,36 @@ public class Server extends AbstractVerticle { @Override public void start() throws Exception { + /** + * Cors + * https://docs.jboss.org/resteasy/docs/4.5.8.Final/userguide/html_single/index.html#d4e2124 + */ + CorsFilter filter = new CorsFilter(); + filter.getAllowedOrigins().add("*"); + filter.setAllowedMethods("OPTIONS, GET, POST, DELETE, PUT, PATCH"); + filter.setAllowedHeaders("Content-Type, Authorization"); + filter.setCorsMaxAge(86400);//Max in FF 86400=24h https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Max-Age + + /** + * https://docs.jboss.org/resteasy/docs/1.1.GA/userguide/html/Installation_Configuration.html#javax.ws.rs.core.Application + */ + ApplicationRs application = new ApplicationRs(); + application.getSingletons().add(filter); + // Build the Jax-RS controller deployment VertxResteasyDeployment deployment = new VertxResteasyDeployment(); + deployment.setApplication(application); deployment.start(); - deployment.getRegistry().addPerInstanceResource(Controller.class); + VertxRegistry registry = deployment.getRegistry(); + registry.addPerInstanceResource(Controller.class); + registry.addPerInstanceResource(OpenApiResource.class); + // Start the front end server using the Jax-RS controller vertx.createHttpServer() - .requestHandler(new VertxRequestHandler(vertx, deployment)) - .listen(8080, ar -> { - System.out.println("Server started on port "+ ar.result().actualPort()); - }); + .requestHandler(new VertxRequestHandler(vertx, deployment)) + .listen(8080, ar -> { + System.out.println("Server started on port "+ ar.result().actualPort()); + }); } } From 4457caf3fea87e1df3422d1794a1ecb46c43bdb3 Mon Sep 17 00:00:00 2001 From: gerardnico Date: Sun, 17 Jan 2021 11:06:55 +0100 Subject: [PATCH 2/5] Version 3.9.5 is working - Added tests --- resteasy-examples/pom.xml | 23 +++++- .../resteasy/asyncresponse/Server.java | 6 +- .../vertx/examples/resteasy/RestEasyTest.java | 81 +++++++++++++++++++ .../io/vertx/example/web/auth/Server.java | 4 +- 4 files changed, 111 insertions(+), 3 deletions(-) create mode 100644 resteasy-examples/src/main/test/io/vertx/examples/resteasy/RestEasyTest.java diff --git a/resteasy-examples/pom.xml b/resteasy-examples/pom.xml index 1fd049626..30db457db 100644 --- a/resteasy-examples/pom.xml +++ b/resteasy-examples/pom.xml @@ -6,13 +6,14 @@ io.vertx resteasy-examples - 3.8.4 + 3.9.5 resteasy-example io.vertx.examples.spring.SpringExampleRunner 3.1.0.Final + 4.13.1 @@ -34,6 +35,26 @@ ${resteasy.version} + + + io.vertx + vertx-unit + ${project.version} + test + + + io.vertx + vertx-web-client + ${project.version} + test + + + junit + junit + ${junit.version} + test + + io.swagger.core.v3 diff --git a/resteasy-examples/src/main/java/io/vertx/examples/resteasy/asyncresponse/Server.java b/resteasy-examples/src/main/java/io/vertx/examples/resteasy/asyncresponse/Server.java index b1268d21d..9a8335c91 100644 --- a/resteasy-examples/src/main/java/io/vertx/examples/resteasy/asyncresponse/Server.java +++ b/resteasy-examples/src/main/java/io/vertx/examples/resteasy/asyncresponse/Server.java @@ -44,7 +44,11 @@ public void start() throws Exception { vertx.createHttpServer() .requestHandler(new VertxRequestHandler(vertx, deployment)) .listen(8080, ar -> { - System.out.println("Server started on port "+ ar.result().actualPort()); + if (ar.succeeded()) { + System.out.println("Server started on port " + ar.result().actualPort()); + } else { + ar.cause().printStackTrace(); + } }); } } diff --git a/resteasy-examples/src/main/test/io/vertx/examples/resteasy/RestEasyTest.java b/resteasy-examples/src/main/test/io/vertx/examples/resteasy/RestEasyTest.java new file mode 100644 index 000000000..f307ebcb9 --- /dev/null +++ b/resteasy-examples/src/main/test/io/vertx/examples/resteasy/RestEasyTest.java @@ -0,0 +1,81 @@ +package io.vertx.examples.resteasy; + +import io.swagger.v3.core.util.Json; +import io.vertx.core.Promise; +import io.vertx.core.Vertx; +import io.vertx.core.json.JsonArray; +import io.vertx.core.json.JsonObject; +import io.vertx.examples.resteasy.asyncresponse.Main; +import io.vertx.ext.unit.Async; +import io.vertx.ext.unit.TestContext; +import io.vertx.ext.unit.junit.VertxUnitRunner; +import io.vertx.ext.web.client.HttpResponse; +import io.vertx.ext.web.client.WebClient; +import io.vertx.ext.web.client.WebClientOptions; +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Test; +import org.junit.runner.RunWith; + +@RunWith(VertxUnitRunner.class) +public class RestEasyTest { + + private static WebClient webClient; + private static Vertx vertx; + + @BeforeClass + public static void setUp() { + + + vertx = Vertx.vertx(); + vertx.deployVerticle(new Main()); + webClient = WebClient.create(vertx, new WebClientOptions() + .setDefaultPort(8080)); + + } + + @AfterClass + public static void tearDown() throws Exception { + vertx.close(); + } + + @Test + public void base(TestContext context) { + Async async = context.async(); + Promise> promise = Promise.promise(); + webClient.get("/products") + .send(ar -> { + if (ar.succeeded()) { + JsonArray jsonArray = ar.result().bodyAsJsonArray(); + System.out.println(Json.pretty(jsonArray)); + context.assertEquals(3, jsonArray.size()); + async.complete(); + } else { + context.fail(ar.cause()); + async.complete(); + } + }); + async.awaitSuccess(5000); + } + + @Test + public void openApi(TestContext context) { + Async async = context.async(); + Promise> promise = Promise.promise(); + webClient.get("/openapi.json") + .send(ar -> { + if (ar.succeeded()) { + JsonObject jsonArray = ar.result().bodyAsJsonObject(); + context.assertEquals(2, jsonArray.size()); + context.assertEquals("3.0.1",jsonArray.getString("openapi")); + async.complete(); + } else { + context.fail(ar.cause()); + async.complete(); + } + }); + async.awaitSuccess(5000); + } + + +} diff --git a/web-examples/src/main/java/io/vertx/example/web/auth/Server.java b/web-examples/src/main/java/io/vertx/example/web/auth/Server.java index 39895d506..0c361755d 100644 --- a/web-examples/src/main/java/io/vertx/example/web/auth/Server.java +++ b/web-examples/src/main/java/io/vertx/example/web/auth/Server.java @@ -33,7 +33,9 @@ public void start() throws Exception { router.route("/private/*").handler(RedirectAuthHandler.create(authn, "/loginpage.html")); // Serve the static private pages from directory 'private' - router.route("/private/*").handler(StaticHandler.create().setCachingEnabled(false).setWebRoot("private")); + router.route("/private/*").handler( + StaticHandler.create().setCachingEnabled(false).setWebRoot("private") + ); // Handles the actual login router.route("/loginhandler").handler(FormLoginHandler.create(authn)); From 99194a9733df6abb78e8af6c36bb16c6a5bb9908 Mon Sep 17 00:00:00 2001 From: gerardnico Date: Sun, 17 Jan 2021 12:18:41 +0100 Subject: [PATCH 3/5] The vertx object was not instantiated because of the static key word. The template engine needs to be inside the start method --- .../src/main/java/io/vertx/example/web/oauth2/Server.java | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/web-examples/src/main/java/io/vertx/example/web/oauth2/Server.java b/web-examples/src/main/java/io/vertx/example/web/oauth2/Server.java index 12edcf82c..4b62efeda 100644 --- a/web-examples/src/main/java/io/vertx/example/web/oauth2/Server.java +++ b/web-examples/src/main/java/io/vertx/example/web/oauth2/Server.java @@ -27,11 +27,12 @@ public static void main(String[] args) { private static final String CLIENT_ID = "57cdaa1952a3f4ee3df8"; private static final String CLIENT_SECRET = "3155eafd33fc947e0fe9f44127055ce1fe876704"; - // In order to use a template we first need to create an engine - private final HandlebarsTemplateEngine engine = HandlebarsTemplateEngine.create(vertx); - @Override public void start() throws Exception { + + // In order to use a template we first need to create an engine + final HandlebarsTemplateEngine engine = HandlebarsTemplateEngine.create(vertx); + // To simplify the development of the web components we use a Router to route all HTTP requests // to organize our code in a reusable way. final Router router = Router.router(vertx); From 27b89ea40aec7e6857ae432966e5525c73af1ae4 Mon Sep 17 00:00:00 2001 From: gerardnico Date: Sun, 17 Jan 2021 12:19:48 +0100 Subject: [PATCH 4/5] React example - Static cache disabled + .gitignore --- .../src/main/java/io/vertx/example/web/react/.gitignore | 1 + .../src/main/java/io/vertx/example/web/react/Server.java | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) create mode 100644 web-examples/src/main/java/io/vertx/example/web/react/.gitignore diff --git a/web-examples/src/main/java/io/vertx/example/web/react/.gitignore b/web-examples/src/main/java/io/vertx/example/web/react/.gitignore new file mode 100644 index 000000000..07e6e472c --- /dev/null +++ b/web-examples/src/main/java/io/vertx/example/web/react/.gitignore @@ -0,0 +1 @@ +/node_modules diff --git a/web-examples/src/main/java/io/vertx/example/web/react/Server.java b/web-examples/src/main/java/io/vertx/example/web/react/Server.java index ba1bc3e3f..2e01148c2 100644 --- a/web-examples/src/main/java/io/vertx/example/web/react/Server.java +++ b/web-examples/src/main/java/io/vertx/example/web/react/Server.java @@ -33,7 +33,7 @@ public void start() throws Exception { router.mountSubRouter("/eventbus", ebHandler.bridge(opts)); // Create a router endpoint for the static content. - router.route().handler(StaticHandler.create()); + router.route().handler(StaticHandler.create().setCachingEnabled(false)); // Start the web server and tell it to use the router to handle requests. vertx.createHttpServer().requestHandler(router).listen(8080); From 439b7d5e6aa9a627797f345da7317fdcfb7a8d62 Mon Sep 17 00:00:00 2001 From: gerardnico Date: Sun, 17 Jan 2021 12:20:10 +0100 Subject: [PATCH 5/5] Static example - Static cache disabled --- .../src/main/java/io/vertx/example/web/staticsite/Server.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web-examples/src/main/java/io/vertx/example/web/staticsite/Server.java b/web-examples/src/main/java/io/vertx/example/web/staticsite/Server.java index ed867a498..8b64fd14d 100644 --- a/web-examples/src/main/java/io/vertx/example/web/staticsite/Server.java +++ b/web-examples/src/main/java/io/vertx/example/web/staticsite/Server.java @@ -47,7 +47,7 @@ public void start() { Router router = Router.router(vertx); // Serve the static pages - router.route().handler(StaticHandler.create()); + router.route().handler(StaticHandler.create().setCachingEnabled(false)); vertx.createHttpServer().requestHandler(router).listen(8080);