Type-safe API responses without boilerplate — powered by Spring Boot & OpenAPI Generator
Type-safe client generation with Spring Boot & OpenAPI using generics. This repository demonstrates how to teach OpenAPI Generator to work with generics in order to avoid boilerplate, reduce duplicated wrappers, and keep client code clean.
Most backend teams standardize responses with a generic wrapper like ServiceResponse<T>. However, OpenAPI Generator does not natively support generics — instead, it generates one wrapper per endpoint ( duplicating fields like status, message, and errors).
This creates:
- ❌ Dozens of almost-identical classes
- ❌ High maintenance overhead
- ❌ No single place to evolve the response envelope
This project shows how to:
- Customize Springdoc to mark wrapper schemas in OpenAPI
- Add a tiny Mustache partial so the generator emits thin shells extending a reusable generic base
- Keep compile-time type safety without repetitive mappers
Run the sample service:
Generate and build the client:
Use the generated API:
Here’s what the create customer endpoint looks like in Swagger UI after running the service:
Comparison of how OpenAPI Generator outputs looked before vs after adding the generics-aware wrapper:
Before (duplicated full model):
After (thin generic wrapper):
- 🚀 Java 21 — modern language features
- 🍃 Spring Boot 3.4.9 — microservice foundation
- 📖 Springdoc OpenAPI — API documentation
- 🔧 OpenAPI Generator 7.x — client code generation
- 🧩 Custom Mustache templates — generics-aware wrappers
- 🧪 JUnit 5 + MockWebServer — integration testing
- 🌐 Apache HttpClient 5 — connection pooling & timeouts
- ✅ Generic base model: ServiceClientResponse<T>
- ✅ Thin wrappers: endpoint-specific shells extending the base
- ✅ Strong typing preserved: getData() returns the exact payload type
- ✅ No duplicated fields across wrappers
- ✅ Easy to maintain and evolve
Without generics support, OpenAPI client generation creates bloated and repetitive code. By applying this approach:
- Development teams save time maintaining response models
- Client libraries become cleaner and smaller
- Easier for new developers to understand the contract
- Code stays future-proof when envelope fields evolve
This pattern is useful when:
- You have multiple microservices with a shared response structure
- You need to evolve response envelopes without breaking dozens of generated classes
- You want type safety in generated clients but without boilerplate
-
Start the sample service
cd customer-service mvn spring-boot:run -
Generate the client
cd customer-service-client mvn clean install -
Use the generated API
ServiceClientResponse<CustomerCreateResponse> response = customerControllerApi.createCustomer(request);
This repository is based on my article: 👉 Type-Safe Generic API Responses with Spring Boot 3.4, OpenAPI Generator, and Custom Templates
MIT
✅ Note: CLI examples should always be provided on a single line. If parameters include spaces or special characters, wrap them in quotes "...".
If you spot any mistakes in this README or have questions about the project, feel free to open an issue or start a discussion. I’m happy to improve the documentation and clarify concepts further!
If you found this project useful, please consider giving it a star ⭐ on GitHub — it helps others discover it too!