diff --git a/modules/ROOT/pages/chapter04/chapter04.adoc b/modules/ROOT/pages/chapter04/chapter04.adoc
index a25f56a0..88e83865 100644
--- a/modules/ROOT/pages/chapter04/chapter04.adoc
+++ b/modules/ROOT/pages/chapter04/chapter04.adoc
@@ -2,81 +2,124 @@
:imagesdir: ../../assets/images
-== Introduction
+== Introduction
-In the previous chapter, we saw how RESTful APIs facilitate language-agnostic access to web services from diverse environments. However, a clear and comprehensive contract is required to ensure seamless integration between clients and services. This need for a well-defined API contract has led to the adoption of the OpenAPI specification.
-This chapter will explore the primary features of MicroProfile OpenAPI, demonstrate how to integrate it into your MicroProfile applications, and show you how to annotate your RESTful services to produce rich documentation that adheres to the OpenAPI specification. Furthermore, we will introduce the OpenAPI UI, a visual interface allowing developers and stakeholders to interact with and visualize the documented APIs, enhancing understanding and facilitating integration.
+In previous chapters, you built Restful (Representational State Transfer) APIs that various clients can use to access your web services regardless of programming language or platform. However, clients need a clear and comprehensive contract that describes available endpoints, expected parameters, and response formats to integrate seamlessly with these web services. Organizations adopt the OpenAPI Specification to provide this well-defined API contract.
+This chapter introduces MicroProfile OpenAPI and shows you how to document your RESTful services using OpenAPI annotations. You will learn to generate comprehensive API documentation that follows the OpenAPI Specification, then visualize and interact with your documented APIs using Swagger UI, a browser-based interface that makes your API contract immediately accessible to developers and stakeholders.
-== Topics to be covered:
-- Introduction to MicroProfile OpenAPI
-- API Specification using MicroProfile Open API
-- Generating API Documentation
-- Documenting Authentication and Authorization Requirements
-- Exploring the APIs using Swagger UI
+== What you will learn
+
+This chapter covers the following topics:
+
+* Understanding MicroProfile OpenAPI
+* Specifying APIs using MicroProfile OpenAPI
+* Generating API documentation
+* Documenting authentication and authorization
+* Exploring APIs using Swagger UI
+* Using new features in MicroProfile OpenAPI 4.1
== OpenAPI Specification
-The Open API Specification (OAS), formerly Swagger specification, is a technical specification that allows REST API providers to describe and publish their APIs using a format that various tools can consume. It defines a standard, language-agnostic interface to RESTful APIs, making it easy for third-party tools to generate documentation, client SDKs, and a range of tools that promote the seamless consumption of RESTful APIs.
+The OpenAPI Specification (OAS), formerly known as Swagger, defines a standard format for describing and publishing REST APIs. It provides a language-agnostic interface to RESTful APIs. API providers use OAS to create machine-readable documents that describe their endpoints, request and response schemas, authentication requirements, and other API characteristics. This standardization enables powerful tooling: Integrated Development Environments (IDEs) can automatically generate client code. Testing frameworks can then verify your API's functionality against its specification. Documentation tools can build interactive API explorers, all stemming from a single OpenAPI document.
-NOTE: The OpenAPI Initiative, a consortium of industry experts committed to standardizing how to describe REST APIs, maintains the OpenAPI Specification. It is a community-driven initiative, and many large organizations use it, including Google, Microsoft, and Amazon.
+[NOTE]
+====
+The OpenAPI Initiative (a Linux Foundation collaborative project) maintains the specification. Industry leaders including Google, Microsoft, and Amazon contribute to this community-driven standard, which ensures it meets enterprise requirements while remaining vendor-neutral.
+====
-The OpenAPI specification enables creation of a well-defined, clear and comprehensive API contract. It provides a standardized way to describe the API's structure, expected requests and responses, and authentication mechanisms, making it easier to develop, test, and maintain RESTful APIs.
+When you adopt OpenAPI, you create a single source of truth that serves as both human-readable documentation and a machine-parsable contract. This approach simplifies API development, testing, and long-term maintenance while making your API more accessible to consumers.
== Introduction to MicroProfile OpenAPI
-The MicroProfile OpenAPI specification builds upon the widely recognized OpenAPI Specification (OAS) and leverages annotations from the Jakarta Restful Web Services specification. The primary focus of MicroProfile OpenAPI is on defining REST APIs that utilize JSON within the context of HTTP.
+The MicroProfile OpenAPI specification integrates the OpenAPI Specification (OAS) with Jakarta RESTful Web Services, previously known as JAX-RS. It provides Java annotations that automatically generate OpenAPI documentation directly from your Java code. This annotation-driven approach offers several advantages:
+
+* Your documentation stays always synchronized with your codebase
+* You do not need to maintain and juggle between separate specification files
+* The OpenAPI output is generated automatically when your application is deployed
+* The standard Jakarta REST endpoints work without any modifications
+
+MicroProfile OpenAPI 4.0 supports OpenAPI Specification 3.1. This ensures your APIs are consistent, well-documented, and easily usable across a variety of development tools, testing frameworks, and API consumers.
-The specification aims to provide a uniform way of describing APIs so that they are both human-readable and machine-readable. It facilitates the creation of APIs that are consistent, well-documented, and easily consumable by both humans and machines.
+== Capabilities of MicroProfile OpenAPI
-== Capabilities of MicroProfile OpenAPI Specification
+MicroProfile OpenAPI provides a set of annotations and APIs that allow you to generate OpenAPI 3.1-compliant specifications directly from your Jakarta REST code. Instead of manually writing YAML (YAML Ain't Markup Language) or JSON (JavaScript Object Notation) specification files, you document your API using Java annotations, and MicroProfile OpenAPI generates the complete specification automatically.
-MicroProfile OpenAPI provides a suite of Java APIs that allows developers to define and generate API specifications that adhere to OpenAPI v3 standards. As a result, it simplifies the process of designing, documenting, and publishing RESTful APIs for developers.
+The specification supports the full range of OpenAPI features:
-Developers can quickly generate documentation for their microservices using MicroProfile OpenAPI. The documentation includes information on what services are provided, how to invoke them, and what data types are used. It generates comprehensive metadata about services, ensuring interoperability across diverse platforms and tools. Also, documentation can generate client code to access the web services.
+* Document endpoints: operations, parameters, request and response schemas, and examples
+* Specify API metadata: versioning, contact information, license details, and servers
+* Define data models: reusable schemas for your domain objects
+* Document authentication: security requirements and schemes
+* Describe responses: success and error responses with status codes
-The OpenAPI Specification fuels a rich ecosystem of tools that automate and support. This specification streamlines the creation of OpenAPI documentation for RESTful services using a unified approach. It generates comprehensive metadata about services, ensuring interoperability across diverse platforms and tools:
+Your generated OpenAPI specification enables a rich ecosystem of tools. Documentation portals like Swagger UI create interactive API explorers. Code generators produce client libraries in multiple languages. Testing frameworks validate requests and responses against your specification. Mock servers simulate your API for development and testing.
-* *API Documentation Generation*: Intuitive interactive documentation portals emerge directly from the specification.
-* *Client SDK Creation*: Client libraries in various languages can be automatically generated.
-* *API Testing*: Testing frameworks can leverage the specification to design robust tests.
-* *API Mocking*: Simplifies mocking APIs for testing and development purposes.
+MicroProfile OpenAPI ensures your documentation stays synchronized with your implementation, which eliminates the common problem of outdated API specifications.
== Generating OpenAPI documents
-There are multiple ways in which you can generate OpenAPI documents. The most common way is to use annotations. This only requires augmenting your Jakarta Restful Web Services annotations with OpenAPI annotations.
+MicroProfile OpenAPI provides multiple approaches to generate OpenAPI documentation. You can use annotations, static files, or a combination of both to create comprehensive API specifications.
+
+=== Annotation-based generation
+
+Add annotations to your Jakarta REST resources to generate documentation with MicroProfile OpenAPI. This annotation-driven approach keeps your documentation synchronized with your code. When you update an endpoint, you update its documentation at the same time.
+
+Annotate your Jakarta REST classes and methods with OpenAPI annotations. MicroProfile OpenAPI scans your application at deployment time, discovers annotated endpoints, and generates a complete OpenAPI specification automatically.
+
+This approach offers several benefits:
+
+* Documentation lives alongside the code it describes
+* IDE support for autocomplete and validation
+* Compile-time checking ensures annotations remain valid
+* No separate specification files to maintain
+
+=== Static OpenAPI files (optional)
+
+You can also provide a static OpenAPI document in `.yaml` or `.json` format at `META-INF/openapi.yaml` or `META-INF/openapi.json`. MicroProfile OpenAPI will merge this static content with the generated specification, which allows you to:
+
+* Add API-level metadata (title, version, contact information)
+* Define reusable schemas or security schemes
+* Override generated documentation for specific endpoints
+
+However, for most applications, annotations alone provide sufficient documentation.
+
+=== Selective documentation
-Besides annotations, a predefined OpenAPI document may be provided in either YAML or JSON format. This so-called static model will be merged with the model generated by scanning for Jakarta REST endpoints and the combined result will be made available to clients. However, the annotation-based approach is recommended as it is more maintainable and easier to understand. Finally, you can filter out the resources you do not want to document using configuration.
+Use the `mp.openapi.scan.exclude.packages` and `mp.openapi.scan.exclude.classes` configuration properties to exclude specific resources from documentation. This approach proves useful for internal or administrative endpoints you do not want to expose in your public API specification.
-== Using MicroProfile Open API in your project
+=== Documentation sources
-To document Jakarta RESTful Web Services using MicroProfile OpenAPI, we need to annotate the resource classes and methods with the OpenAPI annotation.
+MicroProfile OpenAPI merges documentation from multiple sources. Annotations override static files, and configuration properties can override both. Use filters to programmatically modify the final specification.
-To use MicroProfile OpenAPI in your project, you need to add the following maven coordinates to your project:
+== Using MicroProfile OpenAPI in your project
+
+To use MicroProfile OpenAPI in your project, add the following Maven coordinates:
[source, xml]
----
org.eclipse.microprofile.openapi
microprofile-openapi-api
- 3.1.1
+ 4.1
+ provided
----
-Below is an illustrative example of how you might annotate a method in the `ProductResource` class to achieve this documentation using MicroProfile OpenAPI annotations:
+[NOTE]
+====
+Use `provided` because your MicroProfile runtime already includes the implementation.
+====
+
+== Basic annotation example
+
+To document Jakarta RESTful Web Services using MicroProfile OpenAPI, annotate your resource classes and methods with OpenAPI annotations.
+
+The following example shows how to annotate a method in the `ProductResource` class:
[source, java]
----
-import org.eclipse.microprofile.openapi.annotations.Operation;
-import org.eclipse.microprofile.openapi.annotations.media.Content;
-import org.eclipse.microprofile.openapi.annotations.media.Schema;
-import org.eclipse.microprofile.openapi.annotations.responses.APIResponse;
-import org.eclipse.microprofile.openapi.annotations.responses.APIResponses;
-
-import jakarta.ws.rs.GET;
-import jakarta.ws.rs.Path;
-import jakarta.ws.rs.Produces;
-import jakarta.ws.rs.core.MediaType;
+// ...
@ApplicationScoped
@Path("/products")
@@ -88,236 +131,618 @@ public class ProductResource {
@GET
@Produces(MediaType.APPLICATION_JSON)
@Operation(summary = "List all products", description = "Retrieves a list of all available products")
- @APIResponses(value = {
- @APIResponse(
- responseCode = "200",
- description = "Successful, list of products found",
- content = @Content(mediaType = "application/json",
- schema = @Schema(implementation = Product.class))
- ),
- @APIResponse(
- responseCode = "400",
- description = "Unsuccessful, no products found",
- content = @Content(mediaType = "application/json")
+ @APIResponse(
+ responseCode = "200",
+ description = "Successful, list of products found",
+ content = @Content(
+ mediaType = "application/json",
+ schema = @Schema(implementation = Product.class)
)
- })
+ ),
+ @APIResponse(
+ responseCode = "400",
+ description = "Unsuccessful, no products found",
+ content = @Content(mediaType = "application/json")
+ )
public List getAllProducts() {
// Method implementation
}
}
----
-Explanation:
+The annotations provide the following documentation:
+
+* `@Tag`: Groups related endpoints together in the documentation
+* `@Operation`: Describes what the endpoint does
+* `@APIResponse`: Defines a specific response with status code and content
+* `@Content`: Specifies the response media type and structure
+* `@Schema`: References the data model returned (in this case, `Product.class`)
-* `@Operation`: Provides a summary and description for the `getProducts()` method.
+[NOTE]
+====
+The `@APIResponse` annotation is repeatable, which means you can apply it multiple times to document different response codes. You only need the `@APIResponses` wrapper annotation when using the `extensions` field to add vendor-specific metadata to all responses.
+====
-* `@APIResponse`: Describes the possible responses from the `getProducts()` operation. In this case, a successful response (HTTP 200) is described, indicating that the method returns an array of Product entities.
+These annotations enrich the `ProductResource` class with metadata necessary for generating comprehensive OpenAPI documentation automatically.
-* `@Schema`: Specifies the schema of the response content. Here, it is used to indicate that the method returns an array of Product objects.
+[NOTE]
+====
+Annotation scanning is enabled by default. If you need to disable it, you can set `mp.openapi.scan.disable=true` in your `microprofile-config.properties` file.
+====
-These annotations enrich the `ProductResource` class with metadata necessary for generating comprehensive and descriptive OpenAPI documentation automatically.
+Build and run the application.
-We have also annotated the `getProducts()` method with the @APIResponse annotation to document the successful response from the operation. The `responseCode` field is used to specify the status code of the response, and the `description` field is used to provide a brief description of the response. There are two possible responses – a successful response containing a list of produdts with a 200 status code, and an unsuccessful response with a 400 status code, if no products are found. The content field is used to specify the schema of the response content. In this example, the response content is a list of `Product`s.
+== Viewing the generated documentation
-Finally, we need to add the following property to the src/main/resources/META-INF/microprofile-config.properties file:
+To view the generated documentation, use the OpenAPI endpoint. Access the OpenAPI specification at the following URL:
+[source]
----
-mp.openapi.scan=true
+http://:/openapi/
----
-This property tells MicroProfile OpenAPI to scan our classes for annotations and generate API documentation for them.
+Replace `` and `` with the actual hostname and port used by your runtime (for example, `localhost:9080`).
-Now that we have configured MicroProfile OpenAPI, we can build and run our application.
+The `/openapi` endpoint returns the OpenAPI specification generated from the annotations in your source code. By default, it returns the specification in YAML format.
-== How to view the generated documentation
+To receive the specification in JSON format instead, you can:
-To view the generated documentation, we can use the OpenAPI UI tool. The Open API UI tool is a web-based tool that can be used to view the documentation for a REST API.
-
-The OpenAPI UI tool can be accessed at the following URL:
+* Set the `Accept` HTTP header to `application/json`:
++
+[source, bash]
+----
+curl -H "Accept: application/json" http://localhost:9080/openapi
+----
+* Use the `format` query parameter:
++
+[source]
----
-http://localhost:/openapi/
+http://localhost:9080/openapi?format=JSON
----
-Replace `` with the actual port used by your runtime, for e.g. 9080 which is the default port at Open Liberty server.
+[NOTE]
+====
+**Context root behavior:**
+
+The `/openapi` endpoint is provided at the root of the server, not relative to your application's context path. If your application is deployed with a context root (e.g., `/myapp`), the OpenAPI endpoint remains at `/openapi`, not `/myapp/openapi`.
-The `/openapi` endpoint is used to get information about the OpenAPI specification generated from the comments in the source code annotations. It returns information in YAML format.
+However, the generated OpenAPI document will include server URLs that reflect your application's deployment context. For example, if you define `@ApplicationPath("/api")` and deploy to context `/myapp`, the server URL in the generated spec will be `/myapp/api`.
+====
-When we access the `http://localhost:5050/openapi` URL, we should see the API documentation that was generated by MicroProfile OpenAPI:
+When you access the `\http://localhost:9080/openapi` URL, you see the API documentation that MicroProfile OpenAPI generated:
[source, yaml]
----
-openapi: 3.0.3
-info:
- title: Generated API
- version: "1.0"
-servers:
-- url: http://localhost:9080/catalog
-paths:
- /api/products:
- get:
- responses:
- "200":
- description: OK
- content:
- application/json:
- schema:
- type: array
- items:
- $ref: '#/components/schemas/Product'
- put:
- requestBody:
- content:
- application/json:
- schema:
- $ref: '#/components/schemas/Product'
- responses:
- "200":
- description: OK
- post:
- requestBody:
- content:
- application/json:
- schema:
- $ref: '#/components/schemas/Product'
- responses:
- "200":
- description: OK
- /api/products/products/{id}:
- delete:
- parameters:
- - name: id
- in: path
- required: true
- schema:
- format: int64
- type: integer
- responses:
- "200":
- description: OK
- /api/products/{id}:
- get:
- parameters:
- - name: id
- in: path
- required: true
- schema:
- format: int64
- type: integer
- responses:
- "200":
- description: OK
- content:
- application/json:
- schema:
- $ref: '#/components/schemas/Product'
+openapi: 3.1.0
components:
schemas:
Product:
- required:
- - name
- - description
- - price
type: object
properties:
id:
- format: int64
type: integer
+ format: int64
name:
type: string
description:
type: string
price:
- format: double
type: number
+ format: double
+info:
+ title: Generated API
+ version: "1.0"
+paths:
+ /api/products:
+ get:
+ summary: List all products
+ description: Retrieves a complete list of products in the catalog.
+ tags:
+ - Products
+ responses:
+ "200":
+ description: Successfully retrieved product list
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Product'
+ "500":
+ description: Internal server error
+tags:
+- name: Products
+ description: Product catalog operations
+servers:
+- url: https://localhost:5050/mp-ecomm-store
----
-As we can see, MicroProfile OpenAPI has generated API documentation for our resource class. We can use this documentation to learn about the API and how to use it.
+MicroProfile OpenAPI generates API documentation for your resource class. You can use this documentation to learn about the API and how to use it. This documentation includes the following information:
+
+* The `/products` endpoint description
+* The GET operation summary and details
+* Expected response codes (200, 500)
+* The JSON structure of the Product response
+* Grouping under the Products tag
-MicroProfile OpenAPI allows developers to produce these specifications directly from their codebase, leveraging annotations and/or providing OpenAPI documents statically. This direct generation ensures that the API documentation is always up to date with the code.
+MicroProfile OpenAPI allows developers to produce these specifications directly from their codebase by using annotations or providing OpenAPI documents statically. This direct generation ensures that the API documentation remains synchronized with the code.
-== Exploring the APIs using Swagger UI
+Visualization tools like Swagger UI can render this specification, client generators can consume it, and testing frameworks can use it for validation.
-To open Swagger UI for the API documentation generated using MicroProfile OpenAPI, you will need to deploy your application to a server that supports MicroProfile, such as Open Liberty, WildFly, Quarkus, or Payara Micro. These servers automatically generate the OpenAPI documentation for your RESTful services based on the annotations in your code.
+== Exploring APIs using Swagger UI
-Next, visit the following URL to launch the Swagger UI:
+To open Swagger UI for the API documentation generated using MicroProfile OpenAPI, deploy your application to a server that supports MicroProfile, such as Open Liberty, WildFly, Quarkus, or Payara Micro. These servers automatically generate the OpenAPI documentation for your RESTful services based on the annotations in your code.
+
+Visit the following URL to launch Swagger UI:
----
http://localhost:9080/openapi/ui
----
-Swagger UI is then used to render this documentation in a user-friendly web interface. Below is the screenshot of swagger UI for the Product REST Resource.
+Swagger UI renders this documentation in a user-friendly web interface. The following figure shows the Swagger UI for the Product REST resource.
-:figure-caption: Swagger UI
-.Swagger UI
-image::figure4-1.png[MicroProfile OpenAPI]
+.Swagger UI displaying the Product Catalog API
+image::figure4-1.png[Swagger UI interface showing Product API endpoints,800]
== Annotations
-The MicroProfile OpenAPI annotations can be used to document any Jakarta Restful Web Services resource. The annotations can also be used in conjunction with other Jakarta Restful Webservices annotations, such as @Path and @Produces. The most common annotations that are used to document RESTful web services are list in Table 4-1.
+You can use MicroProfile OpenAPI annotations to document any Jakarta RESTful Web Services resource. You can also use the annotations with other Jakarta RESTful Web Services annotations, such as `@Path` and `@Produces`. Table 4-1 lists the most common annotations used to document RESTful web services.
+.MicroProfile OpenAPI annotations for documenting Jakarta REST resources
[cols="1,3", options="header"]
|===
-| Annotations | Details
+| Annotation | Description
-| @OpenAPIDefinition
+| `@OpenAPIDefinition`
| Provides metadata about the entire API. It can include information such as the title, description, version, terms of service, and contact information.
-| @Info
-| Used inside @OpenAPIDefinition to provide API metadata like title, version, description.
+| `@Info`
+| Used inside `@OpenAPIDefinition` to provide API metadata like title, version, and description.
-| @Contact
-| Specifies contact information for the API, used within @Info.
+| `@Contact`
+| Specifies contact information for the API, used within `@Info`.
-| @License
-| Defines the license information for the API, also used within @Info.
+| `@License`
+| Defines the license information for the API, also used within `@Info`.
-| @Operation
+| `@Operation`
| Describes a single API operation on a resource.
-| @APIResponse
-| It is used to document a response from an operation.
+| `@APIResponse`
+| Documents a response from an operation.
+
+| `@APIResponses`
+| A container for multiple `@APIResponse` annotations, allowing documentation of different responses for a single API operation.
-| @APIResponses
-| A container for multiple @APIResponse annotations, allowing documentation of different responses for a single API operation.
+| `@RequestBody`
+| Describes the request body of an HTTP request, specifying the content of the body and whether it is required. In MicroProfile OpenAPI 4.0 and later, request bodies are required by default (`required=true`). To make a request body optional, explicitly set `required=false`. Note: If migrating from earlier versions, review your API documentation to ensure optional request bodies are explicitly marked as `required=false`.
-| @RequestBody
-| Describes the request body of an HTTP request, specifying the content of the body and whether it is required.
+| `@RequestBodySchema`
+| Convenience annotation that simplifies documenting request bodies. Instead of using `@RequestBody` with nested `@Content` and `@Schema`, you can directly specify the implementation class: `@RequestBodySchema(MyClass.class)`.
-| @Schema
+| `@APIResponseSchema`
+| Convenience annotation for documenting responses. Instead of using `@APIResponse` with nested `@Content` and `@Schema`, you can directly specify the response code and implementation class: `@APIResponseSchema(responseCode = "200", value = MyClass.class)`.
+
+| `@SchemaProperty`
+| Allows defining properties within a `@Schema` annotation without creating separate classes. Useful for inline property definitions.
+
+| `@Schema`
| Provides schema details for a response or request body, specifying the data type, format, and constraints.
-| @Parameter
+| `@Parameter`
| Provides information on parameters to the operation, including query parameters, header parameters, and path parameters.
-| @Tag
-| Adds metadata to a single tag that is used by the Operation. It helps in categorizing operations by resources or any other qualifier.
+| `@Tag`
+| Adds metadata to a single tag used by the operation. It helps in categorizing operations by resources or any other qualifier.
-| @Content
+| `@Content`
| Specifies the media type and schema of the operation's request or response body.
-| @Components
-| Allows the definition of reusable components such as schemas, responses, parameters, and more, which can be referenced by other annotations.
+| `@Components`
+| Allows the definition of reusable components such as schemas, responses, parameters, and more, which other annotations can reference.
-| @SecurityRequirement
-| Specifies a security requirement for an operation, referencing security schemes defined in the @Components.
+| `@SecurityRequirement`
+| Specifies a security requirement for an operation, referencing security schemes defined in `@Components`.
-| @ExternalDocumentation
+| `@ExternalDocumentation`
| Provides additional external documentation for an API or operation.
-| @Callback
+| `@Callback`
| Specifies a callback URL for an asynchronous operation.
-| @Callbacks
+| `@Callbacks`
| Specifies multiple `@Callback` annotations.
-| @Server
-| Describes a server that hosts the API, specifying URL and description, which can be global or specific to operations or paths
+| `@Server`
+| Describes a server that hosts the API, specifying URL and description, which can be global or specific to operations or paths.
+
+| `@PathItem`
+| Describes operations available at a specific path. Primarily used to document webhooks in `@OpenAPIDefinition` or to define reusable path items in the `@Components` section.
+
+| `@PathItemOperation`
+| Used within `@PathItem` to describe individual operations (GET, POST, etc.) for a path. Useful for webhook documentation.
+
+| `@DependentRequired`
+| Used within `@Schema` to specify properties that become required when another property is present. Implements JSON Schema's `dependentRequired` keyword.
+
+| `@DependentSchema`
+| Used within `@Schema` to specify additional validation rules that apply when a specific property is present. Implements JSON Schema's `dependentSchemas` keyword.
+
+| `@PatternProperty`
+| Used within `@Schema` to define validation rules for properties whose names match a regular expression. Implements JSON Schema's `patternProperties` keyword.
|===
-All of these annotations are defined in the org.eclipse.microprofile.openapi.annotations package.
+All of these annotations are defined in the `org.eclipse.microprofile.openapi.annotations` package.
+
+=== Convenience annotation examples
+
+MicroProfile OpenAPI 2.0 introduced convenience annotations that simplify common documentation patterns.
+
+==== Using @RequestBodySchema
+
+Instead of:
+
+[source, java]
+----
+@POST
+public Response createProduct(
+ @RequestBody(
+ description = "Product to create",
+ required = true,
+ content = @Content(
+ mediaType = MediaType.APPLICATION_JSON,
+ schema = @Schema(implementation = Product.class)
+ )
+ ) Product product) {
+ // Implementation
+}
+----
+
+You can use:
+
+[source, java]
+----
+import org.eclipse.microprofile.openapi.annotations.parameters.RequestBodySchema;
+
+@POST
+@RequestBodySchema(Product.class)
+public Response createProduct(Product product) {
+ // Implementation
+}
+----
+
+==== Using @APIResponseSchema
+
+Instead of:
+
+[source, java]
+----
+@GET
+@Path("/{id}")
+@APIResponse(
+ responseCode = "200",
+ description = "Product found",
+ content = @Content(
+ mediaType = MediaType.APPLICATION_JSON,
+ schema = @Schema(implementation = Product.class)
+ )
+)
+public Response getProduct(@PathParam("id") Long id) {
+ // Implementation
+}
+----
+
+You can use:
+
+[source, java]
+----
+import org.eclipse.microprofile.openapi.annotations.responses.APIResponseSchema;
+
+@GET
+@Path("/{id}")
+@APIResponseSchema(value = Product.class, responseCode = "200", responseDescription = "Product found")
+public Response getProduct(@PathParam("id") Long id) {
+ // Implementation
+}
+----
+
+==== Using @SchemaProperty
+
+For inline schema property definitions:
+
+[source, java]
+----
+import org.eclipse.microprofile.openapi.annotations.media.SchemaProperty;
+
+@Schema(
+ description = "Order summary",
+ properties = {
+ @SchemaProperty(
+ name = "orderId",
+ description = "Unique order identifier",
+ example = "ORD-12345"
+ ),
+ @SchemaProperty(
+ name = "total",
+ description = "Total order amount",
+ example = "99.99"
+ )
+ }
+)
+public class OrderSummary {
+ // Class implementation
+}
+----
+
+== Configuration properties
+
+MicroProfile OpenAPI provides configuration properties to control its behavior. Configure these properties in `microprofile-config.properties`.
+
+Common configuration properties include:
+
+* `mp.openapi.scan.exclude.packages` - Comma-separated list of packages to exclude from scanning
+* `mp.openapi.scan.exclude.classes` - Comma-separated list of classes to exclude from scanning
+* `mp.openapi.servers` - Comma-separated list of global server URLs
+* `mp.openapi.filter` - Fully qualified name of an OASFilter implementation class
+* `mp.openapi.model.reader` - Fully qualified name of an OASModelReader implementation class
+
+[NOTE]
+====
+Configuration property names are available as constants in the `org.eclipse.microprofile.openapi.OASConfig` class for type-safe access in Java code.
+====
+
+*Example: Exclude internal packages from scanning:*
+
+[source, properties]
+----
+mp.openapi.scan.exclude.packages=io.myapp.internal,io.myapp.admin
+----
+
+*Example: Configure custom servers:*
+
+[source, properties]
+----
+mp.openapi.servers=https://api.example.com/v1,https://api-staging.example.com/v1
+----
+
+== Features in MicroProfile OpenAPI 4.x
+
+MicroProfile OpenAPI 4.0 introduced support for OpenAPI Specification 3.1, and version 4.1 added clarifications and convenience methods.
+
+=== OpenAPI v3.1 specification support
+
+MicroProfile OpenAPI 4.0 supports OpenAPI v3.1, which aligns with JSON Schema 2020-12. This provides better interoperability with standard JSON Schema validators and tooling.
+
+==== Nullable type handling
+
+OpenAPI v3.1 uses JSON Schema's standard type arrays for nullable fields. Use `@Schema(nullable = true)` in your Java code, which generates `type: ["string", "null"]` in the specification:
+
+[source, java]
+----
+@Schema(description = "Optional description", nullable = true)
+private String description;
+----
+
+=== Support for Java records
+
+MicroProfile OpenAPI 4.1 supports Java records and automatically generates schema definitions from record components:
+
+[source, java]
+----
+@Schema(name = "Product", description = "Product information")
+public record Product(
+ @NotNull
+ @Schema(description = "Product ID")
+ Long id,
+
+ @NotNull
+ @Schema(description = "Product name")
+ String name,
+
+ @Schema(description = "Optional description", nullable = true)
+ String description
+) {}
+----
+
+Use `@NotNull` validation annotations to mark required fields. The generated schema includes proper type definitions, required fields, and descriptions from your record components.
+
+== Jakarta Bean Validation integration
+
+MicroProfile OpenAPI automatically processes Jakarta Bean Validation annotations and uses them to enhance the generated OpenAPI schemas. Common validation annotations include:
+
+* `@NotNull`, `@NotEmpty`, `@NotBlank` - Mark fields as required or with minimum constraints
+* `@Size(min, max)` - Set minimum and maximum length for strings, arrays, or objects
+* `@Min(value)`, `@Max(value)` - Set numeric range constraints
+* `@DecimalMin`, `@DecimalMax` - Set decimal range constraints with optional exclusive boundaries
+* `@Positive`, `@Negative` - Enforce positive or negative numeric values
+
+*Example:*
+
+[source, java]
+----
+public class Product {
+ @NotNull
+ @Positive
+ private Long id;
+
+ @NotBlank
+ @Size(min = 3, max = 100)
+ private String name;
+
+ @DecimalMin("0.01")
+ @DecimalMax("999999.99")
+ private BigDecimal price;
+}
+----
+
+The generated schema includes validation constraints such as `minimum`, `maximum`, `minLength`, `maxLength`, and `pattern` based on the annotations. Disable Bean Validation processing using `mp.openapi.scan.beanvalidation=false` if needed.
+
+== Documenting asynchronous operations with callbacks
+
+MicroProfile OpenAPI supports documenting callbacks—HTTP requests your API makes to client-provided URLs. This is useful for webhook notifications and asynchronous processing patterns.
+
+=== Using @Callback annotation
+
+Document callbacks using the `@Callback` annotation. The client provides a callback URL, and your API calls that URL when processing completes:
+
+[source, java]
+----
+@POST
+@Path("/process-async")
+@Operation(summary = "Process product asynchronously")
+@APIResponse(responseCode = "202", description = "Processing initiated")
+@Callback(
+ name = "productProcessed",
+ callbackUrlExpression = "{$request.body#/callbackUrl}",
+ operations = {
+ @CallbackOperation(
+ method = "post",
+ summary = "Product processing completed",
+ requestBody = @RequestBody(
+ description = "Processing result",
+ content = @Content(
+ mediaType = MediaType.APPLICATION_JSON,
+ schema = @Schema(implementation = ProcessResult.class)
+ )
+ )
+ )
+ }
+)
+public Response processProductAsync(AsyncProductRequest request) {
+ // Initiate async processing
+ return Response.accepted()
+ .entity("{\"message\": \"Processing initiated\"}")
+ .build();
+}
+----
+
+*Key elements:*
+
+* `callbackUrlExpression` - JSON Pointer to extract the callback URL from the request (e.g., `{$request.body#/callbackUrl}`)
+* `@CallbackOperation` - Defines the HTTP request your API will make to the client's URL
+* `method` - HTTP method for the callback (typically "post")
+* `requestBody` - Payload your API sends to the callback URL
+
+
+The callback pattern: (1) Client sends request with callback URL, (2) API responds immediately (202 Accepted), (3) API processes asynchronously, (4) API POSTs results to client's callback URL.
+
+== Using security schemes in OpenAPI documentation
+
+[IMPORTANT]
+====
+MicroProfile OpenAPI **documents** security requirements but does **not enforce** them. You must first implement access controls in your application using security frameworks (such as MicroProfile JWT, Jakarta Security, or your runtime's security features), and then use OpenAPI annotations to document how clients should authenticate with your API.
+====
+
+Security is a critical aspect of API documentation. MicroProfile OpenAPI 4.1 provides comprehensive support for documenting various security schemes including API keys, HTTP authentication, OAuth2, and OpenID Connect.
+
+=== Documenting security schemes
+
+Security schemes are defined at the application level using `@SecurityScheme` annotations:
+
+[source, java]
+----
+package io.microprofile.tutorial.store.product;
+
+// ...
+
+@ApplicationPath("/api")
+@OpenAPIDefinition(
+ info = @Info(
+ title = "Secured Product API",
+ version = "1.0.0",
+ description = "Product API with multiple security schemes"
+ )
+)
+@SecuritySchemes({
+ @SecurityScheme(
+ securitySchemeName = "bearer",
+ type = SecuritySchemeType.HTTP,
+ description = "JWT Bearer token authentication",
+ scheme = "bearer",
+ bearerFormat = "JWT"
+ )
+})
+public class ProductRestApplication extends Application {
+}
+----
+
+This example shows Bearer token authentication. You can define multiple security schemes including API keys, OAuth2, and OpenID Connect.
+
+==== Applying security to operations
+
+Apply security requirements to individual operations using `@SecurityRequirement`:
+
+[source, java]
+----
+@GET
+@Path("/{id}")
+@SecurityRequirement(name = "bearer")
+public Response getProduct(@PathParam("id") Long id) {
+ return Response.ok(productService.findById(id)).build();
+}
+----
+
+The generated OpenAPI document includes security requirements that describe how clients must authenticate. Swagger UI displays these requirements and allows users to provide credentials before testing secured endpoints.
+
+==== Security in Swagger UI
+
+When you view the documented API in Swagger UI, security schemes appear in several ways:
+
+* A lock icon (🔒) appears next to secured operations
+* An Authorize button allows testers to input credentials
+* Required scopes display for each operation
+* Operations can be tested with provided authentication
+
+This makes it easy for API consumers to understand authentication requirements and test secured endpoints interactively.
== Summary
-By integrating the MicroProfile OpenAPI, developers can generate detailed, OpenAPI-compliant documentation automatically, fostering better understanding and interaction among services. By annotating `ProductResource` class, we generated API documentation as per Open API specification. This will ensure the services are readily discoverable, understandable, and usable, thereby accelerating development cycles and fostering a more robust and collaborative developer ecosystem.
+In this chapter, you learned how MicroProfile OpenAPI 4.1 enables automatic generation of OpenAPI v3.1-compliant documentation for your RESTful web services.
+
+=== Core concepts
+
+You learned about the OpenAPI Specification, a standard, language-agnostic format for describing REST APIs. You discovered how MicroProfile OpenAPI integrates this specification with Jakarta REST through annotations that automatically generate documentation from your code, keeping your API contracts synchronized with your implementation.
+
+=== Key features demonstrated
+
+*Annotation-based documentation*
+
+You learned to document your RESTful endpoints using core OpenAPI annotations including `@Operation`, `@APIResponse`, `@Tag`, `@Content`, and `@Schema`. You saw how to apply these annotations to Jakarta REST resources to generate complete API specifications automatically.
+
+*Convenience annotations*
+
+You explored MicroProfile OpenAPI's convenience annotations that simplify common documentation tasks. You learned to use `@RequestBodySchema` to document request bodies concisely, `@APIResponseSchema` to document response types efficiently, and `@SchemaProperty` to define inline schema properties without creating separate classes.
+
+*Java records support*
+
+You explored how MicroProfile OpenAPI 4.1 provides native support for Java records, allowing you to use modern, immutable data carriers with automatic schema generation. You learned to combine `@Schema` annotations with `@NotNull` validation to create well-documented, type-safe data models.
+
+*Nullable type handling*
+
+You learned how MicroProfile OpenAPI 4.1 supports improved nullable type handling aligned with OpenAPI v3.1, using the `@Schema` annotation's `nullable` property to generate standard-compliant type arrays in the specification.
+
+*Jakarta Bean Validation integration*
+
+You discovered how validation annotations like `@NotNull`, `@Size`, `@Min`, and `@Max` automatically enhance your OpenAPI documentation, providing accurate constraints and requirements without duplicating information.
+
+*Asynchronous operations*
+
+You learned to document asynchronous operations using the `@Callback` annotation, showing how your API initiates async processing and notifies clients through webhook callbacks when operations complete.
+
+*Security documentation*
+
+You explored how to document security requirements using `@SecurityScheme` and `@SecurityRequirement` annotations. You learned to apply security at both the application and operation levels using Bearer token authentication as an example.
+
+*Viewing and testing APIs*
+
+You learned how to access your generated OpenAPI specification through the `/openapi` endpoint in both YAML and JSON formats. You discovered how to use Swagger UI at `/openapi/ui` to interactively explore and test your documented APIs in a browser-based interface.
+
+=== Configuration and customization
+
+You learned about MicroProfile OpenAPI configuration properties that control documentation behavior, including selective scanning to exclude internal endpoints and defining custom server URLs. You also learned about the option to provide static OpenAPI files that merge with generated documentation.
+
+=== Practical applications
+
+This annotation-driven approach keeps documentation synchronized with your implementation, avoiding the common problem of outdated specifications. The generated OpenAPI documents enable automatic client SDK generation, interactive API exploration via Swagger UI, integration with API gateways, contract testing frameworks, and API discovery in enterprise environments.
+
+Your APIs are now well-documented, standards-compliant, and easily discoverable by consumers.