Skip to content

Commit 2f545c8

Browse files
authored
Update chapter04.adoc
1 parent 03c1c2c commit 2f545c8

1 file changed

Lines changed: 21 additions & 254 deletions

File tree

modules/ROOT/pages/chapter04/chapter04.adoc

Lines changed: 21 additions & 254 deletions
Original file line numberDiff line numberDiff line change
@@ -164,7 +164,7 @@ These annotations enrich the `ProductResource` class with metadata necessary for
164164
Annotation scanning is enabled by default. If you need to disable it, you can set `mp.openapi.scan.disabled=true` in your `microprofile-config.properties` file.
165165
====
166166

167-
Build and run your application after configuring MicroProfile OpenAPI.
167+
Next, let us build and run the application.
168168

169169
== Viewing the generated documentation
170170

@@ -175,7 +175,7 @@ To view the generated documentation, use the OpenAPI endpoint. Access the OpenAP
175175
http://<hostname>:<port>/openapi/
176176
----
177177

178-
Replace `<hostname>` and `<port>` with the actual hostname and port used by your runtime (for example, `localhost:9080`, which is the default port for Open Liberty server).
178+
Replace `<hostname>` and `<port>` with the actual hostname and port used by your runtime (for example, `localhost:9080`).
179179

180180
The `/openapi` endpoint returns the OpenAPI specification generated from the annotations in your source code. It returns information in YAML format.
181181

@@ -461,174 +461,14 @@ components:
461461

462462
Use `@NotNull` validation annotations or `@Schema(required = true)` to explicitly mark components as required in the generated specification. For nullable components, you can either use `@Schema(nullable = true)` or wrap the type in `Optional<T>` to indicate they can accept null values. In this example, `@NotNull` annotations mark `id`, `name`, and `displayOrder` as required, while `parentId` is marked as nullable for root categories that have no parent.
463463

