spring-boot-openapi-generics-clients — Production‑Ready, Type‑Safe API Clients with Generics #1
Replies: 2 comments
-
|
Is this solution fully compliant with OAS 3.1.1 specs OAI/OpenAPI-Specification#3601. Had a hard time making this work end to end. I.e generate openapi spec from controller -> use that in the client code. |
Beta Was this translation helpful? Give feedback.
-
|
Hi! Thanks for digging into this — getting “controller → spec → client” to work end-to-end with generic envelopes is still surprisingly tricky. On the compliance side: the approach in this repo is OAS 3.1.x compatible, because the generated schemas remain valid OpenAPI/JSON Schema. However, it does not use So you can think of it as a practical compatibility layer:
In other words, you’re right about the “intent”: many toolchains assume a manually-augmented spec. What this project aims to do is make that augmentation happen automatically during spec generation, so the client can stay fully aligned without manual edits. If/when the ecosystem supports |
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
-
💭 How are you handling generics‑aware OpenAPI clients in production?
Hi everyone 👋
Over the last iterations, this repository has evolved into a contract‑first, production‑ready reference architecture for building type‑safe OpenAPI clients with generics — without duplicating envelopes or losing nested types during generation.
The key shift is the introduction of a shared canonical contract module:
This module defines the single source of truth for:
ServiceResponse<T>— unified success envelopeMeta,Page<T>,Sort,SortDirection— paging & metadata primitivesProblemExtensions,ErrorItem) — error detailsBoth server and client reuse this contract directly.
OpenAPI is no longer treated as a code generator of truth, but as a semantic bridge between producer and consumer.
🧠 What problem does this pattern solve?
Many teams standardize on a
{ data, meta }response envelope.But once pagination and nested containers enter the picture, default OpenAPI generation tends to:
This project demonstrates how to:
ServiceResponse<T>,ServiceResponse<Page<T>>)🏗 What this project provides today
api-contract— framework‑agnostic canonical contract shared by server and clientSpring Boot producer publishing an enriched OpenAPI 3.1 spec
OpenAPI schema enricher (
OpenApiCustomizer) that:ServiceResponse<T>in controller signaturesx-api-wrapper,x-data-container, …)OpenAPI Generator 7.x with Mustache overlays producing:
ServiceResponse<T>Page<T>)RFC 9457‑first error handling decoded into
ApiProblemExceptionAdapter boundary so consumers never depend directly on generated APIs
This is not a demo — it is a reference implementation.
🤔 Discussion prompts
I’d love to hear how others are approaching similar problems in real systems:
Even short notes or trade‑offs you’ve encountered are valuable.
📘 Docs & Guides
If you want to explore the full setup:
📦 Repository
https://github.com/bsayli/spring-boot-openapi-generics-clients
🏗 Architecture Overview
Generics‑aware flow from Spring Boot producer → OpenAPI → type‑safe client
📘 Adoption Guides
server-side-adoption
client-side-adoption
📖 Background
This work started with the article:
👉 We Made OpenAPI Generator Think in Generics
Since then, the idea matured into a contract‑driven system where:
💬 If you’re using — or considering — generics‑aware API clients, I’d really value your perspective.
Share what worked, what didn’t, or what you’d do differently.
This discussion is meant to surface real‑world constraints, not just happy paths.
Beta Was this translation helpful? Give feedback.
All reactions