diff --git a/examples/microprofile/openapi/basic/README.md b/examples/microprofile/openapi/basic/README.md new file mode 100644 index 000000000..bcdf6e213 --- /dev/null +++ b/examples/microprofile/openapi/basic/README.md @@ -0,0 +1,33 @@ +# Helidon MP OpenAPI Example + +This example shows a simple greeting application, similar to the one from the +Helidon MP QuickStart, enhanced with OpenAPI support. + +## Build and run + +```shell +mvn package +java -jar target/helidon-examples-microprofile-openapi-basic.jar +``` + +Try the endpoints: + +```shell +curl -X GET http://localhost:8080/greet +#Output: {"message":"Hello World!"} + +curl -X GET http://localhost:8080/greet/Joe +#Output: {"message":"Hello Joe!"} + +curl -X PUT -H "Content-Type: application/json" -d '{"message" : "Hola"}' http://localhost:8080/greet/greeting + +curl -X GET http://localhost:8080/greet/Jose +#Output: {"message":"Hola Jose!"} + +curl -X GET http://localhost:8080/openapi +#Output: [lengthy OpenAPI document] +``` +The output describes not only then endpoints from `GreetResource` but +also one contributed by the `SimpleAPIModelReader`. + + diff --git a/examples/microprofile/openapi/basic/pom.xml b/examples/microprofile/openapi/basic/pom.xml new file mode 100644 index 000000000..1fe420dd4 --- /dev/null +++ b/examples/microprofile/openapi/basic/pom.xml @@ -0,0 +1,99 @@ + + + + + 4.0.0 + + io.helidon.applications + helidon-mp + 4.2.0-SNAPSHOT + + + io.helidon.examples.microprofile + helidon-examples-microprofile-openapi-basic + 1.0.0-SNAPSHOT + Helidon Examples Microprofile OpenAPI Basic + + + + io.helidon.microprofile.bundles + helidon-microprofile-core + + + io.helidon.microprofile.openapi + helidon-microprofile-openapi + + + io.helidon.logging + helidon-logging-jul + runtime + + + org.glassfish.jersey.media + jersey-media-json-binding + runtime + + + io.smallrye + jandex + runtime + true + + + org.junit.jupiter + junit-jupiter-api + test + + + org.hamcrest + hamcrest-all + test + + + io.helidon.microprofile.testing + helidon-microprofile-testing-junit5 + test + + + + + + + org.apache.maven.plugins + maven-dependency-plugin + + + copy-libs + + + + + io.smallrye + jandex-maven-plugin + + + make-index + + + + + + diff --git a/examples/microprofile/openapi/src/main/java/io/helidon/microprofile/examples/openapi/GreetResource.java b/examples/microprofile/openapi/basic/src/main/java/io/helidon/microprofile/examples/openapi/basic/GreetResource.java similarity index 97% rename from examples/microprofile/openapi/src/main/java/io/helidon/microprofile/examples/openapi/GreetResource.java rename to examples/microprofile/openapi/basic/src/main/java/io/helidon/microprofile/examples/openapi/basic/GreetResource.java index f40c6fd6e..1c27a0f5d 100644 --- a/examples/microprofile/openapi/src/main/java/io/helidon/microprofile/examples/openapi/GreetResource.java +++ b/examples/microprofile/openapi/basic/src/main/java/io/helidon/microprofile/examples/openapi/basic/GreetResource.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package io.helidon.microprofile.examples.openapi; +package io.helidon.microprofile.examples.openapi.basic; import jakarta.enterprise.context.RequestScoped; import jakarta.inject.Inject; @@ -50,7 +50,7 @@ * * Note that the output will include not only the annotated endpoints from this * class but also an endpoint added by the - * {@link io.helidon.microprofile.examples.openapi.internal.SimpleAPIModelReader}. + * {@link io.helidon.microprofile.examples.openapi.basic.internal.SimpleAPIModelReader}. * * The message is returned as a JSON object. */ diff --git a/examples/microprofile/openapi/src/main/java/io/helidon/microprofile/examples/openapi/GreetingMessage.java b/examples/microprofile/openapi/basic/src/main/java/io/helidon/microprofile/examples/openapi/basic/GreetingMessage.java similarity index 96% rename from examples/microprofile/openapi/src/main/java/io/helidon/microprofile/examples/openapi/GreetingMessage.java rename to examples/microprofile/openapi/basic/src/main/java/io/helidon/microprofile/examples/openapi/basic/GreetingMessage.java index 752e9b132..a3b099697 100644 --- a/examples/microprofile/openapi/src/main/java/io/helidon/microprofile/examples/openapi/GreetingMessage.java +++ b/examples/microprofile/openapi/basic/src/main/java/io/helidon/microprofile/examples/openapi/basic/GreetingMessage.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.helidon.microprofile.examples.openapi; +package io.helidon.microprofile.examples.openapi.basic; /** * POJO defining the greeting message content. diff --git a/examples/microprofile/openapi/src/main/java/io/helidon/microprofile/examples/openapi/GreetingProvider.java b/examples/microprofile/openapi/basic/src/main/java/io/helidon/microprofile/examples/openapi/basic/GreetingProvider.java similarity index 96% rename from examples/microprofile/openapi/src/main/java/io/helidon/microprofile/examples/openapi/GreetingProvider.java rename to examples/microprofile/openapi/basic/src/main/java/io/helidon/microprofile/examples/openapi/basic/GreetingProvider.java index 515214ac6..c06658227 100644 --- a/examples/microprofile/openapi/src/main/java/io/helidon/microprofile/examples/openapi/GreetingProvider.java +++ b/examples/microprofile/openapi/basic/src/main/java/io/helidon/microprofile/examples/openapi/basic/GreetingProvider.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.helidon.microprofile.examples.openapi; +package io.helidon.microprofile.examples.openapi.basic; import java.util.concurrent.atomic.AtomicReference; diff --git a/examples/microprofile/openapi/src/main/java/io/helidon/microprofile/examples/openapi/internal/SimpleAPIFilter.java b/examples/microprofile/openapi/basic/src/main/java/io/helidon/microprofile/examples/openapi/basic/internal/SimpleAPIFilter.java similarity index 95% rename from examples/microprofile/openapi/src/main/java/io/helidon/microprofile/examples/openapi/internal/SimpleAPIFilter.java rename to examples/microprofile/openapi/basic/src/main/java/io/helidon/microprofile/examples/openapi/basic/internal/SimpleAPIFilter.java index 60e872b80..d4316ff39 100644 --- a/examples/microprofile/openapi/src/main/java/io/helidon/microprofile/examples/openapi/internal/SimpleAPIFilter.java +++ b/examples/microprofile/openapi/basic/src/main/java/io/helidon/microprofile/examples/openapi/basic/internal/SimpleAPIFilter.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.helidon.microprofile.examples.openapi.internal; +package io.helidon.microprofile.examples.openapi.basic.internal; import java.util.Map; diff --git a/examples/microprofile/openapi/src/main/java/io/helidon/microprofile/examples/openapi/internal/SimpleAPIModelReader.java b/examples/microprofile/openapi/basic/src/main/java/io/helidon/microprofile/examples/openapi/basic/internal/SimpleAPIModelReader.java similarity index 97% rename from examples/microprofile/openapi/src/main/java/io/helidon/microprofile/examples/openapi/internal/SimpleAPIModelReader.java rename to examples/microprofile/openapi/basic/src/main/java/io/helidon/microprofile/examples/openapi/basic/internal/SimpleAPIModelReader.java index 6d60bfcd8..6eecf9b1b 100644 --- a/examples/microprofile/openapi/src/main/java/io/helidon/microprofile/examples/openapi/internal/SimpleAPIModelReader.java +++ b/examples/microprofile/openapi/basic/src/main/java/io/helidon/microprofile/examples/openapi/basic/internal/SimpleAPIModelReader.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.helidon.microprofile.examples.openapi.internal; +package io.helidon.microprofile.examples.openapi.basic.internal; import org.eclipse.microprofile.openapi.OASFactory; import org.eclipse.microprofile.openapi.OASModelReader; diff --git a/examples/microprofile/openapi/src/main/java/io/helidon/microprofile/examples/openapi/internal/package-info.java b/examples/microprofile/openapi/basic/src/main/java/io/helidon/microprofile/examples/openapi/basic/internal/package-info.java similarity index 91% rename from examples/microprofile/openapi/src/main/java/io/helidon/microprofile/examples/openapi/internal/package-info.java rename to examples/microprofile/openapi/basic/src/main/java/io/helidon/microprofile/examples/openapi/basic/internal/package-info.java index e794f83fc..3104cd77b 100644 --- a/examples/microprofile/openapi/src/main/java/io/helidon/microprofile/examples/openapi/internal/package-info.java +++ b/examples/microprofile/openapi/basic/src/main/java/io/helidon/microprofile/examples/openapi/basic/internal/package-info.java @@ -17,4 +17,4 @@ /** * Internal classes supporting Helidon MP OpenAPI. */ -package io.helidon.microprofile.examples.openapi.internal; +package io.helidon.microprofile.examples.openapi.basic.internal; diff --git a/examples/microprofile/openapi/src/main/java/io/helidon/microprofile/examples/openapi/package-info.java b/examples/microprofile/openapi/basic/src/main/java/io/helidon/microprofile/examples/openapi/basic/package-info.java similarity index 92% rename from examples/microprofile/openapi/src/main/java/io/helidon/microprofile/examples/openapi/package-info.java rename to examples/microprofile/openapi/basic/src/main/java/io/helidon/microprofile/examples/openapi/basic/package-info.java index 2d75af1aa..f3c2fe887 100644 --- a/examples/microprofile/openapi/src/main/java/io/helidon/microprofile/examples/openapi/package-info.java +++ b/examples/microprofile/openapi/basic/src/main/java/io/helidon/microprofile/examples/openapi/basic/package-info.java @@ -17,4 +17,4 @@ /** * Helidon MicroProfile OpenAPI example. */ -package io.helidon.microprofile.examples.openapi; +package io.helidon.microprofile.examples.openapi.basic; diff --git a/examples/microprofile/openapi/src/main/resources/META-INF/beans.xml b/examples/microprofile/openapi/basic/src/main/resources/META-INF/beans.xml similarity index 100% rename from examples/microprofile/openapi/src/main/resources/META-INF/beans.xml rename to examples/microprofile/openapi/basic/src/main/resources/META-INF/beans.xml diff --git a/examples/microprofile/openapi/src/main/resources/META-INF/microprofile-config.properties b/examples/microprofile/openapi/basic/src/main/resources/META-INF/microprofile-config.properties similarity index 86% rename from examples/microprofile/openapi/src/main/resources/META-INF/microprofile-config.properties rename to examples/microprofile/openapi/basic/src/main/resources/META-INF/microprofile-config.properties index 393a125ef..8517ada2b 100644 --- a/examples/microprofile/openapi/src/main/resources/META-INF/microprofile-config.properties +++ b/examples/microprofile/openapi/basic/src/main/resources/META-INF/microprofile-config.properties @@ -21,5 +21,5 @@ app.greeting=Hello server.port=8080 server.host=0.0.0.0 -mp.openapi.filter=io.helidon.microprofile.examples.openapi.internal.SimpleAPIFilter -mp.openapi.model.reader=io.helidon.microprofile.examples.openapi.internal.SimpleAPIModelReader +mp.openapi.filter=io.helidon.microprofile.examples.openapi.basic.internal.SimpleAPIFilter +mp.openapi.model.reader=io.helidon.microprofile.examples.openapi.basic.internal.SimpleAPIModelReader diff --git a/examples/microprofile/openapi/src/main/resources/logging.properties b/examples/microprofile/openapi/basic/src/main/resources/logging.properties similarity index 100% rename from examples/microprofile/openapi/src/main/resources/logging.properties rename to examples/microprofile/openapi/basic/src/main/resources/logging.properties diff --git a/examples/microprofile/openapi/src/test/java/io/helidon/microprofile/examples/openapi/MainTest.java b/examples/microprofile/openapi/basic/src/test/java/io/helidon/microprofile/examples/openapi/basic/MainTest.java similarity index 95% rename from examples/microprofile/openapi/src/test/java/io/helidon/microprofile/examples/openapi/MainTest.java rename to examples/microprofile/openapi/basic/src/test/java/io/helidon/microprofile/examples/openapi/basic/MainTest.java index 402f4572b..1a704b0d0 100644 --- a/examples/microprofile/openapi/src/test/java/io/helidon/microprofile/examples/openapi/MainTest.java +++ b/examples/microprofile/openapi/basic/src/test/java/io/helidon/microprofile/examples/openapi/basic/MainTest.java @@ -14,9 +14,9 @@ * limitations under the License. */ -package io.helidon.microprofile.examples.openapi; +package io.helidon.microprofile.examples.openapi.basic; -import io.helidon.microprofile.examples.openapi.internal.SimpleAPIModelReader; +import io.helidon.microprofile.examples.openapi.basic.internal.SimpleAPIModelReader; import io.helidon.microprofile.testing.junit5.HelidonTest; import jakarta.inject.Inject; diff --git a/examples/microprofile/openapi/src/test/resources/META-INF/microprofile-config.properties b/examples/microprofile/openapi/basic/src/test/resources/META-INF/microprofile-config.properties similarity index 100% rename from examples/microprofile/openapi/src/test/resources/META-INF/microprofile-config.properties rename to examples/microprofile/openapi/basic/src/test/resources/META-INF/microprofile-config.properties diff --git a/examples/microprofile/openapi/expanded-jandex/README.md b/examples/microprofile/openapi/expanded-jandex/README.md new file mode 100644 index 000000000..dc10ffc97 --- /dev/null +++ b/examples/microprofile/openapi/expanded-jandex/README.md @@ -0,0 +1,74 @@ +# Helidon MP OpenAPI Expanded Jandex Indexing Example + +This example shows a simple greeting application, similar to the basic OpenAPI MP example, but with proper handling of types from _outside_ this project that are used in resource method signatures. + +### Why might I need expanded Jandex handling? +Many Helidon MP applications, including those created by the Helidon command line and the starter, run the Jandex plug-in to create an index file for the types defined in the project. +Helidon's OpenAPI support leverages much of SmallRye's OpenAPI implementation and SmallRye scans the resource methods in the application to generate an OpenAPI model. This scan uses the Jandex index file directly to get information about the types used in resource methods, and SmallRye uses this information in preparing the OpenAPI document. + +If a resource method's signature uses a type _outside_ the current project SmallRye's scan cannot usually find the type information because the Jandex index created by the typical project describes only the types defined in the current project, not types in any dependencies. + +### How does this affect my application? +In such cases, SmallRye logs warning messages about the types it cannot find. This can clutter the application output. + +More importantly, the resulting OpenAPI model is less robust. When SmallRye cannot find a type it has no choice but to model that type as an opaque `Object`. The resulting OpenAPI model and document are less useful than they could be. + +Note that if the dependency contains _its own_ Jandex index for its own types then SmallRye can find information about those types. + +### What does this example do? +This example shows how to expand the Jandex index built by your project to include selected types from _outside_ the project. +There are two key differences from the basic OpenAPI example: + +1. The new resource method `mediaType`added to `GreetingResource` returns a `MediaType` from Jarkarta RESTful Web Wervices, a type from outside this project. +2. The `pom.xml` configures its invocation of the Jandex plug-in to include that type in the generated Jandex index. + +The example `pom.xml` adds a single type from a single dependency to the index. If you need to for your application add more dependencies and more include entries. + +## Build and run + +```shell +mvn package +java -jar target/helidon-examples-microprofile-openapi-expanded-jandex.jar +``` + +Try the endpoints. These are the same actions supported by the basic OpenAPI example: + +```shell +curl -X GET http://localhost:8080/greet +#Output: {"message":"Hello World!"} + +curl -X GET http://localhost:8080/greet/Joe +#Output: {"message":"Hello Joe!"} + +curl -X PUT -H "Content-Type: application/json" -d '{"message" : "Hola"}' http://localhost:8080/greet/greeting + +curl -X GET http://localhost:8080/greet/Jose +#Output: {"message":"Hola Jose!"} + +curl -X GET http://localhost:8080/openapi +#Output: [lengthy OpenAPI document] +``` +After running the last command notice that the OpenAPI document's `components/schemas` section contains a declaration for `MediaType` that includes the `MediaType` properties (`type`, `subtype`, etc.). Further, the document's entry for `paths/greet/mediatype:get` declares the response content by referring to that exact `#/components/schemas/MediaType` entry. + +## Building and running without expanded Jandex processing +You can simulate the build without the expanded Jandex processing to see the warning SmallRye logs during startup and to see the difference in the generated OpenAPI document. +When you build the project specify the `normal-jandex` Maven profile and skip the unit tests. + +```shell +mvn clean package -Pnormal-jandex -DskipTests +java -jar target/helidon-examples-microprofile-openapi-expanded-jandex.jar +``` +As the app starts notice a message like the following in the app output: +```list +WARN io.smallrye.openapi.runtime.scanner Thread[#1,main,5,main]: SROAP04005: Could not find schema class in index: jakarta.ws.rs.core.MediaType +``` + +Retrieve the OpenAPI document: +```shell +curl -X GET http://localhost:8080/openapi +``` +Notice two things about the output: +1. The `components/schemas` section contains no entry for `MediaType`. That's expected given that SmallRye could not find the type information for it. +2. The response content for `paths/greet/mediatype:get` is simply `object`. + + While it is true that the response is an `Object` this version of the OpenAPI document for your app is less useful than the earlier one because of the missing type information for `MediaType`. \ No newline at end of file diff --git a/examples/microprofile/openapi/expanded-jandex/pom.xml b/examples/microprofile/openapi/expanded-jandex/pom.xml new file mode 100644 index 000000000..92a445810 --- /dev/null +++ b/examples/microprofile/openapi/expanded-jandex/pom.xml @@ -0,0 +1,139 @@ + + + + + 4.0.0 + + io.helidon.applications + helidon-mp + 4.2.0-SNAPSHOT + + + io.helidon.examples.microprofile + helidon-examples-microprofile-openapi-expanded-jandex + 1.0.0-SNAPSHOT + Helidon Examples Microprofile OpenAPI with expanded Jandex handling + + + + io.helidon.microprofile.bundles + helidon-microprofile-core + + + io.helidon.microprofile.openapi + helidon-microprofile-openapi + + + io.helidon.logging + helidon-logging-jul + runtime + + + org.glassfish.jersey.media + jersey-media-json-binding + runtime + + + io.smallrye + jandex + runtime + true + + + org.junit.jupiter + junit-jupiter-api + test + + + org.hamcrest + hamcrest-all + test + + + io.helidon.microprofile.testing + helidon-microprofile-testing-junit5 + test + + + + + + + org.apache.maven.plugins + maven-dependency-plugin + + + copy-libs + + + + + io.smallrye + jandex-maven-plugin + + + make-index + + + + + jakarta.ws.rs + jakarta.ws.rs-api + + + **/MediaType.class + + + + + + + + + + + + + + normal-jandex + + + + io.smallrye + jandex-maven-plugin + + + make-index + + + + + + + + + diff --git a/examples/microprofile/openapi/expanded-jandex/src/main/java/io/helidon/microprofile/examples/openapi/expandedJandex/GreetResource.java b/examples/microprofile/openapi/expanded-jandex/src/main/java/io/helidon/microprofile/examples/openapi/expandedJandex/GreetResource.java new file mode 100644 index 000000000..163aa583a --- /dev/null +++ b/examples/microprofile/openapi/expanded-jandex/src/main/java/io/helidon/microprofile/examples/openapi/expandedJandex/GreetResource.java @@ -0,0 +1,159 @@ +/* + * Copyright (c) 2024 Oracle and/or its affiliates. + * + * 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. + */ + +package io.helidon.microprofile.examples.openapi.expandedJandex; + +import jakarta.enterprise.context.RequestScoped; +import jakarta.inject.Inject; +import jakarta.ws.rs.Consumes; +import jakarta.ws.rs.GET; +import jakarta.ws.rs.PUT; +import jakarta.ws.rs.Path; +import jakarta.ws.rs.PathParam; +import jakarta.ws.rs.Produces; +import jakarta.ws.rs.core.MediaType; +import jakarta.ws.rs.core.Response; +import org.eclipse.microprofile.openapi.annotations.Operation; +import org.eclipse.microprofile.openapi.annotations.media.Content; +import org.eclipse.microprofile.openapi.annotations.media.ExampleObject; +import org.eclipse.microprofile.openapi.annotations.media.Schema; +import org.eclipse.microprofile.openapi.annotations.parameters.RequestBody; +import org.eclipse.microprofile.openapi.annotations.responses.APIResponse; + +/** + * A simple JAX-RS resource with OpenAPI annotations 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 + *

