Generics-aware OpenAPI Generator extension for contract-aligned Java clients
openapi-generics-java-codegen is a custom OpenAPI Generator extension that enforces contract-first client generation.
It does not try to be smarter than your contract. It ensures the generator does not break it.
Prevent OpenAPI Generator from redefining platform-owned models and enforce contract-aligned output.
This module is build-time only and is typically consumed via openapi-generics-java-codegen-parent.
- 🎯 Purpose
- 🧠 Core Idea
- ⚙️ What It Does
- 🧱 Result
- 🧩 External Model Mapping (BYOC)
- 🧩 Template Integration
- 🔗 How It Is Used
- 🚫 Not Intended For Direct Use
- 🔗 Compatibility Matrix
- 🔒 Determinism Guarantees
⚠️ Design Constraints- 🧠 Mental Model
- 🔗 Related Modules
- 📜 License
Default OpenAPI Generator behavior:
- regenerates response envelopes per endpoint
- flattens or loses generic semantics
- creates model drift between server and client
This module prevents that.
It ensures that generated clients:
- reuse canonical contract types (
ServiceResponse,Meta,Page, etc.) - do NOT regenerate platform-owned models
- remain aligned with server-side contract semantics
It acts as an enforcement layer between OpenAPI and generated Java code.
OpenAPI is a projection — not the source of truth
This generator enforces that rule at build time:
- platform-owned models must NOT be generated
- OpenAPI metadata must be interpreted, not materialized
If OpenAPI contains structure that already exists in the contract:
it is mapped back — not regenerated
Reads additionalProperties and registers mappings:
openapiGenerics.responseContract.CustomerDto=io.example.contract.CustomerDto
Backed by: ExternalModelRegistry
Effect:
- marks models as externally provided
- prevents generation of those models
- enables import injection in wrappers
A model is ignored if:
x-ignore-model=trueis present in schema extensions- OR it is registered as an external model
Backed by: ModelIgnoreDecider
- during
fromModel - mark models as ignored
- in
postProcessModels - remove ignored models from the current batch
- in
postProcessAllModels - remove ignored models from the full graph
- removes imports that reference ignored models
- injects correct imports for external types into wrapper models
Backed by: ExternalImportResolver
Generated code:
- references
openapi-generics-contract - does NOT duplicate envelope types
- preserves generic semantics (
ServiceResponse<T>,Page<T>) - remains deterministic and stable
Optional but powerful.
<additionalProperties>
<additionalProperty>
openapiGenerics.responseContract.CustomerDto=
io.example.contract.CustomerDto
</additionalProperty>
</additionalProperties>- prevents generation of
CustomerDto - injects correct import into wrappers
- reuses your domain model directly
- mapping key must match OpenAPI model name
- value must be fully-qualified class name (FQCN)
Templates live under:
META-INF/openapi-generics/templates
Responsibilities:
- generate thin wrapper classes
- extend
ServiceResponse<T> - apply container semantics (
Page<T>)
Example output:
public class ServiceResponsePageCustomerDto
extends ServiceResponse<Page<CustomerDto>> {}This module is not used directly.
It is wired via:
openapi-generics-java-codegen-parent
The parent POM:
- registers this generator (
java-generics-contract) - injects templates
- configures the OpenAPI Generator plugin
End users should NOT:
- reference this module directly
- configure it manually
- override generator behavior
Instead:
Use the codegen parent — it orchestrates everything
| Component | Supported Versions |
|---|---|
| Java | 17+ |
| OpenAPI Generator | 7.x |
Notes:
restclientlibrary requires OpenAPI Generator ≥ 7.6.0- Module is build-time only (no Spring/runtime dependency)
- ✔ No duplication of contract models
- ✔ Stable model graph
- ✔ Consistent generation output
- ✔ Preservation of generic semantics
Mechanisms:
- explicit ignore rules
- controlled graph pruning
- deterministic template application
- depends on vendor extensions (
x-*fields) - assumes contract-first design
- tightly coupled to platform semantics
It is NOT a general-purpose generator.
A guardrail inside OpenAPI Generator that prevents contract drift
Not:
- a standalone generator
- a user-facing tool
| Module | Role |
|---|---|
openapi-generics-contract |
Defines canonical models |
openapi-generics-server-starter |
Produces OpenAPI projection |
openapi-generics-java-codegen |
Enforces generation rules |
openapi-generics-java-codegen-parent |
Orchestrates build-time generation |
MIT License