Many teams struggle with duplicated response wrappers in their generated API clients. Every endpoint ends up with its own ServiceResponseFooResponse, ServiceResponseBarResponse, … all repeating the same fields. Boilerplate everywhere.
In this post I’ll show a clean approach to generating type-safe generic clients with Spring Boot 3.4 + OpenAPI Generator 7.x — powered by a tiny Mustache customization.
✅ No duplicated wrappers
✅ Strongly typed responses (compile-time safety)
✅ One generic base, thin wrappers per endpoint
✅ Full CRUD demo with tests
Problem
Default OpenAPI Generator doesn’t handle generics. It produces one “wrapper” model per endpoint, duplicating fields like status, message, and errors across dozens of classes.
This is noisy and hard to maintain.
Solution
We introduce a single generic base class:
public class ServiceClientResponse<T> { private Integer status; private String message; private List<ClientErrorDetail> errors; private T data; }
…and let generated wrappers simply extend it:
public class ServiceResponseCustomerCreateResponse extends ServiceClientResponse<CustomerCreateResponse> {}
That’s it: no duplicated boilerplate, while keeping typed getData() access.
How?
- OpenApiCustomizer marks wrapper schemas in the spec.
- Tiny Mustache partial (api_wrapper.mustache) tells the generator to render thin shells instead of full models.
The result: clean, DRY clients that still feel natural to use.
Demo Repo
📂 Full working demo with CRUD endpoints, templates, and integration tests:
👉 spring-boot-openapi-generics-clients
Deep Dive Article
For the full breakdown (customizer code, templates, before/after screenshots, and advanced usage), check out my detailed Medium write-up:
👉 Type-Safe Generic API Responses with Spring Boot 3.4, OpenAPI Generator, and Custom Templates
💡 This pattern scales well across microservices and saves teams from maintaining dozens of duplicated wrapper classes. If your APIs already use a common response envelope, this approach will simplify your client layer dramatically.
Top comments (0)