Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

OpenAPI doc update: mostly SE but some refactoring of MP as well #4558

Merged
merged 2 commits into from
Jul 15, 2022
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ Optional configuration options:
|`servers` |string[] |{nbsp} |Sets servers.
|`servers.operation.*` |string[] |{nbsp} |Sets alternative servers to service the indicated operation (represented here by '*'). Repeat for multiple operations.
|`servers.path.*` |string[] |{nbsp} |Sets alternative servers to service all operations at the indicated path (represented here by '*'). Repeat for multiple paths.
|`static-file` |string |`META-INF/openapi.(json|yaml|yml)` |Sets the file system path of the static OpenAPI document file.
|`static-file` |string |`META-INF/openapi.*` |Sets the file system path of the static OpenAPI document file. Default types are `json`, `yaml`, and `yml`.
|`web-context` |string |`/openapi` |Sets the web context path for the OpenAPI endpoint.

|===
Expand Down
2 changes: 1 addition & 1 deletion docs/config/io_helidon_openapi_OpenAPISupport.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ Optional configuration options:
|key |type |default value |description

|`cors` |xref:{rootdir}/config/io_helidon_webserver_cors_CrossOriginConfig.adoc[CrossOriginConfig] |{nbsp} |Assigns the CORS settings for the OpenAPI endpoint.
|`static-file` |string |`META-INF/openapi.(json|yaml|yml)` |Sets the file system path of the static OpenAPI document file.
|`static-file` |string |`META-INF/openapi.*` |Sets the file system path of the static OpenAPI document file. Default types are `json`, `yaml`, and `yml`.
|`web-context` |string |`/openapi` |Sets the web context path for the OpenAPI endpoint.

|===
Expand Down
2 changes: 1 addition & 1 deletion docs/config/io_helidon_openapi_SEOpenAPISupport.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ Optional configuration options:
|`servers` |string[] |{nbsp} |Sets servers.
|`servers.operation.*` |string[] |{nbsp} |Sets alternative servers to service the indicated operation (represented here by '*'). Repeat for multiple operations.
|`servers.path.*` |string[] |{nbsp} |Sets alternative servers to service all operations at the indicated path (represented here by '*'). Repeat for multiple paths.
|`static-file` |string |`META-INF/openapi.(json|yaml|yml)` |Sets the file system path of the static OpenAPI document file.
|`static-file` |string |`META-INF/openapi.*` |Sets the file system path of the static OpenAPI document file. Default types are `json`, `yaml`, and `yml`.
|`web-context` |string |`/openapi` |Sets the web context path for the OpenAPI endpoint.

|===
Expand Down
11 changes: 8 additions & 3 deletions docs/includes/attributes.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -82,9 +82,10 @@ endif::[]

:microprofile-base-url: https://download.eclipse.org/microprofile

:microprofile-open-api-base-url: {microprofile-base-url}/microprofile-open-api-{version-lib-microprofile-metrics-api}
:microprofile-open-api-spec-url: {microprofile-open-api-base-url}/microprofile-openapi-spec-{version-lib-microprofile-metrics-api}.html
:microprofile-open-api-javadoc-url: {microprofile-open-api-base-url}/apidocs/org/eclipse/microprofile/openapi/
:microprofile-open-api-base-url: {microprofile-base-url}/microprofile-open-api-{version-lib-microprofile-openapi-api}
:microprofile-open-api-spec-url: {microprofile-open-api-base-url}/microprofile-openapi-spec-{version-lib-microprofile-openapi-api}.html
:microprofile-open-api-javadoc-base-url: {microprofile-open-api-base-url}/apidocs
:microprofile-open-api-javadoc-url: {microprofile-open-api-javadoc-base-url}/apidocs/org/eclipse/microprofile/openapi/

:microprofile-lra-base-url: {microprofile-base-url}/microprofile-lra-{version-lib-microprofile-lra-api}
:microprofile-lra-spec-url: {microprofile-lra-base-url}/microprofile-lra-spec-{version-lib-microprofile-lra-api}.html
Expand Down Expand Up @@ -190,6 +191,7 @@ endif::[]
:mp-cors-javadoc-base-url: {javadoc-base-url}/io.helidon.microprofile.cors
:mp-tyrus-javadoc-base-url: {javadoc-base-url}/io.helidon.microprofile.tyrus
:mp-restclient-javadoc-base-url: {javadoc-base-url}/io.helidon.microprofile.restclient
:openapi-javadoc-base-url: {javadoc-base-url}/io.helidon.openapi
:reactive-base-url: {javadoc-base-url}/io.helidon.common.reactive
:scheduling-javadoc-base-url: {javadoc-base-url}/io.helidon.microprofile.scheduling
:webclient-javadoc-base-url: {javadoc-base-url}/io.helidon.webclient
Expand All @@ -207,6 +209,9 @@ endif::[]
:jib-base-url: https://github.com/GoogleContainerTools/jib/blob/v{version-plugin-jib}-maven/jib-maven-plugin
:jedis-base-url: {javadoc-io-base-url}/redis.clients/jedis/{version-lib-jedis}/redis/clients
:kafka-client-base-url: https://kafka.apache.org/28/documentation.html
:openapi-version: 3.0.0
:openapi-spec-base-url: https://github.com/OAI/OpenAPI-Specification/blob/master/versions
:openapi-spec-url: {openapi-spec-base-url}/{openapi-version}.md

