| 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
- BYOE — Bring Your Own Envelope
- Verification
- Further Reading
Add the starter:
<dependency>
<groupId>io.github.blueprint-platform</groupId>
<artifactId>openapi-generics-server-starter</artifactId>
<version>1.2.0</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>>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
- projects wrapper and container metadata into OpenAPI
- publishes OpenAPI Generics vendor extensions
- validates the generated contract metadata
It does not:
- intercept HTTP requests
- change runtime serialization
- modify controller behavior
Projection pipeline:
Java Contract
↓
Response Introspection
↓
OpenAPI Projection
↓
Vendor Extensions
↓
Validated OpenAPI Document
Built-in contracts:
ServiceResponse<T>
ServiceResponse<List<T>>
ServiceResponse<Set<T>>
ServiceResponse<Page<T>>BYOE envelopes support the same response shapes.
Application-defined generic containers (for example Paging<T> or Window<T>) participate in the same projection pipeline when registered through configuration.
Asynchronous wrappers are unwrapped automatically, including:
CompletionStage<T>
Future<T>
DeferredResult<T>
WebAsyncTask<T>Use your own response envelope instead of ServiceResponse<T>.
Configure the envelope and, optionally, register application-defined generic containers:
openapi-generics:
envelope:
type: io.example.contract.ApiResponse
# Optional
containers:
- type: io.example.contract.Paging
item-property: content
- type: io.example.contract.Window
item-property: itemsThe configured envelope becomes the published contract while preserving the same projection model.
Configured generic containers are optional. When registered, they participate in the same projection pipeline as the built-in List<T>, Set<T>, and platform-provided Page<T> container types.
This allows generated clients to reconstruct both built-in and application-defined generic container contracts through the same deterministic model.
After starting the application, verify that the generated OpenAPI document contains OpenAPI Generics metadata.
Built-in container example:
x-api-wrapper: true
x-api-wrapper-datatype: PageCustomerDto
x-data-container: Page
x-data-container-type: io.github.blueprintplatform.openapi.generics.contract.paging.Page
x-data-item: CustomerDtoApplication-defined container example:
x-api-wrapper: true
x-api-wrapper-datatype: PagingCustomerDto
x-data-container: Paging
x-data-container-type: io.example.contract.Paging
x-data-item: CustomerDtoInfrastructure schemas that are contract-owned or externally provided should also be marked with:
x-ignore-model: trueThese metadata allow the client generator to reconstruct the original Java contract deterministically.