skip to content

Starters & Dependency Management

How Boot manages dependencies: starter artifacts that pull a coherent stack, the parent POM, the dependency BOM, and what happens when you override a managed version. Interviewers ask so they can hear you talk about version alignment rather than copy-pasted coordinates.

part ofSpring Frameworkoverview, primer and where to startread it →
on this pageshow

explore

questions

20

What is the spring-boot-dependencies BOM and what problem does it solve?

level: juniorimportance: must knowfreq 70%

answer

  1. packaging=pom, only dependencyManagement
  2. curated, tested-together versions
  3. declare starters with no version
  4. version == Boot version
  5. manages versions, adds nothing

basics

~10 s

spring-boot-dependencies is a BOM (Bill of Materials): a special POM listing tested, compatible versions of Spring and third-party libraries. Import it so you declare dependencies without versions and get a consistent, curated version set.

solid answer

~40 s

The spring-boot-dependencies BOM is a Maven POM of packaging type 'pom' that contains a large <dependencyManagement> section pinning versions for hundreds of libraries Spring Boot tests together (Spring modules, Jackson, Hibernate, Tomcat, Kotlin, etc.). By importing it, your build inherits those managed versions, so you declare dependencies like spring-boot-starter-web with no <version> element. The BOM only manages versions, it doesn't add any dependencies to your build. The benefit is a single curated, mutually-compatible dependency set that eliminates version guesswork and reduces conflicts. Its version equals the Spring Boot version you target. It is the same version data the spring-boot-starter-parent uses under the hood, but importing the BOM directly lets you use it without inheriting the Boot parent POM.

code

kotlin · 17 lines
kotlin
// Excerpt of what spring-boot-dependencies conceptually contains (Maven POM view):
// <dependencyManagement>
//   <dependencies>
//     <dependency>
//       <groupId>com.fasterxml.jackson.core</groupId>
//       <artifactId>jackson-databind</artifactId>
//       <version>2.17.2</version>
//     </dependency>
//     ... hundreds more ...
//   </dependencies>
// </dependencyManagement>
//
// Result in your build.gradle.kts (versions omitted, resolved from BOM):
dependencies {
    implementation("org.springframework.boot:spring-boot-starter-web")
    implementation("com.fasterxml.jackson.module:jackson-module-kotlin")
}

go deeper

for a junior

Know it's a curated list of compatible versions letting you omit versions on starters.

for a middle

Explain packaging=pom, dependencyManagement-only, and that it adds nothing.

for a senior

Contrast parent-inheritance vs direct import and note version-override precedence.

for a principal

Frame it as the reproducible, tested dependency contract and its role in supply-chain/version governance.

## What a BOM is A **BOM (Bill of Materials)** is a normal Maven POM whose `<packaging>` is `pom` and whose main purpose is a large `<dependencyManagement>` block. `<dependencyManagement>` does **not** add dependencies to a project — it only declares *what version to use* if and when a given dependency is requested. Think of it as a lookup table: 'if anyone asks for `com.fasterxml.jackson.core:jackson-databind`, use version X'. ## spring-boot-dependencies specifically `org.springframework.boot:spring-boot-dependencies` is the BOM Spring Boot publishes. Its version string equals the Spring Boot release you target (e.g. `3.3.4`). Inside it are managed versions for: - Every Spring Boot and Spring Framework module (spring-core, spring-web, spring-context, all the `spring-boot-starter-*` artifacts). - Hundreds of third-party libraries Spring Boot integrates with and **tests together**: Jackson, Hibernate/JPA, Tomcat/Jetty/Undertow, Netty, Micrometer, Logback/SLF4J, Kotlin, JUnit, Mockito, Testcontainers, and so on. Because Spring engineers run integration tests against this exact combination, the versions are known to be mutually compatible. That is the core value: you don't hand-pick versions and risk `NoSuchMethodError` from a Jackson/Hibernate mismatch. ## How you consume it When the BOM's managed versions are in effect, you write dependencies **without a version**: ```xml <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> <!-- no <version> --> </dependency> ``` Maven resolves the version from dependency management. There are two ways to bring the BOM in: 1. **Inherit `spring-boot-starter-parent`** — the parent POM itself imports spring-boot-dependencies, plus adds plugin config, resource filtering, Java version, etc. 2. **Import the BOM directly** with `<scope>import</scope>` — gives you only the version management, no parent inheritance. Useful when your project already has another parent (a corporate parent POM) since Maven allows only one parent. ## Key gotchas - Importing the BOM adds **zero** dependencies — you still declare each starter you want; it only supplies versions. - The BOM version must match the Spring Boot version you actually use; mixing a `3.3.x` BOM with `3.4.x` starters is unsupported. - A `<dependency>` version you write explicitly always wins over the BOM's managed version (nearest/explicit wins), which is how you override. ## When to use Always, for any Spring Boot project. Use the parent for greenfield apps; use the import scope when you can't inherit the Boot parent.

  • Does importing the BOM add spring-boot-starter-web to your classpath?
    No. A BOM only supplies managed versions via dependencyManagement. You still declare each dependency yourself; the BOM just fills in the version.
  • What version should the spring-boot-dependencies BOM be?
    The same as the Spring Boot version you target — the BOM is versioned in lockstep with each Boot release, e.g. 3.3.4.