+ * Get OpenAPI document for the endpoints + * curl -X GET http://localhost:8080/openapi + *

+ * Note that the output will include not only the annotated endpoints from this + * class but also an endpoint added by the + * {@link io.helidon.microprofile.examples.openapi.expanded.jandex.internal.SimpleAPIModelReader}. + *

+ * The message is returned as a JSON object. + */ +@Path("/greet") +@RequestScoped +public class GreetResource { + + /** + * The greeting message provider. + */ + private final GreetingProvider greetingProvider; + + /** + * Using constructor injection to get a configuration property. + * By default this gets the value from META-INF/microprofile-config + * + * @param greetingConfig the configured greeting message + */ + @Inject + public GreetResource(GreetingProvider greetingConfig) { + this.greetingProvider = greetingConfig; + } + + /** + * Return a worldly greeting message. + * + * @return {@link GreetingMessage} + */ + @GET + @Operation(summary = "Returns a generic greeting", + description = "Greets the user generically") + @APIResponse(description = "Simple JSON containing the greeting", + content = @Content(mediaType = "application/json", + schema = @Schema(implementation = GreetingMessage.class))) + @Produces(MediaType.APPLICATION_JSON) + public GreetingMessage getDefaultMessage() { + return createResponse("World"); + } + + /** + * Return a greeting message using the name that was provided. + * + * @param name the name to greet + * @return {@link GreetingMessage} + */ + @Path("/{name}") + @GET + @Operation(summary = "Returns a personalized greeting") + @APIResponse(description = "Simple JSON containing the greeting", + content = @Content(mediaType = "application/json", + schema = @Schema(implementation = GreetingMessage.class))) + @Produces(MediaType.APPLICATION_JSON) + public GreetingMessage getMessage(@PathParam("name") String name) { + return createResponse(name); + } + + /** + * Set the greeting to use in future messages. + * + * @param message JSON containing the new greeting + * @return {@link Response} + */ + @Path("/greeting") + @PUT + @Operation(summary = "Set the greeting prefix", + description = "Permits the client to set the prefix part of the greeting (\"Hello\")") + @RequestBody( + name = "greeting", + description = "Conveys the new greeting prefix to use in building greetings", + content = @Content( + mediaType = "application/json", + schema = @Schema(implementation = GreetingMessage.class), + examples = @ExampleObject( + name = "greeting", + summary = "Example greeting message to update", + value = "{\"greeting\": \"New greeting message\"}"))) + @Consumes(MediaType.APPLICATION_JSON) + @Produces(MediaType.APPLICATION_JSON) + public Response updateGreeting(GreetingMessage message) { + if (message.getMessage() == null) { + GreetingMessage entity = new GreetingMessage("No greeting provided"); + return Response.status(Response.Status.BAD_REQUEST).entity(entity).build(); + } + + greetingProvider.setMessage(message.getMessage()); + return Response.status(Response.Status.NO_CONTENT).build(); + } + + /** + * Simplistic method to return a type from outside this project. + * + * @return {@link jakarta.ws.rs.core.MediaType} + */ + @Path("/mediatype") + @GET + @Produces(MediaType.APPLICATION_JSON) + public MediaType mediatype() { + return MediaType.APPLICATION_JSON_TYPE; + } + + private GreetingMessage createResponse(String who) { + String msg = String.format("%s %s!", greetingProvider.getMessage(), who); + + return new GreetingMessage(msg); + } +} diff --git a/examples/microprofile/openapi/expanded-jandex/src/main/java/io/helidon/microprofile/examples/openapi/expandedJandex/GreetingMessage.java b/examples/microprofile/openapi/expanded-jandex/src/main/java/io/helidon/microprofile/examples/openapi/expandedJandex/GreetingMessage.java new file mode 100644 index 000000000..823bd3fb5 --- /dev/null +++ b/examples/microprofile/openapi/expanded-jandex/src/main/java/io/helidon/microprofile/examples/openapi/expandedJandex/GreetingMessage.java @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2024 Oracle and/or its affiliates. + * + * 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. + */ +package io.helidon.microprofile.examples.openapi.expandedJandex; + +/** + * POJO defining the greeting message content. + */ +@SuppressWarnings("unused") +public class GreetingMessage { + private String message; + + /** + * Create a new GreetingMessage instance. + */ + public GreetingMessage() { + } + + /** + * Create a new GreetingMessage instance. + * + * @param message message + */ + public GreetingMessage(String message) { + this.message = message; + } + + /** + * Gets the message value. + * + * @return message value + */ + public String getMessage() { + return message; + } + + /** + * Sets the message value. + * + * @param message message value to set + */ + public void setMessage(String message) { + this.message = message; + } +} diff --git a/examples/microprofile/openapi/expanded-jandex/src/main/java/io/helidon/microprofile/examples/openapi/expandedJandex/GreetingProvider.java b/examples/microprofile/openapi/expanded-jandex/src/main/java/io/helidon/microprofile/examples/openapi/expandedJandex/GreetingProvider.java new file mode 100644 index 000000000..86e2acba6 --- /dev/null +++ b/examples/microprofile/openapi/expanded-jandex/src/main/java/io/helidon/microprofile/examples/openapi/expandedJandex/GreetingProvider.java @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2024 Oracle and/or its affiliates. + * + * 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. + */ +package io.helidon.microprofile.examples.openapi.expandedJandex; + +import java.util.concurrent.atomic.AtomicReference; + +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.inject.Inject; +import org.eclipse.microprofile.config.inject.ConfigProperty; + +/** + * Provider for greeting message. + */ +@ApplicationScoped +public class GreetingProvider { + private final AtomicReference message = new AtomicReference<>(); + + /** + * Create a new greeting provider, reading the message from configuration. + * + * @param message greeting to use + */ + @Inject + public GreetingProvider(@ConfigProperty(name = "app.greeting") String message) { + this.message.set(message); + } + + String getMessage() { + return message.get(); + } + + void setMessage(String message) { + this.message.set(message); + } +} diff --git a/examples/microprofile/openapi/expanded-jandex/src/main/java/io/helidon/microprofile/examples/openapi/expandedJandex/package-info.java b/examples/microprofile/openapi/expanded-jandex/src/main/java/io/helidon/microprofile/examples/openapi/expandedJandex/package-info.java new file mode 100644 index 000000000..22d4277e1 --- /dev/null +++ b/examples/microprofile/openapi/expanded-jandex/src/main/java/io/helidon/microprofile/examples/openapi/expandedJandex/package-info.java @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2024 Oracle and/or its affiliates. + * + * 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. + */ + +/** + * Helidon MicroProfile OpenAPI example with expanded Jandex processing. + */ +package io.helidon.microprofile.examples.openapi.expandedJandex; diff --git a/examples/microprofile/openapi/expanded-jandex/src/main/resources/META-INF/beans.xml b/examples/microprofile/openapi/expanded-jandex/src/main/resources/META-INF/beans.xml new file mode 100644 index 000000000..52f89a20d --- /dev/null +++ b/examples/microprofile/openapi/expanded-jandex/src/main/resources/META-INF/beans.xml @@ -0,0 +1,25 @@ + + + + diff --git a/examples/microprofile/openapi/expanded-jandex/src/main/resources/META-INF/microprofile-config.properties b/examples/microprofile/openapi/expanded-jandex/src/main/resources/META-INF/microprofile-config.properties new file mode 100644 index 000000000..6546504fc --- /dev/null +++ b/examples/microprofile/openapi/expanded-jandex/src/main/resources/META-INF/microprofile-config.properties @@ -0,0 +1,22 @@ +# +# Copyright (c) 2024 Oracle and/or its affiliates. +# +# 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. +# + +# Application properties. This is the default greeting +app.greeting=Hello + +# Microprofile server properties +server.port=8080 +server.host=0.0.0.0 diff --git a/examples/microprofile/openapi/expanded-jandex/src/main/resources/logging.properties b/examples/microprofile/openapi/expanded-jandex/src/main/resources/logging.properties new file mode 100644 index 000000000..f7313283e --- /dev/null +++ b/examples/microprofile/openapi/expanded-jandex/src/main/resources/logging.properties @@ -0,0 +1,36 @@ +# +# Copyright (c) 2024 Oracle and/or its affiliates. +# +# 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. +# + +# Example Logging Configuration File +# For more information see $JAVA_HOME/jre/lib/logging.properties + +# Send messages to the console +handlers=io.helidon.logging.jul.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.microprofile.level=INFO +#io.helidon.common.level=INFO +#org.glassfish.jersey.level=INFO +#org.jboss.weld=INFO diff --git a/examples/microprofile/openapi/expanded-jandex/src/test/java/io/helidon/microprofile/examples/openapi/expandedJandex/MainTest.java b/examples/microprofile/openapi/expanded-jandex/src/test/java/io/helidon/microprofile/examples/openapi/expandedJandex/MainTest.java new file mode 100644 index 000000000..15f8369be --- /dev/null +++ b/examples/microprofile/openapi/expanded-jandex/src/test/java/io/helidon/microprofile/examples/openapi/expandedJandex/MainTest.java @@ -0,0 +1,107 @@ +/* + * Copyright (c) 2019, 2024 Oracle and/or its affiliates. + * + * 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. + */ + +package io.helidon.microprofile.examples.openapi.expandedJandex; + +import java.io.IOException; +import java.io.InputStream; + +import io.helidon.microprofile.testing.junit5.HelidonTest; + +import jakarta.inject.Inject; +import jakarta.json.Json; +import jakarta.json.JsonObject; +import jakarta.json.JsonPointer; +import jakarta.json.JsonString; +import jakarta.ws.rs.client.Entity; +import jakarta.ws.rs.client.WebTarget; +import jakarta.ws.rs.core.MediaType; +import jakarta.ws.rs.core.Response; +import org.jboss.jandex.ClassInfo; +import org.jboss.jandex.Index; +import org.jboss.jandex.IndexReader; +import org.junit.jupiter.api.Test; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.is; +import static org.hamcrest.Matchers.notNullValue; + +@HelidonTest +class MainTest { + + private final WebTarget target; + + @Inject + MainTest(WebTarget target) { + this.target = target; + } + + private static String escape(String path) { + return path.replace("/", "~1"); + } + + @Test + void testHelloWorld() { + GreetingMessage message = target.path("/greet") + .request() + .get(GreetingMessage.class); + assertThat("default message", message.getMessage(), + is("Hello World!")); + + message = target.path("/greet/Joe") + .request() + .get(GreetingMessage.class); + assertThat("hello Joe message", message.getMessage(), + is("Hello Joe!")); + + try (Response r = target.path("/greet/greeting") + .request() + .put(Entity.entity("{\"message\" : \"Hola\"}", MediaType.APPLICATION_JSON))) { + assertThat("PUT status code", r.getStatus(), is(204)); + } + + message = target.path("/greet/Jose") + .request() + .get(GreetingMessage.class); + assertThat("hola Jose message", message.getMessage(), + is("Hola Jose!")); + } + + @Test + public void testOpenAPI() { + JsonObject jsonObject = target.path("/openapi") + .request(MediaType.APPLICATION_JSON) + .get(JsonObject.class); + JsonObject paths = jsonObject.get("paths").asJsonObject(); + + JsonPointer jp = Json.createPointer("/" + escape("/greet") + "/get/summary"); + JsonString js = (JsonString) jp.getValue(paths); + assertThat("/greet GET summary did not match", js.getString(), is("Returns a generic greeting")); + } + + @Test + void checkJandexContentsForExternalType() { + Index indexFromMavenBuild; + try (InputStream is = getClass().getResource("/META-INF/jandex.idx").openStream()) { + IndexReader indexReader = new IndexReader(is); + indexFromMavenBuild = indexReader.read(); + } catch (IOException e) { + throw new RuntimeException(e); + } + ClassInfo mediaTypeClassInfo = indexFromMavenBuild.getClassByName(MediaType.class); + assertThat("MediaType index information from generated Jandex file", mediaTypeClassInfo, notNullValue()); + } +} diff --git a/examples/microprofile/openapi/expanded-jandex/src/test/resources/META-INF/microprofile-config.properties b/examples/microprofile/openapi/expanded-jandex/src/test/resources/META-INF/microprofile-config.properties new file mode 100644 index 000000000..0502dc34c --- /dev/null +++ b/examples/microprofile/openapi/expanded-jandex/src/test/resources/META-INF/microprofile-config.properties @@ -0,0 +1,22 @@ +# +# Copyright (c) 2019, 2024 Oracle and/or its affiliates. +# +# 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. +# + + +# Override configuration in main source branch, so we do not use 8080 port for tests +config_ordinal=1000 +# Microprofile server properties +server.port=-1 +server.host=0.0.0.0 diff --git a/examples/microprofile/openapi/pom.xml b/examples/microprofile/openapi/pom.xml index 60aceefd4..e929d26e0 100644 --- a/examples/microprofile/openapi/pom.xml +++ b/examples/microprofile/openapi/pom.xml @@ -22,78 +22,18 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 - io.helidon.applications - helidon-mp - 4.2.0-SNAPSHOT - + io.helidon.examples.microprofile + helidon-examples-microprofile-project + 1.0.0-SNAPSHOT - io.helidon.examples.microprofile + io.helidon.examples.microprofile.openapi helidon-examples-microprofile-openapi 1.0.0-SNAPSHOT Helidon Examples Microprofile OpenAPI + pom - - - io.helidon.microprofile.bundles - helidon-microprofile-core - - - io.helidon.microprofile.openapi - helidon-microprofile-openapi - - - io.helidon.logging - helidon-logging-jul - runtime - - - org.glassfish.jersey.media - jersey-media-json-binding - runtime - - - io.smallrye - jandex - runtime - true - - - org.junit.jupiter - junit-jupiter-api - test - - - org.hamcrest - hamcrest-all - test - - - io.helidon.microprofile.testing - helidon-microprofile-testing-junit5 - test - - - - - - - org.apache.maven.plugins - maven-dependency-plugin - - - copy-libs - - - - - io.smallrye - jandex-maven-plugin - - - make-index - - - - - + + basic + expanded-jandex +