Skip to content

Commit 4da5c62

Browse files
committed
docs(readme): rewrite root & module docs for generics-aware OpenAPI client
fix(docker): repair Dockerfile to build/run successfully chore(repo): add .dockerignore - Root README: - Clarified project purpose (generics-aware OpenAPI generation with thin wrappers) - Added clean Table of Contents, Compatibility Matrix, Quick Start, and Key Features - Documented end-to-end flow (Springdoc vendor extensions → Mustache overlay → thin wrappers) - Linked submodules and included social preview image - Added Contributing, Feedback, and Support sections - customer-service/README: - Explained module’s role as API producer - Provided run instructions (JVM, Docker, Docker Compose) - Listed CRUD endpoints with example payloads - Documented OpenAPI endpoints (Swagger UI / JSON / YAML) - Added testing notes and profile info - customer-service-client/README: - Stated “Not a Published Library” with explicit DO NOT add as dependency - Added prerequisites, scope & non-goals (kept runtime concerns out of scope) - Included TL;DR generation steps and “what gets generated” - Documented adapter pattern usage and strongly-typed return flow - Described Mustache overlay files (`api_wrapper.mustache`, `model.mustache`) - Added troubleshooting section (wrappers not generated, stale spec, packages, provided deps) - Dockerfile: - Fixed build/run issues so the service starts reliably - Ensured required build args and ports align with app config - .dockerignore: - Added to reduce image context (target/, .git, IDE files, etc.), improving build performance No functional API changes; documentation and tooling only.
1 parent 22b66e2 commit 4da5c62

File tree

8 files changed

+270
-11
lines changed

8 files changed

+270
-11
lines changed

