{"id":18429210,"url":"https://github.com/openliberty/guide-microprofile-openapi","last_synced_at":"2025-04-07T17:32:57.219Z","repository":{"id":30169689,"uuid":"121298050","full_name":"OpenLiberty/guide-microprofile-openapi","owner":"OpenLiberty","description":"A guide on how to document and filter RESTful APIs from code or static files by using MicroProfile OpenAPI: https://openliberty.io/guides/microprofile-openapi.html","archived":false,"fork":false,"pushed_at":"2024-04-12T16:25:01.000Z","size":453,"stargazers_count":16,"open_issues_count":2,"forks_count":15,"subscribers_count":6,"default_branch":"prod","last_synced_at":"2024-04-13T18:30:07.253Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/OpenLiberty.png","metadata":{"files":{"readme":"README.adoc","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2018-02-12T20:29:21.000Z","updated_at":"2024-05-06T19:46:41.911Z","dependencies_parsed_at":"2024-03-18T16:02:52.986Z","dependency_job_id":"198fff0e-8de6-4b85-9be1-e2415d09a76d","html_url":"https://github.com/OpenLiberty/guide-microprofile-openapi","commit_stats":null,"previous_names":[],"tags_count":12,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/OpenLiberty%2Fguide-microprofile-openapi","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/OpenLiberty%2Fguide-microprofile-openapi/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/OpenLiberty%2Fguide-microprofile-openapi/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/OpenLiberty%2Fguide-microprofile-openapi/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/OpenLiberty","download_url":"https://codeload.github.com/OpenLiberty/guide-microprofile-openapi/tar.gz/refs/heads/prod","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247697966,"owners_count":20981278,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-06T05:16:16.631Z","updated_at":"2025-04-07T17:32:57.212Z","avatar_url":"https://github.com/OpenLiberty.png","language":"Java","funding_links":[],"categories":[],"sub_categories":[],"readme":"// Copyright (c) 2017, 2025 IBM Corporation and others.\n// Licensed under Creative Commons Attribution-NoDerivatives\n// 4.0 International (CC BY-ND 4.0)\n//   https://creativecommons.org/licenses/by-nd/4.0/\n//\n// Contributors:\n//   IBM Corporation\n:projectid: microprofile-openapi\n:page-layout: guide-multipane\n:page-duration: 20 minutes\n:page-releasedate: 2018-03-16\n:page-guide-category: microprofile\n:page-essential: false\n:page-description: Explore how to document and filter RESTful APIs from code or static files by using MicroProfile OpenAPI.\n:page-tags: ['microprofile']\n:page-permalink: /guides/{projectid}\n:page-related-guides: ['cdi-intro', 'microprofile-config']\n:common-includes: https://raw.githubusercontent.com/OpenLiberty/guides-common/prod\n:source-highlighter: prettify\n:page-seo-title: Documenting RESTful APIs using MicroProfile OpenAPI\n:page-seo-description: A tutorial on how to document and filter RESTful APIs by using MicroProfile OpenAPI\n:guide-author: Open Liberty\n= Documenting RESTful APIs\n\n[.hidden]\nNOTE: This repository contains the guide documentation source. To view the guide in published form, view it on the https://openliberty.io/guides/{projectid}.html[Open Liberty website].\n\nExplore how to document and filter RESTful APIs from code or static files by using MicroProfile OpenAPI.\n\n:openapi-url: http://localhost:9080/openapi\n:inv-url: http://localhost:9080/inventory/systems\n:sys-url: http://localhost:9080/inventory/properties\n\n== What you'll learn\n\nYou will learn how to document and filter RESTful APIs from annotations, POJOs, and static OpenAPI files by using MicroProfile OpenAPI.\n\nThe OpenAPI specification, previously known as the Swagger specification, defines a standard interface for documenting and exposing RESTful APIs. This specification allows both humans and computers to understand or process the functionalities of services without requiring direct access to underlying source code or documentation. The MicroProfile OpenAPI specification provides a set of Java interfaces and programming models that allow Java developers to natively produce OpenAPI v3 documents from their JAX-RS applications.\n\nYou will document the RESTful APIs of the provided `inventory` service, which serves two endpoints, `inventory/systems` and `inventory/properties`. These two endpoints function the same way as in the other MicroProfile guides.\n\nBefore you proceed, note that the 1.0 version of the MicroProfile OpenAPI specification does not define how the `/openapi` endpoint may be partitioned in the event of multiple JAX-RS applications running on the same server. In other words, you must stick to one JAX-RS application per server instance as the behaviour for handling multiple applications is currently undefined.\n\n\n// =================================================================================================\n// Getting Started\n// =================================================================================================\n[role='command']\ninclude::{common-includes}/gitclone.adoc[]\n\n// =================================================================================================\n// Try what you'll build\n// =================================================================================================\n[role='command']\ninclude::{common-includes}/twyb-intro.adoc[]\n\n\nifndef::cloud-hosted[]\nNext, point your browser to the {openapi-url}[{openapi-url}^] URL and you'll see the RESTful APIs of the `inventory` service. You can also point to the {openapi-url}/ui[{openapi-url}/ui^] URL for a more interactive view of the deployed APIs. This UI is built from the https://swagger.io/tools/swagger-ui/[Open Source Swagger UI^] and renders the generated `/openapi` document into a very user friendly page.\nendif::[]\n\nifdef::cloud-hosted[]\nTo open a new command-line session, select **Terminal** \u003e **New Terminal** from the menu of the IDE.\n\nNext, run the following curl command to see the RESTful APIs of the ***inventory*** service:\n```bash\ncurl http://localhost:9080/openapi\n```\n\nA UI is also available for a more interactive view of the deployed APIs. Click the following button to visit the UI by the ***/openapi/ui*** endpoint. \n::startApplication{port=\"9080\" display=\"external\" name=\"Visit OpenAPI UI\" route=\"/openapi/ui\"}\n\nThis UI is built from the [Open Source Swagger UI](https://swagger.io/tools/swagger-ui), which renders the generated **/openapi** document into a very user friendly page.\nendif::[]\n\n[role='command']\ninclude::{common-includes}/twyb-end.adoc[]\n\n// =================================================================================================\n// Generating APIs\n// =================================================================================================\n\n== Generating the OpenAPI document for the inventory service\n\nYou can generate an OpenAPI document in various ways. First, because all Jakarta Restful Web Services annotations are processed by default, you can augment your existing Jakarta Restful Web Services annotations with OpenAPI annotations to enrich your APIs with a minimal amount of work. Second, you can use a set of predefined models to manually create all elements of the OpenAPI tree. Finally, you can filter various elements of the OpenAPI tree, changing them to your liking or removing them entirely.\n\nNavigate to the `start` directory to begin.\n// cloud hosted instructions\nifdef::cloud-hosted[]\n```bash\ncd /home/project/guide-microprofile-openapi/start\n```\nendif::[]\n\n[role='command']\ninclude::{common-includes}/devmode-lmp33-start.adoc[]\n\nBecause the Jakarta Restful Web Services framework handles basic API generation for Jakarta Restful Web Services annotations, a skeleton OpenAPI tree will be generated from the `inventory` service. You can use this tree as a starting point and augment it with annotations and code to produce a complete OpenAPI document.\n\n\nifndef::cloud-hosted[]\nNow, visit the {openapi-url}[{openapi-url}^] URL to see the generated OpenAPI tree. You can also visit the {openapi-url}/ui[{openapi-url}/ui^] URL for a more interactive view of the APIs.\nendif::[]\n\nifdef::cloud-hosted[]\nNow, run the following curl command to see the generated OpenAPI tree:\n```bash\ncurl http://localhost:9080/openapi\n```\n\nClick the following button to visit the UI by the ***/openapi/ui*** endpoint for a more interactive view of the APIs.\n::startApplication{port=\"9080\" display=\"external\" name=\"Visit OpenAPI UI\" route=\"/openapi/ui\"}\nendif::[]\n\n=== Augmenting the existing Jakarta Restful Web Services annotations with OpenAPI annotations\n\nBecause all Jakarta Restful Web Services annotations are processed by default, you can augment the existing code with OpenAPI annotations without needing to rewrite portions of the OpenAPI document that are already covered by the Jakarta Restful Web Services framework.\n\n[role='code_command hotspot file=0', subs=\"quotes\"]\n----\n#Replace the `InventoryResource` class.#\n`src/main/java/io/openliberty/guides/inventory/InventoryResource.java`\n----\n\n[role=\"edit_command_text\"]\nAdd OpenAPI [hotspot=APIResponse file=0]`@APIResponse`, [hotspot=APIResponseSchema file=0]`@APIResponseSchema`, [hotspot=Operation file=0]`@Operation`, and [hotspot=Parameter file=0]`@Parameter` annotations to the two JAX-RS endpoint methods, [hotspot=host-property hotspot=Parameter file=0]`getPropertiesForHost()` and [hotspot=listContents file=0]`listContents()`.\n\n\nInventoryResource.java\n[source, Java, linenums, role='code_column hide_tags=copyright']\n----\ninclude::finish/src/main/java/io/openliberty/guides/inventory/InventoryResource.java[]\n----\n\nClearly, there are many more OpenAPI annotations now, so let’s break them down:\n\n[cols=\"35, 200\", options=\"header\"]\n|===\n| *Annotation*    | *Description*\n| [hotspot=APIResponse file=0]`@APIResponse`  | Describes a single response from an API operation.\n| [hotspot=APIResponseSchema file=0]`@APIResponseSchema` | Convenient short-hand way to specify a simple response with a Java class that could otherwise be specified using @APIResponse.\n| [hotspot=Operation file=0]`@Operation`    | Describes a single API operation on a path.\n| [hotspot=Parameter file=0]`@Parameter`    | Describes a single operation parameter.\n|===\n\nifndef::cloud-hosted[]\nBecause the Open Liberty instance was started in dev mode at the beginning of the guide, your changes were automatically picked up. Refresh the {openapi-url}[{openapi-url}^] URL to see the updated OpenAPI tree. The two endpoints at which your JAX-RS endpoint methods are served are now more meaningful:\nendif::[]\n\nifdef::cloud-hosted[]\nBecause the Open Liberty instance was started in dev mode at the beginning of the guide, your changes were automatically picked up. Run the following curl command to see the updated OpenAPI tree:\n```bash\ncurl http://localhost:9080/openapi\n```\n\nThe two endpoints at which your JAX-RS endpoint methods are served are now more meaningful:\nendif::[]\n\n[source, YAML, role=\"no_copy\"]\n----\n/inventory/systems:\n  get:\n    summary: List inventory contents.\n    description: Returns the currently stored host:properties pairs in the inventory.\n    responses:\n      \"200\":\n        description: host:properties pairs stored in the inventory.\n        content:\n          application/json:\n            schema:\n              $ref: '#/components/schemas/InventoryList'\n/inventory/systems/{hostname}:\n  get:\n    summary: Get JVM system properties for particular host\n    description: Retrieves and returns the JVM system properties from the system\n      service running on the particular host.\n    parameters:\n    - name: hostname\n      in: path\n      description: The host for whom to retrieve the JVM system properties for.\n      required: true\n      schema:\n        type: string\n      example: localhost\n    responses:\n      \"404\":\n        description: Missing description\n        content:\n          application/json: {}\n      \"200\":\n        description: JVM system properties of a particular host.\n        content:\n          application/json:\n            schema:\n              type: object\n----\n\n\nOpenAPI annotations can also be added to POJOs to describe what they represent. Currently, your OpenAPI document doesn't have a very meaningful description of the [hotspot=InventoryListClass file=1]`InventoryList` POJO and hence it's very difficult to tell exactly what that POJO is used for. To describe the [hotspot=InventoryListClass file=1]`InventoryList` POJO in more detail, augment the [hotspot file=1]`src/main/java/io/openliberty/guides/inventory/model/InventoryList.java` file with some OpenAPI annotations.\n\n[role='code_command hotspot file=1', subs=\"quotes\"]\n----\n#Replace the `InventoryList` class.#\n`src/main/java/io/openliberty/guides/inventory/model/InventoryList.java`\n----\n\n[role='edit_command_text']\nAdd OpenAPI [hotspot=InventoryList hotspot=Systems file=1]`@Schema` annotations to the [hotspot=InventoryList file=1]`InventoryList` class and the [hotspot=Systems file=1]`systems` variable.\n\nInventoryList.java\n[source, Java, linenums, role='code_column hide_tags=copyright']\n----\ninclude::finish/src/main/java/io/openliberty/guides/inventory/model/InventoryList.java[]\n----\n\nLikewise, annotate the [hotspot file=2]`src/main/java/io/openliberty/guides/inventory/model/SystemData.java` POJO, which is referenced in the [hotspot file=1]`InventoryList` class.\n\n[role='code_command hotspot file=2', subs=\"quotes\"]\n----\n#Replace the `SystemData` class.#\n`src/main/java/io/openliberty/guides/inventory/model/SystemData.java`\n----\n\n[role='edit_command_text']\nAdd OpenAPI [hotspot=SystemData hotspot=Hostname hotspot=Properties file=2]`@Schema` annotations to the [hotspot=SystemData file=2]`SystemData` class, the [hotspot=Hostname file=2]`hostname` variable and the [hotspot=Properties file=2]`properties` variable.\n\nSystemData.java\n[source, Java, linenums, role='code_column hide_tags=copyright']\n----\ninclude::finish/src/main/java/io/openliberty/guides/inventory/model/SystemData.java[]\n----\n\nifndef::cloud-hosted[]\nRefresh the {openapi-url}[{openapi-url}^] URL to see the updated OpenAPI tree:\nendif::[]\n\nifdef::cloud-hosted[]\nRun the following curl command to see the updated OpenAPI tree:\n```bash\ncurl http://localhost:9080/openapi\n```\nendif::[]\n\n[source, YAML, role=\"no_copy\"]\n----\ncomponents:\n  schemas:\n    InventoryList:\n      description: POJO that represents the inventory contents.\n      required:\n      - systems\n      type: object\n      properties:\n        systems:\n          type: array\n          items:\n            $ref: '#/components/schemas/SystemData'\n        total:\n          format: int32\n          type: integer\n    SystemData:\n      description: POJO that represents a single inventory entry.\n      required:\n      - hostname\n      - properties\n      type: object\n      properties:\n        hostname:\n          type: string\n        properties:\n          type: object\n----\n\n\n=== Filtering the OpenAPI tree elements\n\nFiltering of certain elements and fields of the generated OpenAPI document can be done by using the `OASFilter` interface.\n\n[role=\"code_command hotspot file=0\", subs=\"quotes\"]\n----\n#Create the `InventoryOASFilter` class.#\n`src/main/java/io/openliberty/guides/inventory/filter/InventoryOASFilter.java`\n----\nInventoryOASFilter.java\n[source, Java, linenums, role='code_column hide_tags=copyright']\n----\ninclude::finish/src/main/java/io/openliberty/guides/inventory/filter/InventoryOASFilter.java[]\n----\n\nThe [hotspot=filterAPIResponse file=0]`filterAPIResponse()` method allows filtering of `APIResponse` elements. When you override this method, it will be called once for every `APIResponse` element in the OpenAPI tree. In this case, you are matching the `404` response that is returned by the `/inventory/systems/{hostname}` endpoint and setting the previously missing description. To remove an `APIResponse` element or another filterable element, simply return `null`.\n\nThe [hotspot=filterOpenAPI file=0]`filterOpenAPI()` method allows filtering of the singleton [hotspot=OpenAPI file=0]`OpenAPI` element. Unlike other filter methods, when you override [hotspot=filterOpenAPI file=0]`filterOpenAPI()`, it is called only once as the last method for a particular filter. Hence, make sure that it doesn't override any other filter operations that are called before it. Your current OpenAPI document doesn't provide much information on the application itself or on what server and port it runs on. This information is usually provided in the `info` and `servers` elements, which are currently missing. Use the `OASFactory` class to manually set these and other elements of the OpenAPI tree from the `org.eclipse.microprofile.openapi.models` package. The [hotspot=OpenAPI file=0]`OpenAPI` element is the only element that cannot be removed, because that would mean removing the whole OpenAPI tree.\n\nEach filtering method is called once for each corresponding element in the model tree. You can think of each method as a callback for various key OpenAPI elements.\n\nBefore you can use the filter class that you created, you need to create the [hotspot file=1]`microprofile-config.properties` file.\n\n[role=\"code_command hotspot file=1\", subs=\"quotes\"]\n----\n#Create the configuration file.#\n`src/main/resources/META-INF/microprofile-config.properties`\n----\nmicroprofile-config.properties\n[source, text, linenums, role='code_column hide_tags=Scan']\n----\ninclude::finish/src/main/resources/META-INF/microprofile-config.properties[]\n----\n\nThis configuration file is picked up automatically by MicroProfile Config and registers your filter by passing in the fully qualified name of the filter class into the [hotspot=Config file=1]`mp.openapi.filter` property.\n\nifndef::cloud-hosted[]\nRefresh the {openapi-url}[{openapi-url}^] URL to see the updated OpenAPI tree:\nendif::[]\n\nifdef::cloud-hosted[]\nRun the following curl command to see the updated OpenAPI tree:\n```bash\ncurl http://localhost:9080/openapi\n```\nendif::[]\n\n[source, yaml, role=\"no_copy\"]\n----\ninfo:\n  title: Inventory App\n  description: App for storing JVM system properties of various hosts.\n  license:\n    name: Eclipse Public License - v 2.0\n    url: https://www.eclipse.org/legal/epl-2.0\n  version: \"1.0\"\nservers:\n- url: \"http://localhost:{port}\"\n  description: Simple Open Liberty.\n  variables:\n    port:\n      default: \"9080\"\n      description: Server HTTP port.\n----\n\n[source, yaml, role=\"no_copy\"]\n----\nresponses:\n  \"404\":\n    description: Invalid hostname or the system service may not be running on\n      the particular host.\n    content:\n      application/json: {}\n----\n\nFor more information about which elements you can filter, see the https://openliberty.io/docs/latest/reference/javadoc/microprofile-7.0-javadoc.html[MicroProfile API documentation^].\n\nTo learn more about MicroProfile Config, visit the MicroProfile Config https://github.com/eclipse/microprofile-config[GitHub repository^] and try one of the MicroProfile Config https://openliberty.io/guides/?search=Config[guides^].\n\n\n// =================================================================================================\n// Pre-generated APIs\n// =================================================================================================\n\n== Using pregenerated OpenAPI documents\n\nAs an alternative to generating the OpenAPI model tree from code, you can provide a valid pregenerated OpenAPI document to describe your APIs. This document must be named `openapi` with a `yml`, `yaml`, or `json` extension and be placed under the `META-INF` directory. Depending on the scenario, the document might be fully or partially complete. If the document is fully complete, then you can disable annotation scanning entirely by setting the `mp.openapi.scan.disable` MicroProfile Config property to `true`. If the document is partially complete, then you can augment it with code.\n\nTo use the pre-generated OpenAPI document, create the OpenAPI document YAML file.\n\n[role=\"code_command hotspot file=0\", subs=\"quotes\"]\n----\n#Create the OpenAPI document file.#\n`src/main/resources/META-INF/openapi.yaml`\n----\n\n\nopenapi.yaml\n[source, text, linenums, role='code_column']\n----\ninclude::finish/src/main/resources/META-INF/openapi.yaml[]\n----\n\nThis document is the same as your current OpenAPI document with extra APIs for the `/inventory/properties` endpoint. This document is complete so you can also add the [hotspot=Scan file=1]`mp.openapi.scan.disable` property and set it to `true` in the [hotspot file=1]`src/main/resources/META-INF/microprofile-config.properties` file.\n\n[role=\"code_command hotspot file=1\", subs=\"quotes\"]\n----\n#Replace the configuration file.#\n`src/main/resources/META-INF/microprofile-config.properties`\n----\n\n[role=\"edit_command_text\"]\nAdd and set the [hotspot=Scan file=1]`mp.openapi.scan.disable` property to `true`.\n\nmicroprofile-config.properties\n[source, text, linenums, role='code_column']\n----\ninclude::finish/src/main/resources/META-INF/microprofile-config.properties[]\n----\n\nifndef::cloud-hosted[]\nRefresh the {openapi-url}[{openapi-url}^] URL to see the updated OpenAPI tree:\nendif::[]\n\nifdef::cloud-hosted[]\nRun the following curl command to see the updated OpenAPI tree:\n```bash\ncurl http://localhost:9080/openapi\n```\nendif::[]\n\n[source, yml, role=\"no_copy\"]\n----\n/inventory/properties:\n  get:\n    operationId: getProperties\n    responses:\n      \"200\":\n        description: JVM system properties of the host running this service.\n        content:\n          application/json:\n            schema:\n              type: object\n              additionalProperties:\n                type: string\n----\n\n\n// =================================================================================================\n// Testing the services\n// =================================================================================================\n\n== Testing the service\n\n// static guide instructions:\nifndef::cloud-hosted[]\nNo automated tests are provided to verify the correctness of the generated OpenAPI document. Manually verify the document by visiting the {openapi-url}[{openapi-url}^] or the {openapi-url}/ui[{openapi-url}/ui^] URL.\nendif::[]\n\n// cloud-hosted guide instructions:\nifdef::cloud-hosted[]\nNo automated tests are provided to verify the correctness of the generated OpenAPI document. Manually verify the document by visiting the ***http://localhost:9080/openapi*** or the ***http://localhost:9080/openapi/ui*** URL.\nendif::[]\n\nA few tests are included for you to test the basic functionality of the `inventory` service. If a test failure occurs, then you might have introduced a bug into the code. These tests will run automatically as a part of the integration test suite.\n\n[role='command']\ninclude::{common-includes}/devmode-test.adoc[]\n\nYou will see the following output:\n\n[source, role=\"no_copy\"]\n----\n-------------------------------------------------------\n T E S T S\n-------------------------------------------------------\nRunning it.io.openliberty.guides.system.SystemEndpointIT\nTests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 1.4 sec - in it.io.openliberty.guides.system.SystemEndpointIT\nRunning it.io.openliberty.guides.inventory.InventoryEndpointIT\n[WARNING ] Interceptor for {http://client.inventory.guides.openliberty.io/}SystemClient has thrown exception, unwinding now\nCould not send Message.\n[err] The specified host is unknown: java.net.UnknownHostException: UnknownHostException invoking http://badhostname:9080/inventory/properties: badhostname\nTests run: 3, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.264 sec - in it.io.openliberty.guides.inventory.InventoryEndpointIT\n\nResults :\n\nTests run: 4, Failures: 0, Errors: 0, Skipped: 0\n----\n\nThe warning and error messages are expected and result from a request to a bad or an unknown hostname. This request is made in the `testUnknownHost()` test from the `InventoryEndpointIT` integration test.\n\n[role='command']\ninclude::{common-includes}/devmode-quit-ctrlc.adoc[]\n\n\n// =================================================================================================\n// Great work! You're done!\n// =================================================================================================\n\n== Great work! You're done!\n\nYou have just documented and filtered the APIs of the `inventory` service from both the code and a static file by using MicroProfile OpenAPI in Open Liberty.\n\nFeel free to try one of the related MicroProfile guides. They demonstrate additional technologies that you can learn and expand on top of what you built here.\n\nFor more in-depth examples of MicroProfile OpenAPI, try one of the demo applications available in the MicroProfile OpenAPI https://github.com/eclipse/microprofile-open-api/tree/master/tck/src/main/java/org/eclipse/microprofile/openapi/apps[GitHub repository^].\n\n\ninclude::{common-includes}/attribution.adoc[subs=\"attributes\"]\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fopenliberty%2Fguide-microprofile-openapi","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fopenliberty%2Fguide-microprofile-openapi","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fopenliberty%2Fguide-microprofile-openapi/lists"}