saying these in an interview costs you the question

  • Saying the BOM downloads/adds dependencies by itself.
  • Thinking you must still specify versions on starters after importing it.
  • Believing you need the Boot parent POM to get managed versions.

context

open as a page

What is spring-boot-starter-parent and why do Spring Boot projects use it as their Maven parent?

level: juniorimportance: must knowfreq 70%

basics

~20 s

It is a special Maven parent POM you inherit from. It sets sensible defaults for you: dependency versions, a Java version, UTF-8 encoding, and it configures the plugin that builds a runnable Spring Boot jar — so you write far less pom.xml.

open as a page

What is a Spring Boot starter, and what problem does it solve?

level: juniorimportance: must knowfreq 85%

basics

~20 s

A starter is one dependency coordinate that pulls in a curated, version-aligned set of libraries for a feature. Example: spring-boot-starter-web adds Spring MVC, embedded Tomcat, and Jackson together, so you declare one line instead of hand-picking and version-matching many jars.

open as a page

In a Maven project that uses spring-boot-starter-parent, how do you override the version of a dependency that Spring Boot manages for you?

level: juniorimportance: must knowfreq 55%

basics

~10 s

Redefine the version property in your own <properties> block. Spring Boot's parent POM sets properties like jackson-bom.version; declaring the same property in your pom.xml overrides the managed version everywhere it's used.

open as a page

In Maven, how do you use the Spring Boot managed versions without inheriting spring-boot-starter-parent?

level: middleimportance: must knowfreq 65%

basics

~10 s

Import the BOM in <dependencyManagement> with type 'pom' and <scope>import</scope>. That pulls in spring-boot-dependencies' managed versions without making the Boot parent your project's parent.

open as a page

How does Spring Boot keep all the libraries a starter pulls version-aligned? Explain the role of spring-boot-starter-parent vs importing the BOM.

level: middleimportance: must knowfreq 70%

basics

~20 s

