Prevent OpenAPI Generator from redefining your Java contract.
A contract-preserving OpenAPI Generator specialization for Java/Spring that keeps shared envelopes and DTOs reusable across service boundaries — no model explosion, no custom template fork to maintain.
- The problem in 30 seconds
- Get started
- Real-World Example
- What's New in 1.2.1
- Key Features
- How it works
- Compatibility
- Relationship to OpenAPI Generator
- Modules
- References
- Contributing
- License
A Spring Boot API may expose a strongly typed generic contract:
ResponseEntity<ServiceResponse<Page<CustomerDto>>> getCustomers() { ... }That type carries more than a JSON shape.
ServiceResponse<T> is the response envelope, Page<T> is the pagination contract, and CustomerDto is the payload. Together, they form a Java contract that already has an owner.
A conventional OpenAPI client generation flow can flatten that contract into a new generated model:
// ❌ Generated by default
class ServiceResponsePageCustomerDto {
PageCustomerDto data;
Meta meta;
}The generated type may represent a similar JSON structure, but the original contract identity has been lost. The envelope and container have become generated interpretations of types that already exist.
OpenAPI Generics preserves that identity:
// ✅ Generated with OpenAPI Generics
public class ServiceResponsePageCustomerDto
extends ServiceResponse<Page<CustomerDto>> {}The generated wrapper is intentionally thin. It binds a concrete OpenAPI response schema back to the shared generic contract instead of redefining that contract.
| Default OpenAPI Generator contract materialized as generated models |
OpenAPI Generics contract reconstructed from shared Java types |
![]() |
![]() |
For a single endpoint, duplicated wrapper types may look harmless.
Across many generated clients, they accumulate. A BFF, aggregator, or downstream service can consume dozens of APIs, each introducing additional generated envelopes, container models, mapping layers, and opportunities for contract drift.
OpenAPI Generics keeps that ownership boundary explicit:
Shared Java contracts remain the authority. Generated clients provide transport bindings around them rather than becoming alternative contract definitions.
Payload models may still be generated. API clients and transport code remain generated by OpenAPI Generator. OpenAPI Generics specializes only the contract projection and reconstruction needed to preserve generic Java semantics across that boundary.
Define the contract once in Java, project its identity through OpenAPI, and reconstruct it deterministically in the generated client.
OpenAPI Generics participates at two points in the contract lifecycle:
Java Producer Contract
↓
OpenAPI Projection
↓
Contract-Aware Client Reconstruction
The repository contains runnable end-to-end samples covering:
- Spring Boot 3 and Spring Boot 4 reference stacks
- built-in
ServiceResponse<T>contracts - BYOE envelopes
- application-defined generic containers
- BYOC reuse
- transport compatibility
Each sample follows the same lifecycle:
Producer
↓
OpenAPI
↓
Generated Client
↓
Consumer
Start with samples/README.md for the runnable projects, Docker-based setup, and verification paths.
OpenAPI Generics has separate producer-side and client-side integration points.
Add the server starter:
<dependency>
<groupId>io.github.blueprint-platform</groupId>
<artifactId>openapi-generics-server-starter</artifactId>
<version>1.2.1</version>
</dependency>The starter participates only when Springdoc generates the OpenAPI document.
It does not intercept application requests or change endpoint runtime behavior.
For the built-in ServiceResponse<T> contract, no envelope configuration is required. Applications using BYOE or application-defined generic containers can declare those contract types on the producer.
See Server-Side Adoption for the complete configuration model.
Use the OpenAPI Generics codegen parent:
<parent>
<groupId>io.github.blueprint-platform</groupId>
<artifactId>openapi-generics-java-codegen-parent</artifactId>
<version>1.2.1</version>
</parent>Configure the official OpenAPI Generator Maven plugin as usual, but select the OpenAPI Generics Java specialization:
<generatorName>java-generics-contract</generatorName>Normal OpenAPI Generator choices remain consumer-controlled, including the input specification, client library, package layout, and generator options.
The OpenAPI Generics integration prepares the reconstruction-specific template environment and restores the projected generic contract semantics without taking ownership of the ordinary OpenAPI Generator lifecycle.
See Client-Side Adoption for the complete generator configuration, BYOC mappings, fallback behavior, and generated-source setup.
See the Licensing Project for a complete end-to-end BYOE example using a shared ApiResponse<T> contract.
The project demonstrates:
- Spring Boot server integration with
openapi-generics-server-starter - Java contract → OpenAPI projection
- Generated Java client using
openapi-generics-java-codegen-parent - Shared
ApiResponse<T>reuse across service, client, SDK, and CLI - Docker-based end-to-end verification
OpenAPI Generics 1.2.1 completes the contract-driven reconstruction metadata model by carrying Java envelope identity in the projected OpenAPI document through x-api-wrapper-type.
Together with the container identity metadata introduced in 1.2 through x-data-container-type, the document now carries the contract identity required by the Java generator to reconstruct both platform-owned and application-owned generic response contracts.
Java Contract
↓
OpenAPI Projection
↓
Envelope + Container Identity
↓
Generated Client Reconstruction
For aligned 1.2.1 producer and codegen components, the Java generator derives the envelope type from the OpenAPI document instead of requiring the same openapi-generics.envelope declaration on the client.
The same reconstruction model applies to built-in and application-owned contracts, for example:
ServiceResponse<Page<CustomerDto>>
ApiResponse<Window<CustomerDto>>Highlights in 1.2.1 include:
- contract-driven envelope reconstruction through
x-api-wrapper-type - no duplicate client-side envelope configuration for aligned 1.2.1 components
- end-to-end validation of application-defined containers with both built-in and BYOE envelopes
- dedicated transport compatibility coverage for multipart, binary download, and form-urlencoded scenarios
- clearer server-side failure diagnostics through a dedicated exception hierarchy
- Spring Boot 3 and Spring Boot 4 reference-stack verification
- OpenAPI Generator 7.24.0 verification
All 1.2.0 runtime contracts remain backward compatible.
No contract migration is required for existing 1.2 users.
For the complete release history, see the Changelog.
| Feature | What it does | Default |
|---|---|---|
| BYOE — Bring Your Own Envelope | Reuse your existing response envelope (for example ApiResponse<T>) instead of ServiceResponse<T>. No migration required. |
ServiceResponse<T> |
| BYOC — Bring Your Own Contract | Reuse your existing domain DTOs instead of generating duplicate models. | Generate from spec |
| Application-defined containers | Register your own generic container contracts (for example Paging<T> or Window<T>) and have them participate in the same projection, metadata, and reconstruction pipeline as built-in containers. |
Built-in containers only |
| Contract-driven envelope reconstruction | Reconstruct the Java envelope directly from x-api-wrapper-type metadata without duplicating envelope configuration on the client. |
Enabled |
| Container-aware reconstruction | Deterministically reconstruct built-in and configured generic container types from OpenAPI metadata instead of using container-specific generation logic. | Enabled |
| Fallback to standard generation | Opt out of generics-aware template patching, or switch fully back to stock OpenAPI Generator behavior with generatorName=java. |
Generics-aware generation enabled |
| Deterministic reconstruction | Apply deterministic template patching, generated-source hygiene, and build-time validation to produce stable, contract-aligned Java clients. | Enabled |
| End-to-end samples | Complete producer → OpenAPI → generated client → consumer pipelines covering Spring Boot 3/4, ServiceResponse, BYOE, application-defined containers, and independent transport compatibility scenarios. |
See samples |
Already have an ApiResponse<T> or another response envelope shared across your services?
Use it as the contract source of truth without migrating to a platform-specific wrapper.
On the server/producer side:
openapi-generics:
envelope:
type: io.example.contract.ApiResponse
# Optional: register application-defined generic containers
containers:
- type: io.example.contract.Paging
item-property: content
- type: io.example.contract.Window
item-property: itemsKey characteristics:
- Your envelope remains the contract owner.
- Generated wrappers extend your envelope instead of redefining it.
- The envelope type must be available on the client classpath.
- Springdoc-based projection is automatic.
- Application-defined containers are optional and participate in the same projection and reconstruction model as built-in containers when configured.
- The same metadata protocol can be represented directly in an OpenAPI document when interoperability requires it; Java-contract projection remains the primary architectural model.
Reuse DTOs you already own instead of generating duplicate models.
Map OpenAPI model names to existing Java types:
<additionalProperties>
<additionalProperty>
openapi-generics.response-contract.CustomerDto=io.example.contract.CustomerDto
</additionalProperty>
</additionalProperties>Each mapping follows:
openapi-generics.response-contract.<OpenAPI model name>=<fully-qualified Java type>
The generated client imports and reuses those contract types directly instead of producing duplicate DTO definitions.
Disable the generics-aware template patching with a single Maven property:
<openapi.generics.skip>true</openapi.generics.skip>This skips the template extraction, patching, and overlay steps provided by openapi-generics-java-codegen-parent.
To fully revert to stock OpenAPI Generator behavior:
<generatorName>java</generatorName>Use this mode for output comparison, troubleshooting, or temporary opt-out scenarios.
OpenAPI Generics preserves Java generic contract semantics across the OpenAPI lifecycle.
It keeps generic response envelopes, container payloads, and shared DTO contracts aligned from Spring Boot producers to generated Java clients.
The project is built on one principle:
The Java contract is the source of truth.
OpenAPI is a projection of that contract.
Client generation deterministically reconstructs the original contract.
Java Contract (SSOT)
↓
OpenAPI Projection
↓
Deterministic Client Reconstruction
↓
Contract-Aligned Client
In practice this means:
- the response envelope remains a shared contract, not a generated artifact
- generated wrapper classes extend existing contracts instead of redefining them
- OpenAPI carries contract metadata, not contract ownership
- container semantics are preserved through projection metadata
- clients and servers remain aligned as contracts evolve
Java-contract projection is the primary architectural path. The same metadata protocol can also be represented directly in an OpenAPI document when integration with an externally managed specification requires it.
The server starter discovers generic response contracts, projects wrapper schemas, enriches them with contract metadata, and marks infrastructure models so generated clients reconstruct the original Java contract instead of regenerating it.
Externally managed OpenAPI documents can represent the reconstruction metadata directly through the OpenAPI Generics vendor extensions:
x-api-wrapperx-api-wrapper-typex-api-wrapper-datatypex-data-containerx-data-container-typex-data-itemx-ignore-model
Together, these extensions describe wrapper semantics, payload type, container identity, item type, and generation behavior. This provides an interoperability path for reconstruction without changing the project's primary Java-contract-as-authority model.
The architecture consists of two complementary phases:
- Projection — derives deterministic OpenAPI metadata from Java contracts.
- Reconstruction — restores contract-aligned Java client types during generation using the projected metadata.
Both phases share the same contract authority while keeping generated code isolated from application code.
For internal architecture and design decisions, see the architecture documentation.
- ✔ Shared Java contracts remain the authority; generated wrappers bind concrete generic parameters instead of redefining the contract.
- ✔ Envelope and container identity survive OpenAPI projection through explicit reconstruction metadata.
- ✔ Built-in, BYOE, BYOC, and registered container semantics participate in the same deterministic Java reconstruction model.
- ✔ Detected reconstruction-specific template drift and contract inconsistencies fail during generation rather than surfacing as silent runtime divergence.
OpenAPI Generics currently supports:
- Java: 17+
- Spring Boot: 3.4.x, 3.5.x, and 4.x
- springdoc-openapi: 2.x with Spring Boot 3.x, and 3.x with Spring Boot 4.x
- OpenAPI Generator: 7.x
- Server integration: Spring WebMvc via
springdoc-openapi-starter-webmvc-ui
The repository maintains verified Spring Boot 3, Spring Boot 4, and OpenAPI Generator reference baselines within these supported ranges.
For exact verified versions, the full compatibility matrix, and the support policy, see Compatibility & Support Policy.
OpenAPI Generics is not a fork of OpenAPI Generator.
It builds on the upstream project as a focused Java/Spring specialization for preserving contract-owned generic structures across the OpenAPI lifecycle.
The generated OpenAPI document remains valid OpenAPI and can still be consumed by standard OpenAPI tooling; tools that do not understand OpenAPI Generics metadata simply ignore the vendor extensions.
OpenAPI Generics owns the specialization required for:
- generic contract projection and OpenAPI Generics metadata
- preservation of envelope and container identity
- contract-aware Java wrapper reconstruction
- BYOE and BYOC reconstruction semantics
- reconstruction-specific template preparation, validation, and generated-source hygiene
OpenAPI Generator continues to own the ordinary generation concerns outside that specialization, including:
- standard API and model generation
- HTTP transport and client-library behavior
- authentication generation
- serialization behavior
- upstream template structure and generator evolution
The project therefore consumes upstream template structure and applies a minimal generics-aware patch and overlay layer rather than maintaining a forked template set.
This boundary is deliberate: OpenAPI Generics reconstructs generic contract semantics while leaving ordinary OpenAPI generation behavior with the upstream ecosystem.
OpenAPI Generics does not lock consumers to a specific OpenAPI Generator version.
The provided parent configuration includes a tested default and defines the supported compatibility line, while consumers may override the openapi-generator.version property within the supported 7.x range.
The parent keeps the selected OpenAPI Generator version aligned across plugin execution, generator dependencies, and upstream template extraction so that the reconstruction pipeline uses a consistent toolchain.
OpenAPI Generics owns contract semantics and declares generator compatibility.
Consumers choose the OpenAPI Generator version they run within the supported compatibility line.
| Module | Responsibility |
|---|---|
openapi-generics-contract |
Shared response contracts and platform-owned generic types. |
openapi-generics-server-starter |
Spring Boot integration that projects generic contract metadata into OpenAPI. |
openapi-generics-java-codegen |
OpenAPI Generator specialization that reconstructs contract-aligned Java clients. |
openapi-generics-java-codegen-parent |
Maven parent for client generation, template patching, and generated-source hygiene. |
openapi-generics-platform-bom |
Dependency alignment for OpenAPI Generics modules. |
-
Rationale: Why OpenAPI Generics Exists
Explains the architectural motivation, design decisions, engineering trade-offs, and ecosystem constraints behind the project. -
Documentation Site
Official GitHub Pages documentation for adoption guides, architecture, compatibility, and project usage.
- We Made OpenAPI Generator Think in Generics
Background, motivation, and technical overview of the project.
-
OpenAPI Specification
Official specification for describing HTTP APIs. -
JSON Schema Draft 2020-12
Specification for describing and validating JSON documents. -
RFC 9457 – Problem Details for HTTP APIs
Standard format for error responses in HTTP APIs.
OpenAPI Generics is still evolving, and real-world feedback is the most valuable input for future improvements.
Whether you're evaluating the project, running it in a prototype, or using it in production, feedback is welcome.
Questions, bug reports, design discussions, and adoption experiences all help shape the roadmap.
For contributions and feedback:
- 🐛 Bugs and issues → Issues
- 💡 Design discussions and feature ideas → Discussions
- 🔗 Private feedback → LinkedIn
If OpenAPI Generics helped solve a real problem in your environment, hearing about that experience is often just as valuable as a code contribution.
MIT — see LICENSE