:oci-sdk-config-url: https://docs.oracle.com/en-us/iaas/Content/API/Concepts/sdkconfig.htm#SDK_and_CLI_Configuration_File
:oci-database-url: https://docs.oracle.com/en-us/iaas/Content/Database/home.htm
Expand Down
190 changes: 190 additions & 0 deletions docs/includes/openapi.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,155 @@

ifndef::rootdir[:rootdir: {docdir}/..]

// tag::overview[]
The link:{openapi-spec-url}[OpenAPI specification] defines a standard way to express the interface exposed by a REST service.

The link:{microprofile-open-api-spec-url}[MicroProfile OpenAPI spec] explains how MicroProfile embraces OpenAPI, adding annotations, configuration, and a service provider interface (SPI).

ifdef::mp-flavor[Helidon {flavor-uc} implements the MicroProfile OpenAPI specification.]
ifdef::se-flavor[OpenAPI support in Helidon {flavor-uc} draws its inspiration from MicroProfile OpenAPI but does not implement the spec because Helidon {flavor-uc} does not support annotations.]

The OpenAPI support in Helidon {flavor-uc} performs two main tasks:

* Build an in-memory model of the REST API your service implements.
* Expose the model in text format (typically yaml) via the `/openapi` endpoint.
tjquinno marked this conversation as resolved.
Show resolved Hide resolved

To construct the model, Helidon OpenAPI gathers information about the service API from whichever of these sources are present in the application:
tjquinno marked this conversation as resolved.
Show resolved Hide resolved

* a _model reader_
+
The SPI defines an interface you can implement in your application for programmatically providing part or all of the model;
* a static OpenAPI document file packaged as part of your service;
ifdef::mp-flavor[]
* OpenAPI annotations;
endif::[]
* a _filter_ class
+
The SPI defines an interface you can implement in your application which can mask parts of the model.


// end::overview[]

// tag::furnish-openapi-info[]

==== Furnish OpenAPI information about your endpoints
// It's a bit odd to intermix the SE and MP content in this common file this way.
// But I tried having a level 3 section in the SE file include a sequence of
// level 4 sections from here, and that led to errors with headers being out of sequence.
// With the entire level 3 section here and conditional text for SE and MP, AsciiDoctor is happy.
ifdef::se-flavor[]
OpenAPI support in Helidon SE largely follows the link:{microprofile-open-api-spec-url}[MicroProfile OpenAPI spec].
But because Helidon SE does not process annotations, your application supplies data for the OpenAPI model in the other ways listed earlier.
endif::[]

ifdef::mp-flavor[]
Helidon MP OpenAPI combines information from all of the following sources as it
builds its in-memory model of your application's API. It constructs the OpenAPI
document from this internal model. Your application can use one or more of these
techniques.

===== Annotate the endpoints in your app
You can add MicroProfile OpenAPI annotations to the endpoints in your source code.
These annotations allow the Helidon MP OpenAPI runtime to discover the endpoints
and information about them via CDI at app start-up.

Here is one of the endpoints, annotated for OpenAPI, from the example mentioned earlier:

[source,java]
----
@GET
@Operation(summary = "Returns a generic greeting", // <1>
description = "Greets the user generically")
@APIResponse(description = "Simple JSON containing the greeting", // <2>
content = @Content(mediaType = "application/json",
schema = @Schema(implementation = GreetingMessage.class)))
@Produces(MediaType.APPLICATION_JSON)
public JsonObject getDefaultMessage() {...}
----
<1> `@Operation` gives information about this endpoint.
<2> `@APIResponse` describes the HTTP response and declares its media type and contents.

You can also define any request parameters the endpoint expects, although this
endpoint uses none.

This excerpt shows only a few annotations for illustration. The
link:{helidon-github-tree-url}/examples/microprofile/openapi-basic[Helidon MP OpenAPI example] illustrates more,
and the link:{microprofile-open-api-spec-url}[MicroProfile OpenAPI spec] describes them all.

===== Provide a static OpenAPI file
Add a static file at `META-INF/openapi.yml`, `META-INF/openapi.yaml`,
or `META-INF/openapi.json`. Tools such as Swagger let you describe your app's API
and they then generate an OpenAPI document file which you can include in your application
so OpenAPI can use it.