464-
=== Enhanced annotation type safety
465-
466-
MicroProfile OpenAPI 4.1 improves type safety by adding explicit `@Target` meta-annotations to several OpenAPI annotations. This enhancement works behind the scenes to help IDEs and build tools provide better warnings when you use annotations in inappropriate locations.
467-
468-
==== What this means for developers
469-
470-
The `@Target` meta-annotation defines where an annotation can be applied (classes, methods, fields, parameters, and so on). Prior to MicroProfile OpenAPI 4.1, some annotations lacked explicit `@Target` definitions, which made it harder for development tools to validate annotation usage.
471-
472-
With MicroProfile OpenAPI 4.1, annotations like `@Schema`, `@SchemaProperty`, and others now have explicit `@Target` constraints that:
473-
474-
* Provide warnings for incorrect annotation usage
475-
* Help build tools detect potential issues during compilation
476-
* Make the API more predictable and self-documenting
477-
* Improve code completion accuracy in modern IDEs
478-
479-
==== Example: Compile-time warnings for incorrect usage
480-
481-
Modern IDEs may provide warnings about improper annotation placement:
482-
483-
*Questionable usage:*
484-
[source, java]
485-
----
486-
@Schema(description = "Product resource") // IDE may warn: unusual location for @Schema
487-
@Path("/products")
488-
public class ProductResource {
489-
// While this compiles, the @Schema annotation on the resource class itself
490-
// may not have the intended effect
491-
}
492-
----
493-
494-
*Recommended usage:*
495-
[source, java]
496-
----
497-
@Path("/products")
498-
public class ProductResource {
499-
500-
@GET
501-
@Produces(MediaType.APPLICATION_JSON)
502-
@Operation(summary = "Get all products")
503-
@APIResponse(
504-
responseCode = "200",
505-
content = @Content(schema = @Schema(implementation = Product.class))
506-
)
507-
public List<Product> getAllProducts() {
508-
return productService.findAll();
509-
}
510-
}
511-
----
512-
513-
==== Working with flexible schema types
514-
515-
The enhanced type safety works seamlessly with flexible schema definitions:
516-
517-
*Example: Product with dynamic attributes*
518-
[source, java]
519-
----
520-
package io.microprofile.tutorial.store.product.entity;
521-
522-
import org.eclipse.microprofile.openapi.annotations.media.Schema;
523-
import org.eclipse.microprofile.openapi.annotations.media.SchemaProperty;
524-
import org.eclipse.microprofile.openapi.annotations.enums.SchemaType;
525-
import java.util.Map;
526-
import java.util.List;
527-
import lombok.Data;
528-
529-
@Data
530-
@Schema(
531-
description = "Product with flexible custom attributes",
532-
properties = {
533-
@SchemaProperty(name = "tags")
534-
}
535-
)
536-
public class FlexibleProduct {
537-
538-
@Schema(description = "Product ID", example = "1")
539-
private Long id;
540-
541-
@Schema(description = "Product name", example = "Wireless Mouse")
542-
private String name;
543-
544-
@Schema(description = "Product price", example = "29.99")
545-
private Double price;
546-
547-
@Schema(
548-
description = "Product specifications (e.g., color, material, size)",
549-
type = SchemaType.OBJECT,
550-
example = "{\"color\": \"black\", \"material\": \"plastic\", \"weight\": \"100g\"}"
551-
)
552-
private Map<String, Object> specifications;
553-
554-
@Schema(
555-
description = "Product tags for categorization and search",
556-
type = SchemaType.ARRAY,
557-
implementation = String.class,
558-
example = "[\"wireless\", \"electronics\", \"accessories\"]"
559-
)
560-
private List<String> tags;
561-
}
562-
----
563-
564-
The `@SchemaProperty` annotation allows you to reference properties at the class level, particularly useful when combined with field-level `@Schema` annotations.
565-
566-
*Generated OpenAPI schema:*
567-
[source, yaml]
568-
----
569-
FlexibleProduct:
570-
description: Product with flexible custom attributes
571-
properties:
572-
tags:
573-
description: Product tags for categorization and search
574-
type: array
575-
examples:
576-
- - wireless
577-
- electronics
578-
- accessories
579-
items:
580-
type: string
581-
id:
582-
type: integer
583-
format: int64
584-
description: Product ID
585-
examples:
586-
- 1
587-
name:
588-
type: string
589-
description: Product name
590-
examples:
591-
- Wireless Mouse
592-
price:
593-
type: number
594-
format: double
595-
description: Product price
596-
examples:
597-
- 29.99
598-
specifications:
599-
type: object
600-
additionalProperties: {}
601-
description: "Product specifications (e.g., color, material, size)"
602-
examples:
603-
- color: black
604-
material: plastic
605-
weight: 100g
606-
type: object
607-
----
608-
609-
==== Benefits of enhanced type safety
610-
611-
The addition of explicit `@Target` annotations provides:
612-
613-
* Early error detection: Misused annotations are caught at compile time, not runtime
614-
* Better IDE experience: Code completion only suggests annotations valid for the current context
615-
* Self-documenting API: Annotation definitions clearly communicate their intended use
616-
* Reduced debugging time: Fewer runtime errors related to incorrect annotation placement
617-
* More maintainable code: Clear constraints make it easier for teams to use annotations correctly
618-
619464
=== JSON Schema dialect support
620465

621-
MicroProfile OpenAPI 4.1 introduces the `jsonSchemaDialect` property, which allows you to specify which JSON Schema dialect your OpenAPI document uses. This property is part of OpenAPI 3.1's alignment with JSON Schema standards.
622-
623-
==== Understanding JSON Schema dialects
624-
625-
A JSON Schema dialect defines which version and vocabulary of JSON Schema is being used. OpenAPI 3.1 supports multiple dialects:
466+
MicroProfile OpenAPI 4.1 introduces the `jsonSchemaDialect` property. This property defines the default meta-schema used to validate and interpret the JSON schema objects within your OpenAPI document.
626467

627-
* Default dialect: `\https://spec.openapis.org/oas/3.1/dialect/base` (the standard OpenAPI 3.1 JSON Schema dialect)
628-
* Full JSON Schema: `\https://json-schema.org/draft/2020-12/schema` (complete JSON Schema 2020-12 specification)
629-
* Custom dialects: Organization-specific or tool-specific schema vocabularies
468+
Below are the available dialects in OpenAPI 3.1:
630469

