This is an automated email from the ASF dual-hosted git repository. aldettinger pushed a commit to branch main in repository https://gitbox.apache.org/repos/asf/camel-quarkus.git
The following commit(s) were added to refs/heads/main by this push: new ae08e2eb69 Add tests for rest-openapi extension (apache#4117) ae08e2eb69 is described below commit ae08e2eb6901c8469cfa8c3c02ac2159dd167a22 Author: Darren Coleman <dcole...@redhat.com> AuthorDate: Thu Sep 22 09:25:59 2022 +0100 Add tests for rest-openapi extension (apache#4117) Fixes #4117 Clarified documentation Registered openapi.json for use on CLASSPATH in native mode Moved file generation to @BeforeAll method for file test Simplified file write in rest-openapi test --- .../pages/reference/extensions/rest-openapi.adoc | 30 +++++++ .../rest-openapi/runtime/src/main/doc/usage.adoc | 25 ++++++ integration-tests/rest-openapi/pom.xml | 38 +++++++- ...RestOpenApiRoutes.java => RestOpenApiBean.java} | 21 +++-- .../rest/openapi/it/RestOpenApiRoutes.java | 15 +++- .../rest/openapi/it/RestOpenapiResource.java | 40 ++++++++- .../src/main/resources/application.properties | 17 ++++ .../rest-openapi/src/main/resources/openapi.json | 100 +++++++++++++++++++++ .../component/rest/openapi/it/RestOpenapiTest.java | 50 ++++++++++- 9 files changed, 324 insertions(+), 12 deletions(-) diff --git a/docs/modules/ROOT/pages/reference/extensions/rest-openapi.adoc b/docs/modules/ROOT/pages/reference/extensions/rest-openapi.adoc index c548336fdf..c6b677b9f6 100644 --- a/docs/modules/ROOT/pages/reference/extensions/rest-openapi.adoc +++ b/docs/modules/ROOT/pages/reference/extensions/rest-openapi.adoc @@ -44,3 +44,33 @@ Or add the coordinates to your existing project: ifeval::[{doc-show-user-guide-link} == true] Check the xref:user-guide/index.adoc[User guide] for more information about writing Camel Quarkus applications. endif::[] + +[id="extensions-rest-openapi-usage"] +== Usage +[id="extensions-rest-openapi-usage-required-dependencies"] +=== Required Dependencies + +A `RestProducerFactory` implementation must be available when using the rest-openapi extension. The currently known extensions are: + +* camel-quarkus-http +* camel-quarkus-netty-http + +Maven users will need to add one of these dependencies to their `pom.xml`, for example: + +[source,xml] +---- +<dependency> + <groupId>org.apache.camel.quarkus</groupId> + <artifactId>camel-quarkus-http</artifactId> +</dependency> +---- + +Depending on which mechanism is used to load the OpenApi specification, additional dependencies may be required. When using the `file` resource locator, the `org.apache.camel.quarkus:camel-quarkus-file` extension must be added as a project dependency. When using `ref` or `bean` to load the specification, not only must the `org.apache.camel.quarkus:camel-quarkus-bean` dependency be added, but the bean itself must be annotated with `@RegisterForReflection`. + +When using the `classpath` resource locator with native code, the path to the OpenAPI specification must be specified in the `quarkus.native.resources.includes` property of the `application.properties` file. For example: + +[source] +---- +quarkus.native.resources.includes=openapi.json +---- + diff --git a/extensions/rest-openapi/runtime/src/main/doc/usage.adoc b/extensions/rest-openapi/runtime/src/main/doc/usage.adoc new file mode 100644 index 0000000000..91399d9285 --- /dev/null +++ b/extensions/rest-openapi/runtime/src/main/doc/usage.adoc @@ -0,0 +1,25 @@ +=== Required Dependencies + +A `RestProducerFactory` implementation must be available when using the rest-openapi extension. The currently known extensions are: + +* camel-quarkus-http +* camel-quarkus-netty-http + +Maven users will need to add one of these dependencies to their `pom.xml`, for example: + +[source,xml] +---- +<dependency> + <groupId>org.apache.camel.quarkus</groupId> + <artifactId>camel-quarkus-http</artifactId> +</dependency> +---- + +Depending on which mechanism is used to load the OpenApi specification, additional dependencies may be required. When using the `file` resource locator, the `org.apache.camel.quarkus:camel-quarkus-file` extension must be added as a project dependency. When using `ref` or `bean` to load the specification, not only must the `org.apache.camel.quarkus:camel-quarkus-bean` dependency be added, but the bean itself must be annotated with `@RegisterForReflection`. + +When using the `classpath` resource locator with native code, the path to the OpenAPI specification must be specified in the `quarkus.native.resources.includes` property of the `application.properties` file. For example: + +[source] +---- +quarkus.native.resources.includes=openapi.json +---- \ No newline at end of file diff --git a/integration-tests/rest-openapi/pom.xml b/integration-tests/rest-openapi/pom.xml index c27037c57a..0d264f8fd9 100644 --- a/integration-tests/rest-openapi/pom.xml +++ b/integration-tests/rest-openapi/pom.xml @@ -37,7 +37,15 @@ </dependency> <dependency> <groupId>org.apache.camel.quarkus</groupId> - <artifactId>camel-quarkus-netty-http</artifactId> + <artifactId>camel-quarkus-bean</artifactId> + </dependency> + <dependency> + <groupId>org.apache.camel.quarkus</groupId> + <artifactId>camel-quarkus-file</artifactId> + </dependency> + <dependency> + <groupId>org.apache.camel.quarkus</groupId> + <artifactId>camel-quarkus-http</artifactId> </dependency> <dependency> <groupId>org.apache.camel.quarkus</groupId> @@ -107,6 +115,19 @@ </activation> <dependencies> <!-- The following dependencies guarantee that this module is built after them. You can update them by running `mvn process-resources -Pformat -N` from the source tree root directory --> + <dependency> + <groupId>org.apache.camel.quarkus</groupId> + <artifactId>camel-quarkus-bean-deployment</artifactId> + <version>${project.version}</version> + <type>pom</type> + <scope>test</scope> + <exclusions> + <exclusion> + <groupId>*</groupId> + <artifactId>*</artifactId> + </exclusion> + </exclusions> + </dependency> <dependency> <groupId>org.apache.camel.quarkus</groupId> <artifactId>camel-quarkus-direct-deployment</artifactId> @@ -122,7 +143,20 @@ </dependency> <dependency> <groupId>org.apache.camel.quarkus</groupId> - <artifactId>camel-quarkus-netty-http-deployment</artifactId> + <artifactId>camel-quarkus-file-deployment</artifactId> + <version>${project.version}</version> + <type>pom</type> + <scope>test</scope> + <exclusions> + <exclusion> + <groupId>*</groupId> + <artifactId>*</artifactId> + </exclusion> + </exclusions> + </dependency> + <dependency> + <groupId>org.apache.camel.quarkus</groupId> + <artifactId>camel-quarkus-http-deployment</artifactId> <version>${project.version}</version> <type>pom</type> <scope>test</scope> diff --git a/integration-tests/rest-openapi/src/main/java/org/apache/camel/quarkus/component/rest/openapi/it/RestOpenApiRoutes.java b/integration-tests/rest-openapi/src/main/java/org/apache/camel/quarkus/component/rest/openapi/it/RestOpenApiBean.java similarity index 60% copy from integration-tests/rest-openapi/src/main/java/org/apache/camel/quarkus/component/rest/openapi/it/RestOpenApiRoutes.java copy to integration-tests/rest-openapi/src/main/java/org/apache/camel/quarkus/component/rest/openapi/it/RestOpenApiBean.java index b364370a7e..9686dfa25c 100644 --- a/integration-tests/rest-openapi/src/main/java/org/apache/camel/quarkus/component/rest/openapi/it/RestOpenApiRoutes.java +++ b/integration-tests/rest-openapi/src/main/java/org/apache/camel/quarkus/component/rest/openapi/it/RestOpenApiBean.java @@ -16,13 +16,22 @@ */ package org.apache.camel.quarkus.component.rest.openapi.it; -import org.apache.camel.builder.RouteBuilder; +import java.io.IOException; +import java.io.InputStream; +import java.nio.charset.StandardCharsets; -public class RestOpenApiRoutes extends RouteBuilder { +import javax.enterprise.context.ApplicationScoped; +import javax.inject.Named; - @Override - public void configure() throws Exception { - from("direct:start") - .toD("rest-openapi:#list?specificationUri=RAW(http://localhost:${header.test-port}/q/openapi?format=JSON)"); +import io.quarkus.runtime.annotations.RegisterForReflection; + +@ApplicationScoped +@Named("openapi") +@RegisterForReflection +public class RestOpenApiBean { + public String getOpenApiJson() throws IOException { + try (InputStream is = getClass().getClassLoader().getResourceAsStream("openapi.json")) { + return new String(is.readAllBytes(), StandardCharsets.UTF_8); + } } } diff --git a/integration-tests/rest-openapi/src/main/java/org/apache/camel/quarkus/component/rest/openapi/it/RestOpenApiRoutes.java b/integration-tests/rest-openapi/src/main/java/org/apache/camel/quarkus/component/rest/openapi/it/RestOpenApiRoutes.java index b364370a7e..cd00434559 100644 --- a/integration-tests/rest-openapi/src/main/java/org/apache/camel/quarkus/component/rest/openapi/it/RestOpenApiRoutes.java +++ b/integration-tests/rest-openapi/src/main/java/org/apache/camel/quarkus/component/rest/openapi/it/RestOpenApiRoutes.java @@ -22,7 +22,20 @@ public class RestOpenApiRoutes extends RouteBuilder { @Override public void configure() throws Exception { - from("direct:start") + + from("direct:start-web-json") .toD("rest-openapi:#list?specificationUri=RAW(http://localhost:${header.test-port}/q/openapi?format=JSON)"); + + from("direct:start-web-yaml") + .toD("rest-openapi:#list?specificationUri=RAW(http://localhost:${header.test-port}/q/openapi?format=YAML)"); + + from("direct:start-file") + .toD("rest-openapi:#list?specificationUri=file:target/openapi.json&host=RAW(http://localhost:${header.test-port})"); + + from("direct:start-bean") + .toD("rest-openapi:#list?specificationUri=bean:openapi.getOpenApiJson&host=RAW(http://localhost:${header.test-port})"); + + from("direct:start-classpath") + .toD("rest-openapi:#list?specificationUri=classpath:openapi.json&host=RAW(http://localhost:${header.test-port})"); } } diff --git a/integration-tests/rest-openapi/src/main/java/org/apache/camel/quarkus/component/rest/openapi/it/RestOpenapiResource.java b/integration-tests/rest-openapi/src/main/java/org/apache/camel/quarkus/component/rest/openapi/it/RestOpenapiResource.java index ad7d3484ff..8bdea0a62f 100644 --- a/integration-tests/rest-openapi/src/main/java/org/apache/camel/quarkus/component/rest/openapi/it/RestOpenapiResource.java +++ b/integration-tests/rest-openapi/src/main/java/org/apache/camel/quarkus/component/rest/openapi/it/RestOpenapiResource.java @@ -16,6 +16,7 @@ */ package org.apache.camel.quarkus.component.rest.openapi.it; +import javax.enterprise.context.ApplicationScoped; import javax.inject.Inject; import javax.ws.rs.GET; import javax.ws.rs.Path; @@ -27,15 +28,50 @@ import javax.ws.rs.core.Response; import org.apache.camel.ProducerTemplate; @Path("/rest-openapi") +@ApplicationScoped public class RestOpenapiResource { @Inject ProducerTemplate producerTemplate; - @Path("/fruits/list") + @Path("/fruits/list/json") @Produces(MediaType.APPLICATION_JSON) @GET public Response invokeListFruitsOperation(@QueryParam("port") int port) { - String response = producerTemplate.requestBodyAndHeader("direct:start", null, "test-port", port, String.class); + return invokeListFruitsOperation("start-web-json", port); + } + + @Path("/fruits/list/yaml") + @Produces(MediaType.APPLICATION_JSON) + @GET + public Response invokeListFruitsOperationYaml(@QueryParam("port") int port) { + return invokeListFruitsOperation("start-web-yaml", port); + } + + @Path("/fruits/list/file") + @Produces(MediaType.APPLICATION_JSON) + @GET + public Response invokeListFruitsOperationFile(@QueryParam("port") int port) { + return invokeListFruitsOperation("start-file", port); + } + + @Path("/fruits/list/bean") + @Produces(MediaType.APPLICATION_JSON) + @GET + public Response invokeListFruitsOperationBean(@QueryParam("port") int port) { + return invokeListFruitsOperation("start-bean", port); + } + + @Path("/fruits/list/classpath") + @Produces(MediaType.APPLICATION_JSON) + @GET + public Response invokeListFruitsOperationClasspath(@QueryParam("port") int port) { + return invokeListFruitsOperation("start-classpath", port); + } + + private Response invokeListFruitsOperation(String endpointName, int port) { + String response = producerTemplate.requestBodyAndHeader("direct:" + endpointName, null, "test-port", port, + String.class); return Response.ok().entity(response).build(); } + } diff --git a/integration-tests/rest-openapi/src/main/resources/application.properties b/integration-tests/rest-openapi/src/main/resources/application.properties new file mode 100644 index 0000000000..ab812d136e --- /dev/null +++ b/integration-tests/rest-openapi/src/main/resources/application.properties @@ -0,0 +1,17 @@ +## --------------------------------------------------------------------------- +## Licensed to the Apache Software Foundation (ASF) under one or more +## contributor license agreements. See the NOTICE file distributed with +## this work for additional information regarding copyright ownership. +## The ASF licenses this file to You 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. +## --------------------------------------------------------------------------- +quarkus.native.resources.includes=openapi.json \ No newline at end of file diff --git a/integration-tests/rest-openapi/src/main/resources/openapi.json b/integration-tests/rest-openapi/src/main/resources/openapi.json new file mode 100644 index 0000000000..36d2617e57 --- /dev/null +++ b/integration-tests/rest-openapi/src/main/resources/openapi.json @@ -0,0 +1,100 @@ +{ + "openapi" : "3.0.3", + "info" : { + "title" : "camel-quarkus-integration-test-rest-openapi API", + "version" : "2.13.0-SNAPSHOT" + }, + "paths" : { + "/fruits" : { + "get" : { + "tags" : [ "Fruit Resource" ], + "operationId" : "list", + "responses" : { + "200" : { + "description" : "OK", + "content" : { + "application/json" : { + "schema" : { + "uniqueItems" : true, + "type" : "array", + "items" : { + "$ref" : "#/components/schemas/Fruit" + } + } + } + } + } + } + } + }, + "/rest-openapi/fruits/list" : { + "get" : { + "tags" : [ "Rest Openapi Resource" ], + "parameters" : [ { + "name" : "port", + "in" : "query", + "schema" : { + "format" : "int32", + "type" : "integer" + } + } ], + "responses" : { + "200" : { + "description" : "OK" + } + } + } + }, + "/rest-openapi/fruits/list/file" : { + "get" : { + "tags" : [ "Rest Openapi Resource" ], + "parameters" : [ { + "name" : "port", + "in" : "query", + "schema" : { + "format" : "int32", + "type" : "integer" + } + } ], + "responses" : { + "200" : { + "description" : "OK" + } + } + } + }, + "/rest-openapi/fruits/list/yaml" : { + "get" : { + "tags" : [ "Rest Openapi Resource" ], + "parameters" : [ { + "name" : "port", + "in" : "query", + "schema" : { + "format" : "int32", + "type" : "integer" + } + } ], + "responses" : { + "200" : { + "description" : "OK" + } + } + } + } + }, + "components" : { + "schemas" : { + "Fruit" : { + "type" : "object", + "properties" : { + "name" : { + "type" : "string" + }, + "description" : { + "type" : "string" + } + } + } + } + } +} \ No newline at end of file diff --git a/integration-tests/rest-openapi/src/test/java/org/apache/camel/quarkus/component/rest/openapi/it/RestOpenapiTest.java b/integration-tests/rest-openapi/src/test/java/org/apache/camel/quarkus/component/rest/openapi/it/RestOpenapiTest.java index 138dfd9e4b..62b41cacdc 100644 --- a/integration-tests/rest-openapi/src/test/java/org/apache/camel/quarkus/component/rest/openapi/it/RestOpenapiTest.java +++ b/integration-tests/rest-openapi/src/test/java/org/apache/camel/quarkus/component/rest/openapi/it/RestOpenapiTest.java @@ -16,9 +16,16 @@ */ package org.apache.camel.quarkus.component.rest.openapi.it; +import java.io.File; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Paths; + import io.quarkus.test.junit.QuarkusTest; import io.restassured.RestAssured; import io.restassured.http.ContentType; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; import static org.hamcrest.Matchers.containsInAnyOrder; @@ -26,11 +33,52 @@ import static org.hamcrest.Matchers.containsInAnyOrder; @QuarkusTest class RestOpenapiTest { + private static final String OUTPUT_DIRECTORY = "target"; + private static final String OPENAPI_FILE = "openapi.json"; + + @BeforeAll + public static void createOpenApiJsonFile() throws Exception { + RestOpenApiBean bean = new RestOpenApiBean(); + String openApiContents = bean.getOpenApiJson(); + Files.createDirectories(Paths.get(OUTPUT_DIRECTORY)); + Files.writeString(Paths.get(OUTPUT_DIRECTORY, OPENAPI_FILE), openApiContents, StandardCharsets.UTF_8); + } + + @AfterAll + public static void deleteOpenApiJsonFile() { + File openApiFile = new File(OUTPUT_DIRECTORY, OPENAPI_FILE); + openApiFile.delete(); + } + @Test public void testInvokeApiEndpoint() { + invokeApiEndpoint("/rest-openapi/fruits/list/json"); + } + + @Test + public void testInvokeYamlApiEndpoint() { + invokeApiEndpoint("/rest-openapi/fruits/list/yaml"); + } + + @Test + public void testInvokeFileApiEndpoint() { + invokeApiEndpoint("/rest-openapi/fruits/list/file"); + } + + @Test + public void testInvokeBeanApiEndpoint() { + invokeApiEndpoint("/rest-openapi/fruits/list/bean"); + } + + @Test + public void testInvokeClasspathApiEndpoint() { + invokeApiEndpoint("/rest-openapi/fruits/list/classpath"); + } + + private void invokeApiEndpoint(String path) { RestAssured.given() .queryParam("port", RestAssured.port) - .get("/rest-openapi/fruits/list") + .get(path) .then() .contentType(ContentType.JSON) .statusCode(200)