Files
spring-boot-demo/openapi-versioning/README.md
T
asmhatreandClaude Sonnet 5 8d0efb0d4b Add openapi-versioning: springdoc-openapi 3.1.1 vs Spring Framework 7 API versioning
Companion module for "springdoc-openapi with Spring Boot 4.1: Generating,
Customising and Versioning Your API Spec". Reuses the ApiVersionConfigurer
setup from the versioning-mechanics companion project and tests what
springdoc-openapi 3.1.1 actually generates for a path with multiple
version-scoped handlers: a default oneOf-merged operation with an
arbitrary operationId, a working GroupedOpenApi + OpenApiCustomizer fix
that collapses it to one clean schema per version, and a check of the
officially-versioning-supported functional-endpoint path (springdoc
v3.0.2's "Add support for Spring Framework API Versioning with Functional
Endpoints"), which turns out to document only one of two registered
versions rather than either version separately.

Co-Authored-By: Claude Sonnet 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01M1uZDXWkY1MnTfQgt4HMeQ
2026-09-17 19:31:42 +00:00

54 lines
3.4 KiB
Markdown

# openapi-versioning
Companion code for **springdoc-openapi with Spring Boot 4.1: Generating, Customising and
Versioning Your API Spec** on [ankurm.com](https://ankurm.com).
Reuses the exact `ApiVersionConfigurer` setup from the companion project for [Spring Framework 7
API Versioning: The Complete Guide](https://ankurm.com/spring-framework-7-api-versioning-guide/)
and asks one question on top of it: once springdoc-openapi 3.1.1 is added, what does it actually
generate for a path with multiple `version`-scoped handlers — and how do you get a clean,
per-version spec out of it?
**Tested with:** Spring Boot 4.1.1 / Spring Framework 7.0.9 / springdoc-openapi 3.1.1 / JDK 25
(Temurin 25.0.4.1+1).
## Quickstart
```bash
mvn test # runs everything, regenerates docs/output/
mvn spring-boot:run # then, in another shell:
curl http://localhost:8080/v3/api-docs # the merged oneOf (default)
curl http://localhost:8080/v3/api-docs/accounts-v2 # the collapsed, clean v2-only spec
open http://localhost:8080/swagger-ui.html # group selector: default / accounts-v1 / accounts-v1.1 / accounts-v2
```
## Where things are
| | |
|---|---|
| Versions and setup | [docs/01-versions-and-setup.md](docs/01-versions-and-setup.md) |
| What springdoc actually generates for a versioned path | [docs/02-what-springdoc-actually-generates.md](docs/02-what-springdoc-actually-generates.md) |
| Why the fix's version→schema map is hand-maintained | [docs/03-why-a-hand-maintained-map.md](docs/03-why-a-hand-maintained-map.md) |
| The functional-endpoint path: officially supported, and worse | [docs/04-the-functional-endpoint-path.md](docs/04-the-functional-endpoint-path.md) |
| The fix: one GroupedOpenApi per version | [docs/05-the-grouped-openapi-fix.md](docs/05-the-grouped-openapi-fix.md) |
| Known issues, checked directly | [docs/06-known-issues.md](docs/06-known-issues.md) |
## Captured output
Every figure quoted in the article is one of these files, regenerated by `mvn test`:
| File | What it shows |
|---|---|
| [docs/output/00-versions.txt](docs/output/00-versions.txt) | Exact resolved versions, including Maven Central metadata for springdoc 3.1.1 |
| [docs/output/01-versioned-runtime-behaviour.txt](docs/output/01-versioned-runtime-behaviour.txt) | The three `/accounts/{id}` versions serving their real, distinct shapes |
| [docs/output/02-what-springdoc-actually-generates.txt](docs/output/02-what-springdoc-actually-generates.txt) | The default `/v3/api-docs` merging all three versions into one `oneOf` operation |
| [docs/output/05-grouped-openapi-fix.txt](docs/output/05-grouped-openapi-fix.txt) | Three `GroupedOpenApi` groups, each collapsed to one clean schema |
| [docs/output/06-functional-endpoint-path.txt](docs/output/06-functional-endpoint-path.txt) | The officially-versioning-supported functional-endpoint path silently documenting only one of two registered versions |
## Source layout
- `web/` — the annotated `@GetMapping(version = ...)` `AccountController` and its three response records.
- `functional/` — the `RouterFunction`-based `WidgetHandler`/`WidgetRouterConfig`, Framework 7's officially-versioning-supported alternative.
- `config/WebConfig.java` — the `ApiVersionConfigurer` setup, unchanged from the versioning-mechanics companion project.
- `config/VersionedOpenApiConfig.java` — the three per-version `GroupedOpenApi` beans and the `OpenApiCustomizer` that makes them clean.