API documentation with OpenAPI
MicroProfile OpenAPI helps you to generate structured documentation from your Jakarta RESTful Services or JAX-RS applications. This documentation helps other microservices and developers to understand and communicate with your application.
Other developers need relevant information to build an application that communicates with the REST API of your application. MicroProfile OpenAPI facilitates this communication by generating human and machine-readable documentation on a simple interface that doesn’t require access to the source code.
You can implement MicroProfile OpenAPI for Open Liberty by enabling the MicroProfile OpenAPI feature. When this feature is enabled, you can view the OpenAPI document in a browser by using the /openapi
endpoint. For example, if your browser is on the same machine where your server is running, you can view the raw OpenAPI document at the http://localhost:9080/openapi
URL or view the OpenAPI document in a user interface at the http://localhost:9080/openapi/ui
URL.
To explore how to document and filter RESTful APIs from code or static files by using Open Liberty and MicroProfile OpenAPI, see the Documenting RESTful APIs guide.
The two main approaches to generate an OpenAPI document are the code-first approach and the design-first approach. In the code-first approach, you can generate documentation of the REST API from the source code. The reference document that is produced lists all the API endpoints with descriptions of how to use them. Alternatively, in the design-first approach, you can include a pre-generated OpenAPI document that was written separately from the code. The JAX-RS framework handles basic API generation for JAX-RS annotations and generates a skeleton OpenAPI treemap. You can use this treemap as a starting point and augment it with annotations and code to produce a complete OpenAPI document. Additionally, you can use this manually created documentation to generate stubs, or testable versions of code modules, such as client libraries for the API.
The code-first approach
In the code-first approach, you can initially generate basic API documentation of the REST API from annotations that are specified in the source code. Then, you can augment the existing annotations with OpenAPI annotations, which are processed to generate the documentation. Adding annotations takes less work than manually defining the OpenAPI document, and gives a useful explanation of the different parts of the API.
In the following example, the OpenAPI annotations @APIResponses
, @Operation
, and @Parameter
are added to the purchaseCar()
JAX-RS method.
@PUT
@Path("/buy/{registration}")
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.TEXT_PLAIN)
@APIResponses(
value = {
@APIResponse(
responseCode = "404",
description = "The requested car could not be found at the dealership, and could not be purchased.",
content = @Content(mediaType = "text/plain")),
@APIResponse(
responseCode = "200",
description = "The requested car was successfully purchased.",
content = @Content(mediaType = "application/json"))})
@Operation(
summary = "Purchases the specified car from the dealership, and adds the car to your garage.",
description = "Retrieves the car with the specified registration from the dealership if it exists, and
adds this to the caller's garage. The boolean response represents the state of the internal operation.")
public Response purchaseCar(
@Parameter(
description = "The registration of the car to be added to the inventory.",
required = true,
example = "NX15 9012",
schema = @Schema(type = SchemaType.STRING))
@PathParam("registration") String registration) {
boolean success = manager.purchaseCar(registration);
if (!success) {
return Response.status(Response.Status.NOT_FOUND)
.entity("{ \"error\" : "
+ "\"The car with registration " + registration
+ " could not be added to the inventory\" }")
.build();
}
return Response.ok(success).build();
}
The default format of the generated document is YAML, but documents can also be provided in JSON format. The following OpenAPI document is generated in YAML format from the OpenAPI annotations in the previous example.
/my-garage/buy/{registration}:
put:
summary: "Purchases the specified car from the dealership, and adds the car\
\ to your garage."
description: "Retrieves the car with the specified registration from the dealership\
\ if it exists, and adds this to the caller's garage. The boolean response\
\ represents the state of the internal operation."
parameters:
- name: registration
in: path
description: The registration of the car to be added to the inventory.
required: true
schema:
type: string
example: NX15 9012
responses:
"404":
description: "The requested car could not be found at the dealership, and\
\ could not be purchased."
content:
text/plain: {}
"200":
description: The requested car was successfully purchased.
content:
application/json: {}
The information that is provided through the OpenAPI annotations augments the basic API documentation that is generated by the JAX-RS framework.
For more information, see the MicroProfile OpenAPI Javadoc for the available annotations.
The design-first approach
An alternative approach is to design the REST API in an editor, such as the Swagger editor, before you write any code. With this approach, you can spot and rectify any issues in the design before it is implemented. In large companies, subject matter experts review the API to ensure it’s consistent and usable. This API design then forms a contract and must be implemented as agreed.
You can write this API design in YAML or JSON format and place it in the META-INF
directory of your application. Optionally, you can create stubs for the API code. The code-first and design-first approaches are not mutually exclusive. You can augment manually created API documents by adding annotations to the code as you would in a code-first approach.
For more information, see Using pregenerated OpenAPI documents.
Multiple application and multi-module application support with MicroProfile OpenAPI
By default, OpenAPI documentation is generated for only the first web module of the first application that is deployed on the server. The MicroProfile OpenAPI feature, version 2.0 and later, provides configuration properties to select which applications and web modules OpenAPI documentation is generated for. If more than one web module or application is specified, an OpenAPI document is generated for each module or application and then they are merged to create a single OpenAPI document. A property is also provided to set the info
section of the final merged OpenAPI document.
For example, to include all the applications in your deployment in a single merged OpenAPI document, you can define the following MicroProfile Config property as a variable in your server.xml
file.
<variable name="mp.openapi.extensions.liberty.merged.include" value="all"/>
The following table lists MicroProfile Config properties that can be specified to configure which modules or applications are included in the generated OpenAPI documentation. These properties are available when you enable the MicroProfile OpenAPI feature, version 2.0 and later. Alternatively, you can specify the MicroProfile convenience feature, version 4.0 or later, which automatically enables the full set of MicroProfile features. For configuration examples, see the MicroProfile OpenAPI feature.
Property name | Description | Default value | Valid values |
---|---|---|---|
| This property specifies which modules or applications are included in the generated OpenAPI documentation. |
|
|
| This property overrides the |
|
|
| This property sets the | N/A | The value must be a valid OpenAPI info section in JSON format. |
Resolution of OpenAPI document merging conflicts
When OpenAPI documentation from multiple modules is merged into a single document, Open Liberty applies the following rules to resolve potential conflicts between the OpenAPI documents that are being merged.
If all server URLs end with the context root, the context root is removed from each server URL and added as a prefix to each path. If no servers exist in a document, the context root is added as a prefix to each path. If the same path is then declared in more than one document, a warning is logged and all but one of the clashing documents is excluded from the merged documentation.
If the same extension name is declared with different values at the top level of more than one document, a warning is logged. All but one of the clashing documents are excluded from the merged documentation.
If the top-level
servers
section is not identical across all documents, each server is removed from the top level and copied under the paths that it applies to.Component names are made unique by adding a number to the end of them where necessary. References to the component name are updated.
Operation IDs are made unique by adding a number to the end of them where necessary. References to the operation ID are updated.
If the
info
section is not identical across all documents, it is replaced by a standard info section that says that the documentation from several modules was merged.If the top-level
security
section is not the same across all documents, the security requirements are copied under each operation that they apply to.If the
externalDocs
section is not the same across all documents, it is removed from the final document.