Repository navigation
Add swagger-annotations(-jakarta) to springdoc-openapi-bom for annotation-only consumers #3325
Description
Is your feature request related to a problem? Please describe.
We have a multi-module Maven build. Some modules depend on
springdoc-openapi-starter-webmvc-ui and correctly receive the Swagger
annotations transitively at the matching version — no action needed there.
Other modules only put Swagger annotations (@Schema, @Operation, …) on their
DTOs/controllers but do not depend on springdoc at all. They still need
io.swagger.core.v3:swagger-annotations-jakarta on the compile classpath, and
its version must match the swagger-core version that springdoc pulls in
elsewhere, otherwise we risk mixing annotation versions across the application.
Today, because springdoc-openapi-bom does not manage any Swagger artifact,
the only way to keep these modules in sync is to hardcode the version in our
own POM and remember to bump it manually on every springdoc upgrade (we even
have to disable Renovate for these artifacts to prevent drift). A BOM-managed
entry would let these modules declare swagger-annotations-jakarta without a
version and stay automatically in lockstep with springdoc.
This is a follow-up to #3212 ("Add swagger version to BOM"), which was closed
with the recommendation to override swagger-core-jakarta before importing the
BOM. That workaround does not cover this use case (details under Alternatives
and Additional context). The use case sounds similar to #2044.
What is the actual result using OpenAPI Description (yml or json)? — Not
applicable: this is a build / dependency-management concern (Maven & Gradle
version alignment), not about the generated OpenAPI description output.
Describe the solution you'd like
Add the Swagger annotation artifact — and optionally swagger-core-jakarta /
swagger-models-jakarta — to springdoc-openapi-bom's <dependencyManagement>,
versioned via the existing swagger-api.version:
<dependency>
<groupId>io.swagger.core.v3</groupId>
<artifactId>swagger-annotations-jakarta</artifactId>
<version>${swagger-api.version}</version>
</dependency>
<!-- optionally swagger-core-jakarta / swagger-models-jakarta as well -->This lets any consumer that already imports springdoc-openapi-bom declare
swagger-annotations-jakarta without a version and stay in lockstep with the
springdoc release — exactly what a BOM is for — without dragging in
swagger-core or a second Jackson version.
If a managed entry on the existing BOM is genuinely undesirable, the "separate
parent/BOM project" mentioned in #3212 would work just as well for us — the
essential ask is simply a published, version-managed coordinate for the
annotations artifact tied to the springdoc release.
What is the expected result using OpenAPI Description (yml or json)? — Not
applicable (same reason as above); the generated OpenAPI output is unchanged.
Describe alternatives you've considered
-
Manually pinning the annotation version and disabling Renovate for it
(our current approach): works, but is error-prone on every springdoc bump. -
The Add swagger version to BOM #3212 workaround — declaring
swagger-core-jakartawith
${swagger-api.version}before the BOM import:<dependency> <groupId>io.swagger.core.v3</groupId> <artifactId>swagger-core-jakarta</artifactId> <version>${swagger-api.version}</version> </dependency>
Two problems for us:
- It still requires the consumer to define the version: importing
springdoc-openapi-bomdoes not makeswagger-api.versionavailable
(BOM import copies<dependencyManagement>, not<properties>), so
${swagger-api.version}is unresolved unless we declare it ourselves —
manual override, not reuse. It also does not work under Gradle, which
rejects a dependency whose version is an undefined property (as
@HenrikPublic noted in Add swagger version to BOM #3212). - It targets
swagger-core-jakarta, which is far more than annotation-only
modules need — it pulls ~13 transitive dependencies including a
Jackson 2.x stack, whereas our modules run on Jackson 3.
- It still requires the consumer to define the version: importing
-
Importing the
springdoc-openapiparent pom (instead of the BOM) +
depending onswagger-core-jakarta: auto-syncs the version, but forces the
heavy swagger-core transitive tree (incl. Jackson 2.x) onto annotation-only
modules.
Additional context
Question about the "breaking change" concern from #3212. The request there was
declined with:
Adding this to the existing BOM would be a breaking change, as it would force
users to specify the versions manually.
We'd appreciate clarification, because on the face of it this seems backwards: a
managed <dependencyManagement> entry lets consumers omit the version, not
specify it. Our best guess at the intended meaning is that BOM-managed versions
override transitive resolution in the importing project, so an existing user
who imports springdoc-openapi-bom and resolves a different Swagger version
through another path would see it change, and would then have to add an explicit
override to keep the old one. If that is the concern, could you confirm? For the
Swagger artifacts specifically we'd gently push back: any project using springdoc
already resolves springdoc's Swagger version transitively, so pinning the BOM to
that same version would not change what those users get — it would only help
consumers that currently have no managed version at all.
Test results (springdoc-openapi 3.1.0, swagger-api.version 2.2.52).
-
A — import the BOM, use
${swagger-api.version}without defining it:
fails; the property is not wired up by the BOM import:[ERROR] 'dependencies.dependency.version' for io.swagger.core.v3:swagger-core-jakarta must be a valid version but is '${swagger-api.version}' -
B — same, but with
swagger-api.versiondefined by the consumer (2.2.40):
works, but only because the consumer supplied the number (override, not reuse):\- io.swagger.core.v3:swagger-core-jakarta:jar:2.2.40 +- io.swagger.core.v3:swagger-annotations-jakarta:jar:2.2.40 -
C — import the
springdoc-openapiparent pom, nothing defined: the
version flows through automatically (2.2.52), confirming the parent already
manages this — but it only managesswagger-core-jakartaand pulls its full
transitive tree:\- io.swagger.core.v3:swagger-core-jakarta:jar:2.2.52 +- io.swagger.core.v3:swagger-annotations-jakarta:jar:2.2.52
Environment. spring-boot-starter-parent 4.1.0; springdoc-openapi 3.1.0 (swagger-api.version = 2.2.52); Maven 3.9.x.
Activity
Mattias-Sehlstedt commentedon Aug 13, 2026
Hi, you can find further discussion on the subject here.
I am not associated with the project, just a user and a contributor. I have personally managed this in my own projects by defining tests that ensure that my springdoc/swagger-core functionality behaves as expected. This by having tests similar to what springdoc itself has where the application context is created and a spec is rendered. For a DTO project this would then either be resolver tests or that the test suite relies on springdoc but not the application artifact itself. This then allows renovates to run as normal since they will fail entirely in the tests if there has been some level of breaking change.
In general one should be able to trust swagger-core to align to semantic versioning, and that non-aligned annotation versions should behave properly even if not perfectly aligned (I am aware of their back-and-forth with an unintentional breaking change of their
default-value handling, which basically brought up the requirement for a BOM to begin with).feat: manage the swagger artifacts in the BOM
rearl commentedon Sep 8, 2026
Thanks a lot
HenrikPublic commentedon Sep 8, 2026
Thank you!
Next up: Add therapi-runtime-javadoc and therapi-runtime-javadoc-scribe to the bom as well.
Should i create a new issue for that @bnasslahsen ?
michaldo commentedon Sep 11, 2026
BOM 3.1.1 is step in the right direction.
Unfortunately, contains a lot of noise.
https://repo1.maven.org/maven2/org/springdoc/springdoc-openapi-bom/3.1.1/springdoc-openapi-bom-3.1.1.pom contains plenty properties like hibernate.version, spring-ldap.version
#3272 shows how to fix that