631-
When you set the dialect explicitly, you ensure compatibility with tools and validators that support specific JSON Schema versions.
470+
* *Default dialect*: `https://spec.openapis.org/oas/3.1/dialect/base` - This is used when no dialect is specified. It is a superset of JSON Schema 2020-12. It permits all standard JSON Schema 2020-12 keywords as well as OpenAPI-specific keywords.
471+
* *JSON Schema 2020-12*: `https://json-schema.org/draft/2020-12/schema` - Use this to restrict schemas to standard JSON Schema 2020-12. It ensures your OpenAPI documents compatibility with external systems that require strict adherence to the JSON Schema 2020-12 specification and do not understand OpenAPI extensions.
632472

633473
==== Specifying the dialect programmatically
634474

@@ -648,10 +488,12 @@ public class CustomModelReader implements OASModelReader {
648488
public OpenAPI buildModel() {
649489
return OASFactory.createOpenAPI()
650490
.openapi("3.1.0")
651-
// Use default OpenAPI 3.1 dialect (recommended for most use cases)
491+
// Use default OpenAPI 3.1 dialect (recommended for most use cases).
492+
// Supports all JSON Schema 2020-12 keywords PLUS Open API specific extensions.
652493
.jsonSchemaDialect("https://spec.openapis.org/oas/3.1/dialect/base")
653494
654-
// Alternative: Use full JSON Schema 2020-12 dialect for advanced features
495+
// Alternative: Use JSON Schema 2020-12 ONLY if you need strict compatibility
496+
// with external tools that do not recognize OpenAPI-specific keywords.
655497
// .jsonSchemaDialect("https://json-schema.org/draft/2020-12/schema")
656498
657499
.info(OASFactory.createInfo()
@@ -662,13 +504,6 @@ public class CustomModelReader implements OASModelReader {
662504
}
663505
----
664506

665-
The full JSON Schema 2020-12 dialect enables advanced features like:
666-
667-
* `prefixItems` for tuple validation
668-
* `$dynamicRef` and `$dynamicAnchor` for dynamic schema references
669-
* `unevaluatedProperties` and `unevaluatedItems` for strict validation
670-
* Enhanced pattern properties and additional vocabulary extensions
671-
672507
==== Activating the model reader
673508

674509
Configure the model reader in `microprofile-config.properties`:
@@ -678,72 +513,6 @@ Configure the model reader in `microprofile-config.properties`:
678513
mp.openapi.model.reader=io.microprofile.tutorial.store.config.CustomModelReader
679514
----
680515

681-
==== Dialect usage
682-
683-
While you can set the `jsonSchemaDialect` programmatically through the OpenAPI model, the dialect property controls how JSON Schema validation and processing occurs internally. The dialect setting ensures that:
684-
685-
* Schema validation follows the specified JSON Schema version rules
686-
* Type definitions are interpreted according to the dialect's vocabulary
687-
* Schema composition keywords (`oneOf`, `anyOf`, `allOf`) behave according to the dialect specification
688-
* Nullable types use the appropriate representation for the dialect
689-
* Advanced JSON Schema features are available when using the full 2020-12 dialect
690-
691-
==== When to specify the dialect
692-
693-
You should explicitly set the `jsonSchemaDialect` when:
694-
695-
* Using advanced JSON Schema features: `prefixItems`, `$dynamicRef`, `unevaluatedProperties`
696-
* Integrating with external validators: Tools that require JSON Schema 2020-12 compliance
697-
* Requiring strict schema validation: Need features like `unevaluatedProperties` for comprehensive validation
698-
* Ensuring tool compatibility: Working with schema generators or validators that expect specific dialects
699-
* Using custom vocabularies: Organization-specific schema extensions
700-
701-
For most applications using standard MicroProfile OpenAPI features, the default dialect (`\https://spec.openapis.org/oas/3.1/dialect/base`) is used automatically and does not need to be explicitly set.
702-
703-
==== Comparison of dialects
704-
705-
.JSON Schema dialect feature comparison
706-
[cols="3,2,2", options="header"]
707-
|===
708-
| Feature and description | OpenAPI 3.1 base dialect | Full JSON Schema 2020-12
709-
710-
| *Basic validation:* Basic type validation (string, number, boolean, and so on)
711-
| ✓ Supported
712-
| ✓ Supported
713-
714-
| *Schema composition:* Combining schemas using `oneOf`, `anyOf`, `allOf`
715-
| ✓ Supported
716-
| ✓ Supported
717-
718-
| *Nullable types:* Representing values that can be null
719-
| ✓ Supported with type arrays
720-
| ✓ Supported with type arrays
721-
722-
| *Tuple validation (`prefixItems`):* Validate arrays with different types per position (for example, [`string`, `number`, `boolean`])
723-
| ✗ Not available
724-
| ✓ Supported
725-
726-
| *Dynamic references (`$dynamicRef`):* Advanced schema composition with runtime-resolved reference
727-
| ✗ Not available
728-
| ✓ Supported
729-
730-
| *Strict validation (`unevaluatedProperties`):* Reject additional properties not covered by schema
731-
| ✗ Not available
732-
| ✓ Supported
733-
734-
| *Custom vocabularies (`$vocabulary`):* Define and use custom validation keywords
735-
| ✗ Not available
736-
| ✓ Supported
737-
738-
| *Primary use case*
739-
| Standard REST API documentation and validation
740-
| Advanced schema validation, tooling integration, strict compliance
741-
742-
| *Recommended for*
743-
| Most microservices and REST APIs
744-
| Complex validation requirements, schema tooling, external validators
745-
|===
746-
747516
=== Extensible interface methods
748517

749518
MicroProfile OpenAPI 4.1 adds two new methods to the `Extensible` interface: `getExtension(String)` and `hasExtension(String)`. These methods provide a more convenient way to work with vendor extensions (custom properties prefixed with `x-`) in your OpenAPI model.
@@ -926,26 +695,24 @@ Filters prove useful for:
926695
Filters modify the OpenAPI document before it is served. They do not directly generate configuration files or code. Instead, they add metadata (often as vendor extensions) that other tools consume from the generated OpenAPI specification.
927696
====
928697

929-
=== Documenting asynchronous operations with callbacks
698+
== Documenting Asynchronous Operations with Callbacks
930699

931-
MicroProfile OpenAPI 4.1 supports documenting asynchronous operations that use callbacks. Callbacks prove useful for webhook-style APIs where your service initiates an asynchronous process and notifies the client when it completes by making an HTTP request back to a URL provided by the client.
700+
MicroProfile OpenAPI 4.1 supports documenting asynchronous operations that use callbacks. Callbacks are useful for APIs where your service initiates an asynchronous process and notifies the client when it completes by making an HTTP request back to a URL provided by the client.
932701

933-
==== Understanding callbacks
702+
=== Understanding Callbacks
934703

935-
A callback in OpenAPI describes an HTTP request that your API will make to the client. Common use cases include:
704+
A callback in OpenAPI describes an HTTP request that your API will make to the client. Common use cases of callbacks include:
936705

937-
* Webhook notifications: Notify clients when long-running operations complete
938-
* Event subscriptions: Send events to client-provided endpoints
939-
* Payment processing: Notify clients of payment status changes
940-
* Batch processing: Alert clients when batch jobs finish
941-
* Order fulfillment: Update clients on order status changes
706+
* *Webhook notifications*: Notify clients when long-running operations complete
707+
* *Event subscriptions*: Send events to client-provided endpoints
708+
* *Batch processing*: Alert clients when batch jobs finish
942709

943710
The callback pattern works as follows:
944711

945-
1. Client makes a request to your API and provides a callback URL.
946-
2. Your API accepts the request and returns immediately (typically 202 Accepted).
947-
3. Your API processes the request asynchronously.
948-
4. When complete, your API makes an HTTP request to the client's callback URL.
712+
1. Client makes a request to your API and provides a callback URL
713+
2. Your API accepts the request and returns immediately (typically 202 Accepted)
714+
3. Your API processes the request asynchronously
715+
4. When complete, your API makes an HTTP request to the client's callback URL
949716

950717
==== Documenting callbacks with @Callback
951718

0 commit comments

Comments
 (0)