===== Write and configure a model reader class
Write a Java class that implements the OpenAPI
link:{microprofile-open-api-javadoc-url}/OASModelReader.html[`org.eclipse.microprofile.openapi.OASModelReader`] interface. Your
model reader code programmatically adds elements to the internal model that OpenAPI
builds.

endif::[]

===== Provide a static OpenAPI file
Add a static file at `META-INF/openapi.yml`, `META-INF/openapi.yaml`,
or `META-INF/openapi.json`. Tools such as Swagger let you describe your app's API
and they then generate an OpenAPI document file which you can include in your application
so OpenAPI can use it.

===== Write and configure a model reader class
Write a Java class that implements the OpenAPI
link:{microprofile-open-api-javadoc-url}/OASModelReader.html[`org.eclipse.microprofile.openapi.OASModelReader`] interface. Your
model reader code programmatically adds elements to the internal model that OpenAPI
builds.

Change your application's MP configuration to set `mp.openapi.model.reader` as the
fully-qualified class name of your class.

===== Write and configure a filter class
Write a Java class that implements the OpenAPI
link:{microprofile-open-api-javadoc-url}/OASFilter.html[`org.eclipse.microprofile.openapi.OASFilter`] interface.
As OpenAPI composes its internal model, it invokes your filter with each
model element _before_ adding the element to the model. Your filter can
accept the element as-is, modify it, or suppress it.

Change your application's configuration to set `mp.openapi.filter` as the full-qualified
class name of your class.

// end::furnish-openapi-info[]

// tag::usage-access-endpoint[]
=== Accessing the REST Endpoint
Once you add the {flavor-uc} OpenAPI dependency to your
ifdef::mp-flavor[project,]
ifdef::se-flavor[project and add code to create the `OpenAPISupport` object to your routing,]
your application will automatically respond to the built-in endpoint --
spericas marked this conversation as resolved.
Show resolved Hide resolved
`/openapi` -- and it will return the OpenAPI document describing the endpoints
in your application.

By default, per the MicroProfile OpenAPI spec, the default format of the OpenAPI document is YAML.
There is not yet an adopted IANA YAML media type, but a proposed one specifically
for OpenAPI documents that has some support is `application/vnd.oai.openapi`.
That is what Helidon returns, by default.

In addition, a client can specify the HTTP header `Accept:` as either `application/vnd.oai.openapi+json` or
tjquinno marked this conversation as resolved.
Show resolved Hide resolved
`application/json` to request JSON. Alternatively, the client can pass the query parameter `format` as either `JSON`
or `YAML` to receive `application/json` or `application/vnd.oai.openapi` (YAML) output, respectively.
// end::usage-access-endpoint[]

// tag::api[]
ifdef::mp-flavor[]
The link:{microprofile-open-api-spec-url}[MicroProfile OpenAPI specification] gives a listing and brief examples of the annotations you can add to your code to convey OpenAPI information.
endif::[]

The link:{microprofile-open-api-javadoc-base-url}[MicroProfile OpenAPI JavaDocs] give full details of the
ifdef::mp-flavor[annotations and the other]
classes and interfaces you can use in your code.
ifdef::se-flavor[]
Remember that, although the JavaDocs describe annotations, Helidon {flavor-uc} does not support them.
endif::[]

// end::api[]

// tag::common-config[]
Helidon {h1-prefix} also supports additional properties specific to Helidon.
tjquinno marked this conversation as resolved.
Show resolved Hide resolved

Expand All @@ -31,3 +180,44 @@ Helidon {h1-prefix} also supports additional properties specific to Helidon.
`META-INF/openapi.yaml`, or
`META-INF/openapi.json`)
|===

// tag::additional-building-jandex[]

=== Building the Jandex index

A Jandex index stores information about the classes and methods in your app and
what annotations they have. It allows CDI to process annotations faster during your
application's start-up.

Add the link:https://github.com/wildfly/jandex-maven-plugin[Jandex maven plug-in] to the `<build><plugins>`
section of your `pom.xml`:

[source,xml,subs="attributes+"]
----
<plugin>
<groupId>org.jboss.jandex</groupId>
<artifactId>jandex-maven-plugin</artifactId>
<version>{jandex-plugin-version}</version>
<executions>
<execution>
<id>make-index</id>
<goals>
<goal>jandex</goal>
</goals>
</execution>
</executions>
</plugin>
----
When you build your app `maven` should include the index `META-INF/jandex.idx` in
the JAR.

[NOTE]
====
If you _do not_ modify your build to create
the index then the Helidon MP OpenAPI runtime automatically creates one in memory during
app start-up. This slows down your app start-up and, depending on how CDI is
configured, might inadvertently miss information.

We _strongly recommend_ using the Jandex plug-in to build the index into your app.
====
// end::additional-building-jandex[]
Loading