Versions live in the spring-boot-dependencies BOM — a dependencyManagement list of managed versions. You inherit it either by using spring-boot-starter-parent as your Maven parent, or by importing spring-boot-dependencies directly (Gradle's Boot plugin does this for you). Starters then omit versions.

open as a page

What are the risks of overriding a Spring Boot managed version, and how do you decide whether an override is safe?

level: seniorimportance: must knowfreq 48%

basics

~20 s

Each Boot release is tested against one specific dependency set. Overriding moves you off it, risking binary incompatibilities, transitive conflicts, and behavior changes Boot never validated. Justify each override (e.g. a CVE fix), keep it minimal, and test.

open as a page

How do the java.version property and encoding settings inherited from the parent affect the build, and how do you change the Java version?

level: middleimportance: should knowfreq 55%

basics

~10 s

The parent sets a default Java level and UTF-8 encoding. To compile for a different JDK, set <java.version>21</java.version> in your <properties>; that flows into the compiler plugin. UTF-8 encoding keeps builds identical across machines.

open as a page

spring-boot-starter-web ships embedded Tomcat. How would you switch the embedded server to Jetty (or Undertow) instead?

level: middleimportance: should knowfreq 45%

basics

~10 s

Exclude spring-boot-starter-tomcat from spring-boot-starter-web, then add spring-boot-starter-jetty (or spring-boot-starter-undertow). Auto-configuration detects Jetty on the classpath and starts it as the embedded server instead of Tomcat.

open as a page

You import spring-boot-dependencies as a BOM (scope=import) instead of using spring-boot-starter-parent. How do you override a managed version now, and why is it different?

level: middleimportance: should knowfreq 45%

basics

~10 s

Property overrides no longer work. Add your own <dependencyManagement> entry with the desired version, declared BEFORE the imported spring-boot-dependencies BOM. Maven's 'first declaration wins' for imported BOMs makes your entry take precedence.

open as a page

In Gradle, what are the two ways to consume the Spring Boot BOM, and how do they differ?

level: seniorimportance: should knowfreq 55%

basics

~10 s

Either use Gradle's native platform() (e.g. implementation(platform("org.springframework.boot:spring-boot-dependencies:3.3.4"))) or apply the io.spring.dependency-management plugin. platform() is Gradle-native; the plugin mimics Maven-style dependency management.

open as a page

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

level: seniorimportance: should knowfreq 50%

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.

open as a page

How does inheriting the parent make `mvn package` produce an executable fat jar? Explain the repackage goal wiring.

level: seniorimportance: should knowfreq 45%

basics

~20 s

The parent's plugin management binds the spring-boot-maven-plugin's repackage goal to Maven's package phase. So after Maven builds the plain jar, the plugin rewrites it into a self-contained runnable jar (with nested dependencies and a launcher) automatically.

open as a page

The parent enables resource filtering with @...@ delimiters instead of the default ${...}. Why, and how would you inject the Maven build version into application.properties?

level: seniorimportance: should knowfreq 40%

basics

~10 s

Spring's own config uses ${...} placeholders, which would collide with Maven's filtering. So the parent switches Maven's resource-filtering delimiter to @, letting you write @project.version@ in application.properties while Spring's ${...} stays untouched.

open as a page

How would you author your own reusable starter for an internal library, and what are the conventions?

level: seniorimportance: should knowfreq 35%

basics

~20 s

Split it in two: an autoconfigure module with @AutoConfiguration classes (registered in META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports), and a thin starter module that just depends on the autoconfigure module plus required libraries. Name it acme-spring-boot-starter (name first, not the reserved spring-boot-starter- prefix).

open as a page

How do you override a Spring Boot managed dependency version in a Gradle build, and what does strictly() add over resolutionStrategy.force?

level: seniorimportance: should knowfreq 42%

basics

~20 s

Simplest: set an extra property matching Boot's version property, e.g. ext['slf4j.version'] = '2.0.13'. You can also use a strict version constraint or resolutionStrategy.force. strictly() fails the build on an incompatible conflict; force silently rewrites the version.

open as a page

Your org mandates a corporate parent POM, so you can't use spring-boot-starter-parent. What's the alternative, and what exactly do you give up?

level: principalimportance: should knowfreq 35%

basics

~20 s

Import the spring-boot-dependencies BOM in <dependencyManagement> with scope=import. You keep managed versions but lose the parent's extras: Java version property, UTF-8 encoding, plugin management, @-delimiter resource filtering, and the automatic repackage wiring — all of which you must configure yourself.

open as a page

In a multi-module build importing several BOMs, how do version conflicts resolve, and how would you govern this across an organization?

level: principalimportance: nice to knowfreq 30%

basics

~20 s

When multiple BOMs manage the same artifact, Maven picks the first-declared entry (first-wins), while Gradle merges constraints and resolves to the highest compatible unless enforced. Govern with a single company platform/BOM module that all projects import.

open as a page

At org scale, curated starters can pull large transitive graphs (bloat, unwanted CVE-carrying jars, duplicate logging bindings). How do you keep dependency hygiene while still benefiting from starters?

level: principalimportance: nice to knowfreq 25%

basics

~20 s

Keep the version alignment from the BOM but prune what you don't use: exclude unwanted transitive jars (e.g. resolve duplicate logging bindings), audit the resolved graph with dependency:tree / dependencies, enforce via a shared internal BOM/platform, and let auto-config back off for absent classes so unused starters aren't force-added.

open as a page

As a tech lead across many services, how would you govern dependency-version overrides so teams can patch CVEs without silently drifting off Spring Boot's tested baseline?

level: principalimportance: nice to knowfreq 22%

basics

~20 s

Standardize how versions are managed (shared parent/platform), require every override to be justified, minimal, and time-boxed, verify with dependency-tree checks and tests in CI, and review overrides each Boot upgrade to retire ones the new baseline covers.

open as a page