README.md

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,42 @@
88
[![OpenAPI Generator](https://img.shields.io/badge/OpenAPI%20Generator-7.x-blue?logo=openapiinitiative)](https://openapi-generator.tech/)
99
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)
1010

11+
---
12+
13+
## 📑 Table of Contents
14+
15+
- 📦 [Modules](#-modules-in-this-repository)
16+
- 🛠 [Compatibility Matrix](#-compatibility-matrix)
17+
- 🚀 [Problem Statement](#-problem-statement)
18+
- 💡 [Solution](#-solution)
19+
-[Quick Start](#-quick-start)
20+
- 🧩 [Tech Stack](#-tech-stack--features)
21+
-[Key Features](#-key-features)
22+
-[Usage Example](#-usage-example-adapter-interface)
23+
- 📦 [Related Modules](#-related-modules-quick-view)
24+
25+
### 📦 Modules in this Repository
26+
27+
This repository consists of two main modules:
28+
29+
- [**customer-service**](customer-service/README.md) — Sample API producer (Spring Boot microservice + OpenAPI spec)
30+
- [**customer-service-client**](customer-service-client/README.md) — Generated Java client (generics support via custom
31+
templates)
32+
33+
---
34+
35+
### 🔧 Compatibility Matrix
36+
37+
| Component | Version |
38+
|-------------------------|---------|
39+
| **Java** | 21 |
40+
| **Spring Boot** | 3.4.10 |
41+
| **Springdoc OpenAPI** | 2.8.13 |
42+
| **OpenAPI Generator** | 7.15.0 |
43+
| **Apache HttpClient 5** | 5.5 |
44+
45+
---
46+
1147
<p align="center">
1248
<img src="docs/images/social-preview.png" alt="Social preview" width="720"/>
1349
<br/>
@@ -287,6 +323,24 @@ If parameters include spaces or special characters, wrap them in quotes `"..."`.
287323
If you spot any mistakes in this README or have questions about the project, feel free to open an issue or start a
288324
discussion. I’m happy to improve the documentation and clarify concepts further!
289325

326+
---
327+
328+
## 🤝 Contributing
329+
330+
Contributions, issues, and feature requests are welcome!
331+
Feel free to [open an issue](../../issues) or submit a PR.
332+
333+
---
334+
290335
## ⭐ Support
291336

292337
If you found this project useful, please consider giving it a star ⭐ on GitHub — it helps others discover it too!
338+
339+
---
340+
341+
## 📦 Related Modules (Quick View)
342+
343+
| Module | Description | Docs |
344+
|--------------------------------|---------------------------------------------|---------------------------------------------|
345+
| 🟢 **customer-service** | Spring Boot sample API (producer) | [README](customer-service/README.md) |
346+
| 🔵 **customer-service-client** | Generated Java client with generics support | [README](customer-service-client/README.md) |

customer-service-client/README.md

Lines changed: 120 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
11
# customer-service-client
22

3+
[![Java 21](https://img.shields.io/badge/Java-21-red?logo=openjdk)](https://openjdk.org/projects/jdk/21/)
4+
[![Spring Boot](https://img.shields.io/badge/Spring%20Boot-3.4.10-green?logo=springboot)](https://spring.io/projects/spring-boot)
5+
[![OpenAPI Generator](https://img.shields.io/badge/OpenAPI%20Generator-7.15.0-blue?logo=openapiinitiative)](https://openapi-generator.tech/)
6+
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](../LICENSE)
7+
38
Generated Java client for the **customer-service**, showcasing **type-safe generic responses** with OpenAPI + a
49
custom Mustache template (wrapping payloads in a reusable `ServiceClientResponse<T>`).
510

@@ -72,12 +77,117 @@ Each is a **thin shell** extending `ServiceClientResponse<PayloadType>`.
7277

7378
---
7479

80+
## 🚫 Not a Published Library (Re-generate in your project)
81+
82+
This module is a **reference demo**, not a published library.
83+
To apply the same approach in your own project:
84+
85+
1. Generate your own OpenAPI spec (`/v3/api-docs.yaml`).
86+
2. Copy the two Mustache templates (`api_wrapper.mustache`, `model.mustache`) into your project.
87+
3. Run OpenAPI Generator with your spec + templates → you’ll get type-safe wrappers.
88+
89+
> ⚠️ **Do not add `customer-service-client` as a Maven/Gradle dependency in your project.**
90+
> Instead, re-generate your own client using **your service’s OpenAPI spec** and the provided Mustache templates.
91+
92+
---
93+
94+
## 📦 Prerequisites
95+
96+
Before generating or using the client, make sure you have:
97+
98+
* **Java 21** or newer
99+
* **Maven 3.9+** (or Gradle 8+ if you adapt the build)
100+
* A running instance of the `customer-service` exposing its OpenAPI spec
101+
102+
---
103+
104+
## 🎯 Scope & Non-Goals
105+
106+
This module focuses on **generics-aware client generation** only. Specifically, it demonstrates:
107+
108+
* Marking wrapper schemas via OpenAPI **vendor extensions** (e.g., `x-api-wrapper`, `x-api-wrapper-datatype`)
109+
* A tiny **Mustache overlay** that emits **thin wrapper classes** extending a reusable `ServiceClientResponse<T>`
110+
* How those wrappers enable **compile-time type safety** in consumer code (see the adapter example)
111+
112+
**Out of scope (non-goals):**
113+
114+
* Runtime concerns such as error handling strategies for non-2xx responses, retries, logging, metrics, circuit-breaking
115+
* Business validation, pagination conventions, or API design guidelines
116+
* Authentication/authorization configuration
117+
* Packaging and publishing this client as a reusable library
118+
119+
If you need those capabilities, add them in your host application or platform code. This repo is intentionally minimal
120+
to keep the focus on the **wrapper generation pattern**.
121+
122+
---
123+
124+
## 🔄 How thin wrappers are produced (end-to-end flow)
125+
126+
```
127+
Controller returns `ServiceResponse<T>`
128+
129+
130+
Springdoc `OpenApiCustomizer` discovers `T` and marks wrapper schemas
131+
(vendor extensions: `x-api-wrapper: true`, `x-api-wrapper-datatype: <T>`)
132+
133+
134+
OpenAPI spec (YAML/JSON) contains `ServiceResponse{T}` schemas with vendor extensions
135+
136+
137+
OpenAPI Generator runs with a tiny Mustache overlay
138+
(`api_wrapper.mustache`, `model.mustache`)
139+
140+
141+
Generated Java classes:
142+
- Thin wrappers like `ServiceResponseCustomerCreateResponse`
143+
extending `ServiceClientResponse<CustomerCreateResponse>`
144+
- No duplicated envelope fields
145+
146+
147+
Consumer code (e.g., adapter) gets compile-time type safety
148+
```
149+
150+
**Key files**
151+
152+
* Templates: `src/main/resources/openapi-templates/api_wrapper.mustache`, `.../model.mustache`
153+
* Generated output: `target/generated-sources/openapi/src/gen/java`
154+
* Packages (from `pom.xml`): `apiPackage`, `modelPackage`, `invokerPackage`
155+
156+
---
157+
158+
## 🧰 Troubleshooting (quick)
159+
160+
* **No thin wrappers generated?**
161+
Check your spec contains vendor extensions on wrapper schemas (look for `x-api-wrapper: true`).
162+
Also verify the generator uses your overlay via `<templateDirectory>`.
163+
164+
* **Wrong packages or missing classes?**
165+
Ensure `apiPackage`, `modelPackage`, and `invokerPackage` in the plugin configuration match what you expect.
166+
Delete `target/` and re-run: `mvn clean install`.
167+
168+
* **Spec is stale?**
169+
Re-pull it:
170+
171+
```bash
172+
curl -s http://localhost:8084/customer-service/v3/api-docs.yaml \
173+
-o src/main/resources/customer-api-docs.yaml
174+
mvn -q clean install
175+
```
176+
177+
* **Validation/annotations not found at runtime?**
178+
Some dependencies (e.g., `spring-web`, `jakarta.*`) are marked **provided**.
179+
Your host app must supply them on the classpath.
180+
181+
* **Base URL not applied?**
182+
If you use the Spring configuration, set `customer.api.base-url` correctly and ensure the `RestClient` bean is
183+
created.
184+
185+
---
186+
75187
## 🧩 Using the Client
76188

77189
### Option A — Spring Configuration (recommended)
78190

79-
Include this module as a dependency and configure the base URL:
80-
81191
```java
82192

83193
@Configuration
@@ -339,3 +449,11 @@ This module is **reference-oriented**. If you want to publish it as a reusable l
339449
* remove `provided` scopes and pin minimal runtime deps,
340450
* add a semantic version and release process (e.g., GitHub Release + `mvn deploy` to Maven Central),
341451
* keep the Mustache overlay in-repo for transparent builds.
452+
453+
---
454+
455+
## 📦 Related Module
456+
457+
This client is generated from the OpenAPI spec exposed by:
458+
459+
* [customer-service](../customer-service/README.md) — Sample Spring Boot microservice (API producer).

customer-service-client/pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77
<groupId>io.github.bsayli</groupId>
88
<artifactId>customer-service-client</artifactId>
9-
<version>0.6.3</version>
9+
<version>0.6.4</version>
1010
<name>customer-service-client</name>
1111
<description>Generated client (RestClient) using generics-aware OpenAPI templates</description>
1212
<packaging>jar</packaging>

customer-service-client/src/main/resources/customer-api-docs.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ openapi: 3.1.0
22
info:
33
title: Customer Service API
44
description: Customer Service API with type-safe generic responses using OpenAPI
5-
version: 0.6.3
5+
version: 0.6.4
66
servers:
77
- url: http://localhost:8084/customer-service
88
description: Local service URL

customer-service/.dockerignore

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
target/
2+
.git
3+
.gitignore
4+
Dockerfile
5+
README.md

customer-service/Dockerfile

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
1-
FROM eclipse-temurin:21-jdk AS build
1+
FROM maven:3.9.9-eclipse-temurin-21 AS build
22
WORKDIR /src
33
COPY . .
4-
RUN ./mvnw -q -DskipTests package
4+
RUN mvn -q -DskipTests package
55

66
FROM eclipse-temurin:21-jre-alpine
77
RUN addgroup -S app && adduser -S app -G app
88
USER app
99
WORKDIR /app
10-
COPY --from=build /src/customer-service/target/customer-service-*.jar app.jar
10+
COPY --from=build /src/target/customer-service-*.jar app.jar
1111
EXPOSE 8084
1212
ENTRYPOINT ["sh","-c","exec java $JAVA_OPTS -jar app.jar"]

customer-service/README.md

Lines changed: 85 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
# customer-service
22

3-
Sample Spring Boot 3.4 microservice demonstrating **type-safe generic API responses** with OpenAPI.
4-
5-
This module is part of the parent repo: `spring-boot-openapi-generics-clients`.
3+
[![Java](https://img.shields.io/badge/Java-21-red?logo=openjdk)](https://openjdk.org/projects/jdk/21/)
4+
[![Spring Boot](https://img.shields.io/badge/Spring%20Boot-3.4.10-green?logo=springboot)](https://spring.io/projects/spring-boot)
5+
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](../LICENSE)
6+
[![Build](https://github.com/bsayli/spring-boot-openapi-generics-clients/actions/workflows/build.yml/badge.svg)](https://github.com/bsayli/spring-boot-openapi-generics-clients/actions/workflows/build.yml)
67

78
---
89

@@ -22,6 +23,16 @@ against.
2223

2324
---
2425

26+
## 📊 Architecture at a Glance
27+
28+
```text
29+
client <--> customer-service <--> OpenAPI Spec (YAML/JSON) <--> customer-service-client
30+
```
31+
32+
This module defines the contract; the client module consumes it.
33+
34+
---
35+
2536
## 🚀 How to Run (Local JVM)
2637

2738
```bash
@@ -78,6 +89,43 @@ Example full URL for listing customers:
7889
http://localhost:8084/customer-service/v1/customers
7990
```
8091

92+
### Example Response: Get Customer
93+
94+
```json
95+
{
96+
"status": 200,
97+
"message": "OK",
98+
"data": {
99+
"customerId": 1,
100+
"name": "Jane Doe",
101+
"email": "jane@example.com"
102+
},
103+
"errors": []
104+
}
105+
```
106+
107+
### Example Response: List Customers
108+
109+
```json
110+
{
111+
"status": 200,
112+
"message": "OK",
113+
"data": [
114+
{
115+
"customerId": 1,
116+
"name": "Jane Doe",
117+
"email": "jane@example.com"
118+
},
119+
{
120+
"customerId": 2,
121+
"name": "John Smith",
122+
"email": "john@example.com"
123+
}
124+
],
125+
"errors": []
126+
}
127+
```
128+
81129
---
82130

83131
## 🔗 OpenAPI Endpoints
@@ -147,6 +195,17 @@ docker compose down
147195

148196
---
149197

198+
## 🧪 Testing
199+
200+
Run unit and integration tests:
201+
202+
```bash
203+
cd customer-service
204+
mvn test
205+
```
206+
207+
---
208+
150209
## 📖 Notes
151210

152211
* Demonstrates **generic `ServiceResponse<T>`** pattern.
@@ -157,4 +216,27 @@ docker compose down
157216
* OpenAPI spec (`/v3/api-docs.yaml`) is the input for client generation.
158217
* Includes **exception handling via `CustomerControllerAdvice`**.
159218
* Provides **unit tests** for both controller and service layers.
219+
* Profiles: `local` (default) and `dev` available — can be extended per environment.
160220
* Focused on clarity and minimal setup.
221+
222+
---
223+
224+
## 📦 Related Module
225+
226+
This service is the API producer for the generated client:
227+
228+
* [customer-service-client](../customer-service-client/README.md) — Java client generated from this service's OpenAPI
229+
spec.
230+
231+
---
232+
233+
## 🤝 Contributing
234+
235+
Contributions, issues, and feature requests are welcome!
236+
Feel free to [open an issue](../../issues) or submit a PR.
237+
238+
---
239+
240+
## 🛡 License
241+
242+
MIT

customer-service/pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313

1414
<groupId>io.github.bsayli</groupId>
1515
<artifactId>customer-service</artifactId>
16-
<version>0.6.3</version>
16+
<version>0.6.4</version>
1717
<name>customer-service</name>
1818
<description>Spring Boot 3.4 + Springdoc (OpenAPI) for generics-aware client generation</description>
1919

0 commit comments

Comments
 (0)