Files
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

3.4 KiB

openapi-versioning

Companion code for springdoc-openapi with Spring Boot 4.1: Generating, Customising and Versioning Your API Spec on ankurm.com.

Reuses the exact ApiVersionConfigurer setup from the companion project for Spring Framework 7 API Versioning: The Complete 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

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
What springdoc actually generates for a versioned path 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
The functional-endpoint path: officially supported, and worse docs/04-the-functional-endpoint-path.md
The fix: one GroupedOpenApi per version docs/05-the-grouped-openapi-fix.md
Known issues, checked directly 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 Exact resolved versions, including Maven Central metadata for springdoc 3.1.1
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 The default /v3/api-docs merging all three versions into one oneOf operation
docs/output/05-grouped-openapi-fix.txt Three GroupedOpenApi groups, each collapsed to one clean schema
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.