@@ -28,7 +28,7 @@ This repository demonstrates a production-grade architecture where backend and c
2828* 💡 [ Solution Overview] ( #-solution-overview )
2929* ⚙️ [ New Architecture Highlights] ( #-new-architecture-highlights )
3030* ⚡ [ Quick Start] ( #-quick-start )
31- * 🖼 [ Generated Client Wrapper — Before & After] ( #-generated-client -wrapper--before--after )
31+ * 🖼 [ Generated Wrappers — Before & After] ( #-generated-wrapper--before--after )
3232* 🧱 [ Example Responses] ( #-example-responses )
3333* 🧩 [ Tech Stack] ( #-tech-stack )
3434* ✅ [ Key Features] ( #-key-features )
@@ -51,7 +51,8 @@ boilerplate-free.*
5151
5252## 🚀 Problem & Motivation
5353
54- OpenAPI Generator, by default, does not handle ** generic response types** .
54+ OpenAPI Generator, by default, does not handle ** generic response types** .
55+
5556When backend APIs wrap payloads in ` ServiceResponse<T> ` (e.g., the unified ` { data, meta } ` envelope),
5657the generator produces ** duplicated models per endpoint** instead of a single reusable generic base.
5758
@@ -65,34 +66,56 @@ This results in:
6566
6667## 💡 Solution Overview
6768
68- This project provides a ** full-stack pattern** to align Spring Boot services and OpenAPI clients:
69+ This project provides a ** full-stack pattern** to align Spring Boot services and OpenAPI clients.
6970
7071### Server-Side (Producer)
7172
72- A ` Springdoc ` customizer automatically scans controller return types and marks generic wrappers (` ServiceResponse<T> ` )
73- using vendor extensions:
73+ A ` Springdoc ` customizer automatically inspects controller return types like:
74+
75+ ``` java
76+ ResponseEntity<ServiceResponse<CustomerDto > >
77+ ResponseEntity<ServiceResponse<Page<CustomerDto > > >
78+ ```
79+
80+ and enriches the generated OpenAPI schema with vendor extensions:
81+
82+ ** For single type (` ServiceResponse<T> ` ):**
7483
7584``` yaml
85+ # For simple generic responses
7686x-api-wrapper : true
7787x-api-wrapper-datatype : CustomerDto
88+ ` ` `
89+
90+ **For nested generics (` ServiceResponse<Page<T>>`):**
91+
92+ ` ` ` yaml
93+ x-api-wrapper: true
7894x-data-container: Page
7995x-data-item: CustomerDto
8096` ` `
8197
98+ These hints make the OpenAPI spec fully aware of generic and nested structures — no manual annotations required.
99+
100+ ---
101+
82102# ## Client-Side (Consumer)
83103
84- Mustache overlays redefine OpenAPI templates to generate **thin, type-safe wrappers** extending a reusable base class
85- ` ServiceClientResponse<T>`.
104+ Mustache overlays redefine OpenAPI templates to generate **thin, type-safe wrappers** extending a reusable base class `ServiceClientResponse<T>`.
86105
87106**Example generated output:**
88107
89108` ` ` java
90- public class ServiceResponseCustomerDto extends ServiceClientResponse<CustomerDto> {
91- }
109+ // Single
110+ public class ServiceResponseCustomerDto
111+ extends ServiceClientResponse<CustomerDto> {}
112+
113+ // Paged
114+ public class ServiceResponsePageCustomerDto
115+ extends ServiceClientResponse<Page<CustomerDto>> {}
92116` ` `
93117
94- This pattern supports **nested generics** like `ServiceClientResponse<Page<CustomerDto>>` and maps all error responses
95- into **ProblemDetail** objects.
118+ This pattern supports **nested generics** like `ServiceClientResponse<Page<CustomerDto>>` and automatically maps all error responses into **ProblemDetail** objects.
96119
97120---
98121
@@ -132,9 +155,11 @@ target/generated-sources/openapi/src/gen/java
132155
133156Each wrapper extends `ServiceClientResponse<T>` and aligns perfectly with the `{ data, meta }` envelope model.
134157
158+ You can now test end-to-end type-safe responses through the generated client — verifying both single and paged envelopes in action.
159+
135160---
136161
137- # # 🖼 Generated Client Wrapper — Before & After
162+ # # 🖼 Generated Wrapper — Before & After
138163
139164Comparison of how OpenAPI Generator outputs looked **before** vs **after** enabling the generics-aware wrapper support.
140165
@@ -158,9 +183,25 @@ Comparison of how OpenAPI Generator outputs looked **before** vs **after** enabl
158183
159184# # 🧱 Example Responses
160185
161- The unified envelope applies to both single and paged responses. Below is a paged example :
186+ The unified envelope applies to both single and paged responses.
187+
188+ # ## 🧩 Single Item Example (`ServiceClientResponse<CustomerDto>`)
189+
190+ ` ` ` json
191+ {
192+ "data": {
193+ "customerId": 1,
194+ "name": "Jane Doe",
195+ 196+ },
197+ "meta": {
198+ "serverTime": "2025-01-01T12:34:56Z",
199+ "sort": []
200+ }
201+ }
202+ ` ` `
162203
163- # ## Paged Example (`ServiceClientResponse<Page<CustomerDto>>`)
204+ # ## 📄 Paged Example (`ServiceClientResponse<Page<CustomerDto>>`)
164205
165206` ` ` json
166207{
@@ -195,6 +236,8 @@ The unified envelope applies to both single and paged responses. Below is a page
195236 }
196237}
197238` ` `
239+ Both examples demonstrate the unified `{ data, meta }` structure —
240+ the same envelope applies seamlessly to single and paged results.
198241
199242# ## Client Usage
200243
@@ -211,7 +254,6 @@ for (CustomerDto c : page.content()) {
211254
212255---
213256
214-
215257# # 🧩 Tech Stack
216258
217259| Component | Version | Purpose |
@@ -253,7 +295,7 @@ This adapter defines a stable contract that hides generated artifacts and provid
253295
254296# # 📘 Adoption Guides
255297
256- See the detailed integration steps under [`docs/adoption`](docs/adoption) :
298+ Explore integration steps under [`docs/adoption`](docs/adoption) :
257299
258300* [Server-Side Adoption](docs/adoption/server-side-adoption.md)
259301* [Client-Side Adoption](docs/adoption/client-side-adoption.md)
0 commit comments