skip to content

How do you override a version that the Spring Boot BOM manages, and what are the risks?

level: seniorimportance: should knowfreq 50%

answer

  1. parent: <lib.version> property
  2. import: redeclare, first-match wins
  3. Gradle plugin: ext version property
  4. native: explicit version / constraint
  5. risk: leaves tested matrix -> NoSuchMethodError

basics

~10 s

With the Boot parent, override the documented version property (e.g. <jackson-bom.version>). With Gradle plugin, set the matching ext property. Or declare an explicit version on the dependency. The risk: you break the tested-compatible set.

solid answer

~40 s

There are three override paths depending on setup. (1) With spring-boot-starter-parent (Maven), redefine the documented version property in <properties> — Spring Boot exposes properties like <jackson-bom.version> or <hibernate.version> that the parent's managed entries reference. (2) With a BOM import (Maven, no parent), property overrides usually don't work, so you add your own <dependencyManagement> entry (or import a newer BOM for that library) before the Boot BOM; your entry wins. (3) In Gradle with io.spring.dependency-management, set the ext property (e.g. set("jackson.version", "...")); with native platform(), declare an explicit version or a constraint. The main risk: you leave the mutually-tested version matrix. Bumping one library can pull in incompatible transitive APIs and cause NoSuchMethodError/NoClassDefFound at runtime, and CVEs may exist in versions Spring hasn't validated. Prefer upgrading Spring Boot itself when possible.

code

kotlin · 15 lines
kotlin
// Gradle native platform(): override one managed version safely-ish
dependencies {
    implementation(platform("org.springframework.boot:spring-boot-dependencies:3.3.4"))
    implementation("org.springframework.boot:spring-boot-starter-web")

    // Explicit version wins over the BOM constraint
    implementation("com.fasterxml.jackson.core:jackson-databind:2.18.0")
}

// Better: keep the whole Jackson family aligned via a constraint
dependencies {
    constraints {
        implementation("com.fasterxml.jackson:jackson-bom:2.18.0")
    }
}

go deeper

for a junior

Know you can put an explicit version to override the BOM default.

for a middle

Use the parent's version property (e.g. jackson-bom.version) to override.

for a senior

Handle import-scope and Gradle override paths and keep families aligned.

for a principal

Set policy: prefer Boot upgrades, family-level overrides for CVEs, tracked and time-boxed, verified via dependency reports.

## Why you'd override You need a newer library than the BOM pins — commonly to pick up a **security fix (CVE)** before a new Spring Boot release, or to get a feature. The BOM value is a curated default, not a hard lock; every mechanism lets you override, but each differs by build setup. ## Maven with the parent — version properties The Spring Boot reference documents a set of **version properties** the parent's managed dependencies reference indirectly. Redefining the property in your `<properties>` changes the managed version: ```xml <properties> <jackson-bom.version>2.18.0</jackson-bom.version> </properties> ``` Property names are documented (e.g. `jackson-bom.version`, `hibernate.version`, `mockito.version`). This is the cleanest override with the parent because it keeps the whole library family (e.g. all Jackson modules) aligned. ## Maven with BOM import (no parent) — redeclare When you use `<scope>import</scope>` rather than the parent, the version **properties generally do not take effect** (importing merges only the resolved `dependencyManagement` entries, not the property-driven indirection reliably). Override by adding your own management entry, which must appear so it wins by first-match: ```xml <dependencyManagement> <dependencies> <!-- your override wins because it's declared first --> <dependency> <groupId>com.fasterxml.jackson</groupId> <artifactId>jackson-bom</artifactId> <version>2.18.0</version> <type>pom</type> <scope>import</scope> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-dependencies</artifactId> <version>3.3.4</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement> ``` ## Gradle - **io.spring.dependency-management plugin**: set the ext property Spring's Gradle conventions read, e.g. `extra["jackson.version"] = "2.18.0"` (the Boot Gradle plugin recognizes a documented set of `*.version` extras), or use a `dependencyManagement { dependencies { dependency("...") } }` override. - **Native platform()**: declare the explicit coordinate+version, or add a `constraints { implementation("grp:art:ver") }`, or `resolutionStrategy.force(...)`. ## Risks — the whole point of the BOM is coherence 1. **Compatibility break**: Spring tested version *N*; you jump to *N+2*. If Spring modules call APIs that changed, you get `NoSuchMethodError`, `NoClassDefFoundError`, or subtle behavior changes at runtime, not compile time. 2. **Family drift**: overriding one Jackson artifact but not the others causes mixed-version Jackson on the classpath — override the **BOM/property for the whole family**, not a single artifact. 3. **Downgrades**: forcing an older version to satisfy something can break Boot's assumptions. 4. **Maintenance debt**: your override may later conflict with a Boot upgrade that pins something higher/lower. ## Best practice - Prefer **upgrading Spring Boot** (and thus the whole BOM) over pinning one library. - If you must override for a CVE, override at the **family BOM/property** granularity and add a comment + tracking issue to remove it after the next Boot bump. - Verify with tests and a dependency report (`mvn dependency:tree`, `gradle dependencies`).

  • Why is overriding a single jackson-databind version riskier than bumping the jackson-bom?
    Spring and other libs use several Jackson artifacts (core, annotations, databind, modules). Bumping only databind leaves mismatched versions on the classpath, which can cause linkage errors. Overriding the whole jackson-bom keeps the family consistent.
  • When should you NOT override and instead upgrade Spring Boot?
    Almost always — upgrading Boot moves the entire tested matrix forward, preserving compatibility guarantees. Override only as a temporary bridge (e.g. urgent CVE) until the next Boot release.

saying these in an interview costs you the question

  • Overriding one artifact of a multi-artifact family (mixed Jackson versions).
  • Assuming version properties work with BOM import the same as with the parent.
  • Treating BOM versions as immutable and claiming they can't be overridden at all.

context