| layout | default |
|---|---|
| title | Server-Side Adoption |
| parent | Adoption Guides |
| nav_order | 1 |
| has_toc | false |
Publish a generics-aware OpenAPI document from your Spring Boot service without changing runtime behavior.
This guide explains how to enable OpenAPI Generics on the producer side.
For client generation, see Client-Side Adoption.
For implementation details, see Architecture.
- Quick Start
- What the Starter Does
- Supported Controller Shapes
- Application-Defined Generic Containers
- BYOE — Bring Your Own Envelope
- Published Contract Metadata
- Validation and Failure Behavior
- Verification
- Further Reading
Add the starter:
<dependency>
<groupId>io.github.blueprint-platform</groupId>
<artifactId>openapi-generics-server-starter</artifactId>
<version>1.2.1</version>
</dependency>Write controller methods normally:
@GetMapping("/{id}")
public ResponseEntity<ServiceResponse<CustomerDto>> getCustomer(...) {
return ResponseEntity.ok(ServiceResponse.of(service.findById(id)));
}Container payloads are supported as well:
ServiceResponse<List<CustomerDto>>
ServiceResponse<Set<CustomerDto>>
ServiceResponse<Page<CustomerDto>>No controller-specific OpenAPI Generics annotations or runtime response adapters are required for supported shapes.
Application-defined generic containers are also supported when registered through the optional openapi-generics.containers configuration.
The starter runs only when Springdoc generates an OpenAPI document, for example:
/v3/api-docs
/v3/api-docs.yaml
It:
- discovers supported generic response contracts
- introspects wrapper, container, and payload types
- projects generic wrapper schemas into OpenAPI
- preserves envelope identity through
x-api-wrapper-type - preserves container identity through
x-data-container-type - publishes the remaining OpenAPI Generics vendor extensions
- validates configuration, descriptors, projection state, and generated contract metadata
- marks infrastructure or contract-owned schemas so they can be excluded from generated client models
It does not:
- intercept HTTP requests
- change runtime serialization
- modify controller behavior
- replace Spring MVC request handling
- alter standard endpoint transport behavior
Projection pipeline:
Java Contract
↓
Response Introspection
↓
Envelope / Container Resolution
↓
OpenAPI Projection
↓
Contract Metadata Enrichment
↓
Contract Validation
↓
Validated OpenAPI Document
The generated OpenAPI document becomes the boundary between server-side projection and client-side reconstruction.
Built-in contracts include:
ServiceResponse<T>
ServiceResponse<List<T>>
ServiceResponse<Set<T>>
ServiceResponse<Page<T>>BYOE envelopes participate in the same response-shape model.
Application-defined generic containers such as Paging<T>, Window<T>, or Batch<T> participate in the same projection pipeline when registered through configuration.
Examples:
ServiceResponse<Window<CustomerDto>>
ServiceResponse<Batch<CustomerDto>>and, with a BYOE envelope:
ApiResponse<Paging<CustomerDto>>
ApiResponse<Window<CustomerDto>>Supported asynchronous wrappers are unwrapped automatically during response type introspection, including:
CompletionStage<T>
Future<T>
DeferredResult<T>
WebAsyncTask<T>OpenAPI Generics reconstructs supported generic contract shapes after the framework wrapper has been unwrapped.
Applications may register their own generic container contracts.
Example:
openapi-generics:
containers:
- type: io.example.contract.Paging
item-property: content
- type: io.example.contract.Window
item-property: itemsEach configured container contributes:
- the fully qualified Java container type
- the property that contains the generic item collection
- the metadata required to preserve container identity through OpenAPI
Configured containers participate in the same descriptor, projection, metadata, and reconstruction model as built-in container types.
The projected OpenAPI metadata preserves the Java container type through:
x-data-container-type: io.example.contract.WindowThis prevents the client generator from requiring container-specific reconstruction logic.
Application-defined containers are independent from BYOE.
You may use them with the built-in platform envelope:
ServiceResponse<Window<CustomerDto>>or with an application-owned envelope:
ApiResponse<Window<CustomerDto>>Use your own shared response envelope instead of ServiceResponse<T>.
Configure the envelope on the producer:
openapi-generics:
envelope:
type: io.example.contract.ApiResponseYou can combine BYOE with application-defined generic containers:
openapi-generics:
envelope:
type: io.example.contract.ApiResponse
containers:
- type: io.example.contract.Paging
item-property: content
- type: io.example.contract.Window
item-property: itemsThe configured envelope remains the Java contract authority for projected wrapper schemas.
Its fully qualified Java identity is preserved through:
x-api-wrapper-type: io.example.contract.ApiResponseThe generated OpenAPI document therefore carries the envelope identity required by the Java code generator.
When producer and codegen components are aligned, the same envelope does not need to be configured again on the client side through openapi-generics.envelope.
Producer configuration
↓
Java envelope contract
↓
x-api-wrapper-type
↓
OpenAPI document
↓
Generated client reconstruction
The producer remains responsible for publishing the envelope metadata.
The generated client is responsible for consuming it.
The envelope type itself must still be available on the generated client's classpath when generated wrapper classes extend it.
OpenAPI Generics projects contract semantics through vendor extensions.
A built-in container wrapper may look like:
x-api-wrapper: true
x-api-wrapper-type: io.github.blueprintplatform.openapi.generics.contract.response.ServiceResponse
x-api-wrapper-datatype: PageCustomerDto
x-data-container: Page
x-data-container-type: io.github.blueprintplatform.openapi.generics.contract.paging.Page
x-data-item: CustomerDtoAn application-defined container with a BYOE envelope may look like:
x-api-wrapper: true
x-api-wrapper-type: io.example.contract.ApiResponse
x-api-wrapper-datatype: WindowCustomerDto
x-data-container: Window
x-data-container-type: io.example.contract.Window
x-data-item: CustomerDtoThe principal metadata fields are:
x-api-wrapper— identifies a projected generic wrapper schemax-api-wrapper-type— preserves the fully qualified Java envelope typex-api-wrapper-datatype— identifies the projected wrapper payload datatypex-data-container— identifies container semanticsx-data-container-type— preserves the fully qualified Java container typex-data-item— identifies the concrete item or payload typex-ignore-model— marks infrastructure or contract-owned schemas that should not become generated models
Infrastructure schemas that are contract-owned or externally provided may therefore also be marked with:
x-ignore-model: trueTogether, these metadata allow the client generator to reconstruct the original Java contract deterministically.
The server starter follows fail-fast validation.
Invalid configuration or unsupported projected contract state fails while the OpenAPI document is being generated rather than producing ambiguous metadata for downstream code generation.
The server-side failure model distinguishes platform-specific categories covering:
- configuration failures
- generic container descriptor validation failures
- projection failures
- generated contract validation failures
This exception model improves categorization while preserving the existing fail-fast behavior and diagnostic intent.
Typical validation includes:
- envelope configuration validity
- configured container type validity
- configured container generic structure
- configured container item-property validity
- supported response shape discovery
- projected wrapper metadata consistency
- generated contract metadata validation
Because the starter participates only in OpenAPI document generation, these failures belong to the contract publication path rather than normal HTTP request processing.
After starting the application, verify that the generated OpenAPI document contains the expected OpenAPI Generics metadata.
A projected wrapper may look like:
x-api-wrapper: true
x-api-wrapper-type: io.example.contract.ApiResponse
x-api-wrapper-datatype: WindowCustomerDto
x-data-container: Window
x-data-container-type: io.example.contract.Window
x-data-item: CustomerDtoVerify the metadata relevant to the projected contract:
x-api-wrapper-typepreserves the Java envelope identityx-data-container-typepreserves the Java container identity when a generic container is presentx-data-itemidentifies the concrete item or payload typex-ignore-modelis present on infrastructure or contract-owned schemas where exclusion from generated client models is expected- built-in and BYOE envelopes publish the same reconstruction metadata model
- application-defined containers work with both built-in and BYOE envelopes
- OpenAPI document generation succeeds without changing normal HTTP request behavior
The repository additionally verifies the complete producer → OpenAPI → generated client → consumer lifecycle through maintained end-to-end samples and regression coverage.