Spring Boot OpenAPI Generics Clients
A production-grade blueprint for generics-aware API clients built with Spring Boot and OpenAPI Generator.
Welcome! 👋
This project demonstrates a modern, generics-aware OpenAPI client generation pattern for Spring Boot 3.4+, featuring the unified { data, meta } response model and full nested generic support — from ServiceResponse<T> to ServiceResponse<Page<T>>.
💡 Overview
Using Springdoc on the backend and OpenAPI Generator 7.17.0 on the client side, this setup enables seamless code generation where all responses are type-safe, clean, and boilerplate-free.
public class ServiceResponseCustomerDto
extends ServiceClientResponse<CustomerDto> {
}
Each generated client wrapper now automatically supports nested generic envelopes such as:
ServiceClientResponse<Page<CustomerDto>>
✅ Key Features
- Unified response model:
{ data, meta }replaces legacy status/message/errors structure. - Nested generics support: Handles both
ServiceResponse<T>andServiceResponse<Page<T>>. - RFC 9457 compliant errors: All non-2xx responses are mapped into
ProblemDetailand thrown asClientProblemException. - Generics-aware OpenAPI Generator overlay: Mustache templates produce thin, type-safe wrappers.
- Simple integration: Works with any Spring Boot service exposing
/v3/api-docs.yaml.
🧩 Architecture
[customer-service] → publishes OpenAPI spec (/v3/api-docs.yaml)
│
└──► [customer-service-client] → generates thin wrappers extending ServiceClientResponse<T>
│
└──► used by consumer microservices via adapters
🚀 Quick Start
# Run the backend
cd customer-service && mvn spring-boot:run
# Generate the OpenAPI client
cd ../customer-service-client && mvn clean install
Generated wrappers appear under:
target/generated-sources/openapi/src/gen/java
Each class extends ServiceClientResponse<T> and is compatible with the { data, meta } response structure.
🧱 Example Response
{
"data": {
"customerId": 1,
"name": "Jane Doe",
"email": "jane@example.com"
},
"meta": {
"serverTime": "2025-01-01T12:34:56Z",
"sort": []
}
}
Client usage:
ServiceClientResponse<CustomerDto> response = api.getCustomer(1);
CustomerDto dto = response.getData();
Instant serverTime = response.getMeta().serverTime();
⚙️ Toolchain
| Component | Version | Purpose |
|---|---|---|
| Java | 21 | Language baseline |
| Spring Boot | 3.4.11 | REST + OpenAPI provider |
| Springdoc | 2.8.13 | OpenAPI 3.1 integration |
| OpenAPI Generator | 7.17.0 | Generics-aware client generation |
| HttpClient5 | 5.5 | Production-grade HTTP backend |
📚 Learn More
🔗 References & External Links
✅ With this setup, you get end-to-end generics awareness, clean { data, meta } responses, nested generic wrappers, and unified error handling — all generated automatically.