@@ -28,7 +28,10 @@ curl -s http://localhost:8084/customer-service/v3/api-docs.yaml \
2828mvn -q clean install
2929```
3030
31- Generated sources → ` target/generated-sources/openapi/src/gen/java `
31+ * Generated sources → ` target/generated-sources/openapi/src/gen/java ` *
32+
33+ > ℹ️ ** Multi-module builds:** If your project is multi-module, ensure the generated path is compiled via
34+ ` build-helper-maven-plugin ` (already configured in this repo’s ` pom.xml ` ).
3235
3336---
3437
@@ -89,6 +92,14 @@ To apply the same approach in your own project:
8992> ⚠️ ** Do not add ` customer-service-client ` as a Maven/Gradle dependency in your project.**
9093> Instead, re-generate your own client using ** your service’s OpenAPI spec** and the provided Mustache templates.
9194
95+ ## 📘 Adoption Guides
96+
97+ Looking to integrate this approach into your own project?
98+ See the detailed guides under [ ` docs/adoption ` ] ( ../docs/adoption ) :
99+
100+ - [ Server-Side Adoption] ( ../docs/adoption/server-side-adoption.md )
101+ - [ Client-Side Adoption] ( ../docs/adoption/client-side-adoption.md )
102+
92103---
93104
94105## 📦 Prerequisites
@@ -157,9 +168,12 @@ Consumer code (e.g., adapter) gets compile-time type safety
157168
158169## 🧰 Troubleshooting (quick)
159170
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> ` .
171+ * ** No thin wrappers generated?**
172+ Ensure wrapper schemas in your OpenAPI spec include the vendor extensions:
173+ ` x-api-wrapper: true ` and ` x-api-wrapper-datatype ` .
174+ Confirm your generator points to the correct ` <templateDirectory> ` ** and** that effective templates are copied (see
175+ the ` maven-dependency-plugin ` + ` maven-resources-plugin ` steps).
176+ If unsure, delete ` target/ ` and run ` mvn clean install ` .
163177
164178* ** Wrong packages or missing classes?**
165179 Ensure ` apiPackage ` , ` modelPackage ` , and ` invokerPackage ` in the plugin configuration match what you expect.
@@ -186,32 +200,37 @@ Consumer code (e.g., adapter) gets compile-time type safety
186200
187201## 🧩 Using the Client
188202
189- ### Option A — Spring Configuration (recommended )
203+ ### Option A — Quick Start (simple RestClient for demos/dev )
190204
191205``` java
192206
193- @Configuration
194- public class CustomerApiClientConfig {
207+ package your.pkg ;
195208
196- @Bean
197- public RestClient customerRestClient (RestClient .Builder builder ,
198- @Value (" ${customer.api.base-url}" ) String baseUrl ) {
199- return builder. baseUrl(baseUrl). build();
200- }
209+ import io.github.bsayli.openapi.client.generated.api.CustomerControllerApi ;
210+ import io.github.bsayli.openapi.client.generated.invoker.ApiClient ;
211+ import org.springframework.beans.factory.annotation.Value ;
212+ import org.springframework.context.annotation.Bean ;
213+ import org.springframework.context.annotation.Configuration ;
214+ import org.springframework.web.client.RestClient ;
201215
202- @Bean
203- public io.github.bsayli.openapi.client.generated.invoker. ApiClient customerApiClient (
204- RestClient customerRestClient ,
205- @Value (" ${customer.api.base-url}" ) String baseUrl ) {
206- return new io.github.bsayli.openapi.client.generated.invoker. ApiClient (customerRestClient)
207- .setBasePath(baseUrl);
208- }
216+ @Configuration
217+ public class CustomerApiClientConfig {
209218
210- @Bean
211- public io.github.bsayli.openapi.client.generated.api. CustomerControllerApi customerControllerApi (
212- io.github.bsayli.openapi.client.generated.invoker. ApiClient apiClient ) {
213- return new io.github.bsayli.openapi.client.generated.api. CustomerControllerApi (apiClient);
214- }
219+ @Bean
220+ RestClient customerRestClient (RestClient .Builder builder ) {
221+ return builder. build();
222+ }
223+
224+ @Bean
225+ ApiClient customerApiClient (RestClient customerRestClient ,
226+ @Value (" ${customer.api.base-url}" ) String baseUrl ) {
227+ return new ApiClient (customerRestClient). setBasePath(baseUrl);
228+ }
229+
230+ @Bean
231+ CustomerControllerApi customerControllerApi (ApiClient customerApiClient ) {
232+ return new CustomerControllerApi (customerApiClient);
233+ }
215234}
216235```
217236
@@ -224,19 +243,32 @@ customer.api.base-url=http://localhost:8084/customer-service
224243** Usage example:**
225244
226245``` java
246+ import io.github.bsayli.openapi.client.generated.api.CustomerControllerApi ;
247+ import io.github.bsayli.openapi.client.generated.dto.CustomerCreateRequest ;
248+ import io.github.bsayli.openapi.client.generated.dto.CustomerCreateResponse ;
249+ import io.github.bsayli.openapi.client.common.ServiceClientResponse ;
250+ import org.springframework.beans.factory.annotation.Autowired ;
251+ import org.springframework.stereotype.Component ;
227252
228- @Autowired
229- private io.github.bsayli.openapi.client.generated.api . CustomerControllerApi customerApi;
253+ @Component
254+ public class CustomerClientExample {
230255
231- public void createCustomer() {
232- var req = new io.github.bsayli.openapi.client.generated.dto. CustomerCreateRequest ()
256+ private final CustomerControllerApi customerApi;
257+
258+ public CustomerClientExample (CustomerControllerApi customerApi ) {
259+ this . customerApi = customerApi;
260+ }
261+
262+ public void createCustomer () {
263+ CustomerCreateRequest req = new CustomerCreateRequest ()
233264 .name(" Jane Doe" )
234265 .email(" jane@example.com" );
235266
236- var resp = customerApi. createCustomer(req); // ServiceResponseCustomerCreateResponse
267+ ServiceClientResponse< CustomerCreateResponse > resp = customerApi. createCustomer(req);
237268
238269 System . out. println(resp. getStatus()); // 201
239270 System . out. println(resp. getData(). getCustomer(). getName()); // "Jane Doe"
271+ }
240272}
241273```
242274
@@ -246,11 +278,22 @@ public void createCustomer() {
246278
247279---
248280
249- ### Option A.2 — Alternative with HttpClient5 (connection pooling)
281+ ### Option B — Recommended (production-ready with HttpClient5 pooling)
250282
251283If you want more control (connection pooling, timeouts, etc.), you can wire the client with ** Apache HttpClient5** :
252284
253285``` java
286+ import io.github.bsayli.openapi.client.generated.api.CustomerControllerApi ;
287+ import io.github.bsayli.openapi.client.generated.invoker.ApiClient ;
288+ import java.time.Duration ;
289+ import org.apache.hc.client5.http.impl.classic.CloseableHttpClient ;
290+ import org.apache.hc.client5.http.impl.classic.HttpClients ;
291+ import org.apache.hc.client5.http.impl.io.PoolingHttpClientConnectionManagerBuilder ;
292+ import org.springframework.beans.factory.annotation.Value ;
293+ import org.springframework.context.annotation.Bean ;
294+ import org.springframework.context.annotation.Configuration ;
295+ import org.springframework.http.client.HttpComponentsClientHttpRequestFactory ;
296+ import org.springframework.web.client.RestClient ;
254297
255298@Configuration
256299public class CustomerApiClientConfig {
@@ -301,15 +344,31 @@ public class CustomerApiClientConfig {
301344 }
302345
303346 @Bean
304- CustomerControllerApi customerControllerApi (ApiClient apiClient ) {
305- return new CustomerControllerApi (apiClient );
347+ CustomerControllerApi customerControllerApi (ApiClient customerApiClient ) {
348+ return new CustomerControllerApi (customerApiClient );
306349 }
307350}
308351```
309352
353+ > ** Requires:** ` org.apache.httpcomponents.client5:httpclient5 ` (already included in this module).
354+
355+ ** application.properties:**
356+
357+ ``` properties
358+ # Base URL
359+ customer.api.base-url =http://localhost:8084/customer-service
360+ # HttpClient5 pool settings
361+ customer.api.max-connections-total =64
362+ customer.api.max-connections-per-route =16
363+ # Timeouts (in seconds)
364+ customer.api.connect-timeout-seconds =10
365+ customer.api.connection-request-timeout-seconds =10
366+ customer.api.read-timeout-seconds =15
367+ ```
368+
310369---
311370
312- ### Option B — Manual Wiring (no Spring context)
371+ ### Option C — Manual Wiring (no Spring context)
313372
314373``` java
315374var rest = RestClient . builder(). baseUrl(" http://localhost:8084/customer-service" ). build();
0 commit comments