|
| 1 | +--- |
| 2 | +layout: post |
| 3 | +title: "Building Better APIs: Documenting APIs in Open Liberty using MicroProfile OpenAPI" |
| 4 | +categories: blog |
| 5 | +author_picture: https://avatars3.githubusercontent.com/sweettypdevassy |
| 6 | +author_github: https://github.com/sweettypdevassy |
| 7 | +seo-title: Building Better APIs, Documenting APIs in Open Liberty using MicroProfile OpenAPI - OpenLiberty.io |
| 8 | +seo-description: This blog explores the OpenAPI Specification and its integration with Open Liberty using MicroProfile OpenAPI. It covers the importance of API documentation, the role of OpenAPI and Swagger, and a step-by-step guide to using MicroProfile OpenAPI in an Open Liberty project. Readers will learn about various MicroProfile OpenAPI annotations with practical examples and see how they are rendered in Swagger UI. |
| 9 | +blog_description: "This blog explores the OpenAPI Specification and its integration with Open Liberty using MicroProfile OpenAPI. It covers the importance of API documentation, the role of OpenAPI and Swagger, and a step-by-step guide to using MicroProfile OpenAPI in an Open Liberty project. Readers will learn about various MicroProfile OpenAPI annotations with practical examples and see how they are rendered in Swagger UI." |
| 10 | +open-graph-image: https://openliberty.io/img/twitter_card.jpg |
| 11 | +open-graph-image-alt: Open Liberty Logo |
| 12 | +additional_authors: |
| 13 | +- name: Abhinav K |
| 14 | + github: https://github.com/itsabhinavk |
| 15 | + image: https://avatars0.githubusercontent.com/itsabhinavk |
| 16 | +--- |
| 17 | += Building Better APIs: Documenting APIs in Open Liberty using MicroProfile OpenAPI |
| 18 | +Sweetty P Devassy <https://github.com/sweettypdevassy> |
| 19 | +:imagesdir: / |
| 20 | +:url-prefix: |
| 21 | +:url-about: / |
| 22 | + |
| 23 | + |
| 24 | +As technology has evolved and our applications have become more complicated, so too have our APIs. We are now building a huge number of highly complicated APIs. Documenting them requires effort and is often seen as a tedious task. Furthermore, the complex nature of these APIs can make documentation even more challenging. But why does documentation of our APIs matter? API documentation serves as a means of sharing up-to-date information between development teams, acting as a sort of how-to manual for developers that are looking to build things with your API. But having a standardized way of documenting our APIs so that we can all easily understand other APIs and what they do was a challenge... at least until the development of link:https://swagger.io/[Swagger] and later the link:https://www.openapis.org/[OpenAPI] specification. Having a structured approach to documentation helps developers improve collaboration, reduce errors, and accelerate development cycles. |
| 25 | + |
| 26 | +So, let's dive into the OpenAPI specification and explore how you can use it in your Open Liberty project with link:https://microprofile.io/specifications/open-api/[MicroProfile OpenAPI] features to easily and effectively document your APIs. |
| 27 | + |
| 28 | +== What is OpenAPI? |
| 29 | + |
| 30 | +OpenAPI is a standardised specification for describing RESTful APIs in a machine-readable format (JSON or YAML). It allows developers to define, document, and share API structures in a way that is both human-readable and programmatically useful. At its core, an OpenAPI definition includes: |
| 31 | + |
| 32 | +* *Info* – API title, version, description |
| 33 | + |
| 34 | +* *Servers* – Base URLs of the API |
| 35 | + |
| 36 | +* *Paths* – Endpoints (/users, /orders) |
| 37 | + |
| 38 | +* *Methods* – GET, POST, PUT, DELETE |
| 39 | + |
| 40 | +* *Parameters* – Query, path, header, or body inputs |
| 41 | + |
| 42 | +* *Responses* – Expected status codes and return data |
| 43 | + |
| 44 | +* *Security* – Authentication methods (OAuth, API keys, etc.) |
| 45 | + |
| 46 | +The OpenAPI specification can be used together with link:https://swagger.io/tools/swagger-ui/[Swagger UI] to allow developers to visualize the APIs and test them interactively. The great part about this integration is that the UI is automatically generated from your OpenAPI specification. |
| 47 | + |
| 48 | +== MicroProfile OpenAPI and Open Liberty |
| 49 | + |
| 50 | +For Open Liberty developers, the link:https://microprofile.io/specifications/open-api/[MicroProfile OpenAPI] library can be used to integrate and make use of the OpenAPI specification. As well as enabling the documentation standards offered through the OpenAPI specification, MicroProfile OpenAPI also eliminates some of the need for additional manual effort by offering the ability to automatically generate OpenAPI-compliant documentation for JAX-RS services, saving even more time and effort! Making use of MicroProfile OpenAPI, Open Liberty developers are able to maintain consistent, accurate, and up-to-date API documentation. |
| 51 | + |
| 52 | +Additionally, MicroProfile OpenAPI can be used seamlessly with the Swagger UI to enhance the developer and user experience by providing interactive API documentation, allowing users to visualise endpoints, test API calls, and understand request/response structures in a more intuitive way. This removes the need for manually written API documentation, reducing maintenance overhead and minimising the risk of outdated or inconsistent documentation. |
| 53 | + |
| 54 | +In summary, MicroProfile OpenAPI streamlines API development in Open Liberty, making it easier for teams to build, expose, and manage RESTful services efficiently. |
| 55 | + |
| 56 | +== Adding MicroProfile OpenAPI to Open Liberty |
| 57 | + |
| 58 | + |
| 59 | +. Set up Java |
| 60 | + * Install JDK 8 or later. |
| 61 | + * Set the `JAVA_HOME` environment variable. |
| 62 | + ** Linux/macOS: `export JAVA_HOME=/path/to/jdk` |
| 63 | + ** Windows: `set JAVA_HOME=C:\path\to\jdk` |
| 64 | + |
| 65 | +. Download a sample Open Liberty Project |
| 66 | + * Go to the link:https://openliberty.io/start/[Open Liberty starter page]. |
| 67 | + * Choose the appropriate release and download the `.zip` file. |
| 68 | + |
| 69 | +. Extract the files |
| 70 | + * Extract the downloaded `.zip` file to your preferred directory. |
| 71 | + |
| 72 | +. Add MicroProfile dependency in `pom.xml` |
| 73 | ++ |
| 74 | +[source,xml] |
| 75 | +---- |
| 76 | +<dependency> |
| 77 | + <groupId>org.eclipse.microprofile</groupId> |
| 78 | + <artifactId>microprofile</artifactId> |
| 79 | + <version>7.0</version> |
| 80 | + <type>pom</type> |
| 81 | + <scope>provided</scope> |
| 82 | +</dependency> |
| 83 | +---- |
| 84 | +. Update `server.xml` in `liberty/config` to enable MicroProfile: (`microprofile-7.0` includes `mpOpenAPI-4.0` feature) |
| 85 | ++ |
| 86 | +[source,xml] |
| 87 | +---- |
| 88 | +<featureManager> |
| 89 | + <feature>jakartaee-10.0</feature> |
| 90 | + <feature>microprofile-7.0</feature> |
| 91 | +</featureManager> |
| 92 | +---- |
| 93 | +. Create an Endpoints.java file, |
| 94 | +* Define your API endpoints and add MicroProfile OpenAPI annotations. For example: |
| 95 | ++ |
| 96 | +[source,java] |
| 97 | +---- |
| 98 | +import org.eclipse.microprofile.openapi.annotations.Operation; |
| 99 | +import org.eclipse.microprofile.openapi.annotations.responses.APIResponse; |
| 100 | +import jakarta.ws.rs.GET; |
| 101 | +import jakarta.ws.rs.Path; |
| 102 | +import jakarta.ws.rs.Produces; |
| 103 | +import jakarta.ws.rs.core.MediaType; |
| 104 | +
|
| 105 | +@Path("/hello") |
| 106 | +public class Endpoints { |
| 107 | +
|
| 108 | + @GET |
| 109 | + @Produces(MediaType.TEXT_PLAIN) |
| 110 | + @Operation(summary = "Returns a greeting message") |
| 111 | + @APIResponse(responseCode = "200", description = "Successful response") |
| 112 | + public String hello() { |
| 113 | + return "Hello, OpenAPI with Liberty!"; |
| 114 | + } |
| 115 | +} |
| 116 | +---- |
| 117 | + |
| 118 | +. Run the project using Maven |
| 119 | +* Execute: `mvn liberty:dev` |
| 120 | + |
| 121 | +. Test using Swagger UI |
| 122 | +* Open: http://localhost:9080/openapi/ui/ |
| 123 | + |
| 124 | +For a fully functional example, check out this link:https://github.com/sweettypdevassy/openAPI-blog[GitHub Repository]. This blog will use this example project for further explanations. |
| 125 | + |
| 126 | +This is how it appears on the Swagger UI |
| 127 | +[.img_border_light] |
| 128 | +image::img/blog/OPENAPI-1.png[Swagger UI ,width=70%,align="center"] |
| 129 | + |
| 130 | +== MicroProfile OpenAPI Annotations |
| 131 | + |
| 132 | +MicroProfile OpenAPI provides the following annotations: |
| 133 | + |
| 134 | +.MicroProfile OpenAPI Annotations |
| 135 | +[options="header"] |
| 136 | +|=== |
| 137 | +| Annotation | Purpose |
| 138 | + |
| 139 | +| @OpenAPIDefinition | Defines API metadata like title, version, description, and contact details. |
| 140 | +| @Info | Provides API information (title, version, description, contact, license). |
| 141 | +| @Server | Specifies the server where the API is hosted. |
| 142 | +| @Tag | Categorises API operations into different groups. |
| 143 | +| @Operation | Describes an API endpoint operation. |
| 144 | +| @APIResponse | Defines responses for an API operation. |
| 145 | +| @APIResponses | Groups multiple @APIResponse annotations. |
| 146 | +| @Parameter | Defines a parameter in an API request. |
| 147 | +| @SecurityRequirement | Specifies security requirements for an endpoint. |
| 148 | +| @Schema | Defines the structure of request and response models. |
| 149 | +|=== |
| 150 | + |
| 151 | +Below is an example of using MicroProfile OpenAPI annotations to define an API, its metadata, security, and operations. |
| 152 | + |
| 153 | +*1 . API Metadata Definitions* |
| 154 | + |
| 155 | +These annotations should used with a REST Application class. |
| 156 | + |
| 157 | +* *`@OpenAPIDefinition`* - Defines metadata for the entire API. |
| 158 | + |
| 159 | +* *`@Info`* - Provides metadata such as title, description, version, and contact details. |
| 160 | + |
| 161 | +* *`@Server`* - Specifies one or more servers where the API is hosted. |
| 162 | + |
| 163 | +* *`@Tag`* - Defines logical groupings of endpoints. |
| 164 | + |
| 165 | +* *`@SecurityRequirement`* - Documentation for security (e.g., JWT authentication) of API endpoints. |
| 166 | + |
| 167 | +[source, java ] |
| 168 | +---- |
| 169 | +@OpenAPIDefinition( |
| 170 | + info = @Info( |
| 171 | + title = "Blog API", |
| 172 | + version = "1.0", |
| 173 | + description = "This is an example API using MicroProfile OpenAPI", |
| 174 | + contact = @Contact(name = "Sweetty", email = "[email protected]"), |
| 175 | + license = @License(name = "Apache 2.0", url = "https://apache.org/licenses/LICENSE-2.0.html") |
| 176 | + ), |
| 177 | + servers = @Server(url = "http://localhost:9080/openapi-demo", description = "Localhost Server"), |
| 178 | + tags = { |
| 179 | + @Tag(name = "Blog", description = "Operations related to blog management") |
| 180 | + }, |
| 181 | + security = @SecurityRequirement(name = "jwtAuth") |
| 182 | +) |
| 183 | +public class Endpoints extends Application { |
| 184 | +---- |
| 185 | +[.img_border_light] |
| 186 | +image::img/blog/OPENAPI-3.png[API Metadata Definitions ,width=70%,align="center"] |
| 187 | + |
| 188 | +*2 . Security Definitions* |
| 189 | + |
| 190 | +These annotations should used with a REST Application class. |
| 191 | + |
| 192 | +* *`@SecurityScheme`* - Defines authentication for the API. |
| 193 | + |
| 194 | +* *`@SecuritySchemes`*- Specifies multiple security schemes if needed. |
| 195 | + |
| 196 | +[source, java] |
| 197 | +---- |
| 198 | +@SecuritySchemes({ |
| 199 | + @SecurityScheme( |
| 200 | + securitySchemeName = "jwtAuth", |
| 201 | + description = "JWT Authentication", |
| 202 | + type = SecuritySchemeType.HTTP, |
| 203 | + scheme = "bearer", |
| 204 | + bearerFormat = "JWT" |
| 205 | + ) |
| 206 | +}) |
| 207 | +public class Endpoints extends Application { |
| 208 | +---- |
| 209 | +[.img_border_light] |
| 210 | +image::img/blog/OPENAPI-4.png[Security Definitions ,width=70%,align="center"] |
| 211 | +*3 . API Operations* |
| 212 | + |
| 213 | +These annotations should be used with REST resource methods. |
| 214 | + |
| 215 | +* *`@Operation`* - Describes an API operation. |
| 216 | + |
| 217 | +* *`@APIResponse`* - Defines possible responses for an operation. |
| 218 | + |
| 219 | +* *`@ApiResponses`* - Groups multiple @APIResponse annotations. |
| 220 | + |
| 221 | +* *`@Content`* - Specifies the media type and structure of request/response bodies. |
| 222 | + |
| 223 | +* *`@Schema`* - Defines the properties of a model used in API requests and responses. |
| 224 | + |
| 225 | +[source, java] |
| 226 | +---- |
| 227 | +@GET |
| 228 | +@Path("/user/{id}") |
| 229 | +@Produces(MediaType.APPLICATION_JSON) |
| 230 | +@Tag(name = "Blog") |
| 231 | +@Operation(summary = "Get User by ID", description = "Returns the user details for a given ID") |
| 232 | +@APIResponses({ |
| 233 | +@APIResponse(responseCode = "200", description = "Successful Response", content = @Content( |
| 234 | + mediaType = MediaType.APPLICATION_JSON, schema = @Schema(implementation = User.class) |
| 235 | +)), |
| 236 | +@APIResponse(responseCode = "404", description = "User not found")}) |
| 237 | +public User getUser( |
| 238 | +---- |
| 239 | +[.img_border_light] |
| 240 | +image::img/blog/OPENAPI-5.png[API Operations ,width=70%,align="center"] |
| 241 | +[.img_border_light] |
| 242 | +image::img/blog/OPENAPI-6.png[API Operations Response ,width=70%,align="center"] |
| 243 | + |
| 244 | +*4 . Request Parameter Definitions* |
| 245 | + |
| 246 | +This annotation should be used with REST resource method parameters. |
| 247 | + |
| 248 | +* *`@Parameter`* - Describes request parameters. |
| 249 | + |
| 250 | +[source, java] |
| 251 | +---- |
| 252 | +public User getUser( |
| 253 | + @Parameter(description = "User ID", required = true) |
| 254 | + @PathParam("id") String id) { |
| 255 | + |
| 256 | + return new User(id, "John Doe"); |
| 257 | +} |
| 258 | +---- |
| 259 | +[.img_border_light] |
| 260 | +image::img/blog/OPENAPI-7.png[Request Parameter Definitions ,width=70%,align="center"] |
| 261 | +*5 . Schema Definitions* |
| 262 | + |
| 263 | +This annotation should be defined on a Schema class. |
| 264 | + |
| 265 | +* *`@Schema`* at the `class level` provides metadata for the model. |
| 266 | + |
| 267 | +* *`@Schema`* at the `field level` describes each property of the model. |
| 268 | + |
| 269 | +[source, java] |
| 270 | +---- |
| 271 | +@Schema(description = "User model") |
| 272 | +class User { |
| 273 | + @Schema(description = "Unique user ID", example = "123") |
| 274 | + public String id; |
| 275 | + |
| 276 | + @Schema(description = "User name", example = "John Doe") |
| 277 | + public String name; |
| 278 | +---- |
| 279 | + |
| 280 | +[.img_border_light] |
| 281 | +image::img/blog/OPENAPI-8.png[Schema Definitions ,width=70%,align="center"] |
| 282 | + |
| 283 | +While basic API documentation is automatically generated from REST methods in Open Liberty, MicroProfile OpenAPI annotations help enhance and refine it. This is similar to how Javadoc comments work in Java—without them, Javadoc can still list methods, parameters, and return types, but it lacks detailed explanations of behavior and usage. Likewise, MicroProfile OpenAPI annotations provide essential context to REST endpoints, describing their purpose, expected inputs, responses, and error handling. Additionally, some API details cannot be inferred directly from Java code, such as custom response headers, security requirements, or detailed descriptions of parameters. In such cases, annotations become essential for ensuring comprehensive, well-structured API documentation that is both developer-friendly and machine-readable. |
| 284 | + |
| 285 | +The MicroProfile OpenAPI feature is responsible for generating this documentation. This eliminates the need for external configuration files and ensures the documentation evolves alongside the codebase. |
| 286 | + |
| 287 | +Ultimately, MicroProfile OpenAPI annotations play a vital role in creating useful, up-to-date documentation. Because they reside within the source code, they make it easier for teams to maintain alignment between implementation and documentation—benefiting both developers and end users who need to understand how to interact with the API effectively. |
| 288 | + |
| 289 | +== Influence |
| 290 | +As API architectures evolve, OpenAPI, the industry-standard specification for documenting REST APIs, is influencing how other tools' and specifications' APIs handle documentation and interoperability. Among those being influenced are link:https://graphql.org/learn/[GraphQL] and link:https://grpc.io/[gRPC]. GraphQL is a query language for your API, and a server-side runtime for executing queries using a type system you define for your data. gRPC is a modern open source high performance Remote Procedure Call (RPC) framework that can run in any environment. It can efficiently connect services in and across data centers with pluggable support for load balancing, tracing, health checking and authentication. While OpenAPI was designed for REST, its structured approach to API documentation, tooling, and automation has influenced how GraphQL and gRPC handle documentation and interoperability. |
| 291 | + |
| 292 | +* OpenAPI’s structured JSON/YAML format has influenced GraphQL’s SDL (Schema Definition Language), where types, queries, and mutations are explicitly defined. |
| 293 | + |
| 294 | +* Tools like Swagger UI, which originated alongside the Swagger project and now commonly accompany OpenAPI specifications, have inspired similar tools in other ecosystems. For example, gRPC UI offers an interactive interface to explore and test gRPC methods, much like Swagger UI does for REST APIs—though both Swagger UI and gRPC UI are independent, community-driven tools. |
| 295 | + |
| 296 | +== Conclusion |
| 297 | +In today's world of microservices and cloud computing, standardised API documentation is more important than ever. OpenAPI has become the foundation for creating consistent, accessible, and well-documented APIs, ensuring seamless integration across diverse systems. As APIs continue to evolve, having a structured approach to documentation helps developers improve collaboration, reduce errors, and accelerate development cycles. For those working with Open Liberty, exploring MicroProfile OpenAPI offers a way to generate OpenAPI-compliant documentation, making API management more efficient. As we embrace automation and interoperability in modern software development, OpenAPI will have an important role to play. |
| 298 | + |
| 299 | + |
| 300 | + |
| 301 | + |
| 302 | +Want to get hands-on with this and try it out in our own Open Liberty applications? |
| 303 | +Either follow along with our interactive guide, or, check out the documentation we have available too: |
| 304 | + |
| 305 | +* link:https://openliberty.io/guides/microprofile-openapi.html[Guide: Documenting RESTful APIs] |
| 306 | + |
| 307 | +* link:https://openliberty.io/docs/25.0.0.1/documentation-openapi.html[Docs: API documentation with OpenAPI] |
0 commit comments