Add swagger-annotations(-jakarta) to springdoc-openapi-bom for annotation-only consumers
envgap__springdoc__springdoc-openapi-3325
01 / FAILURE SIGNATURE
As reported upstream
[ERROR] 'dependencies.dependency.version' for io.swagger.core.v3:swagger-core-jakarta
Not a benchmark task.
- The project already builds and runs before the fix, so there is nothing to repair.
02 / ENVIRONMENT RECIPE
- Base commit
7247cae4102787d1aa847b8b53d16713a8ca230f- Manifest
springdoc-openapi-bom/pom.xml- Reproduce
Awaiting issue-specific recipe- Run under trace
Awaiting a meaningful runtime command
03 / ORIGINAL ISSUE TEXT
springdoc/springdoc-openapi #3325 · read the original issue
**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`:
```xml
<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**
1. **Manually pinning the annotation version** and disabling Renovate for it
(our current approach): works, but is error-prone on every springdoc bump.
2. **The #3212 workaround** — declaring `swagger-core-jakarta` with
`${swagger-api.version}` before the BOM import:
```xml
<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-bom` does not make `swagger-api.version` available
(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 #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.
3. **Importing the `springdoc-openapi` parent pom** (instead of the BOM) +
depending on `swagger-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.version` defined 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-openapi` *parent* pom, nothing defined:** the
version flows through automatically (2.2.52), confirming the parent already
manages this — but it only manages `swagger-core-jakarta` and 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.
04 / LABELS
Labels from the report text only; not yet run
No supported category has been assigned.
Label rules and the text that matched
[]