Managing Dependency Versions & Conflicts
Learn how spring-boot-starter-parent and the Spring Boot BOM manage dependency versions for you, how to inspect the dependency tree, and how to resolve version conflicts.
Introduction
Across the last 24 lessons, you added dozens of Spring Boot starters and almost never wrote a version number. That is not an accident — it is one of Spring Boot's most valuable, least visible features. This lesson pulls back the curtain on how it works, and what to do the rare times it does not.
- How spring-boot-starter-parent supplies default versions for every starter you have used so far.
- How to get the same benefit when you cannot use it as your parent POM, via the spring-boot-dependencies BOM.
- How to inspect the actual resolved dependency tree of your project.
- How to resolve a real version conflict using an exclusion.
Why This Lesson Matters
Every starter used throughout this course — web, data JPA, security, mail, Kafka, Quartz, and more — was added without a <version> tag, and every one of them just worked together. That consistency comes from a curated, tested set of versions maintained by the Spring Boot team, and understanding how you plug into that set is what turns you from someone who copies dependency snippets into someone who can actually debug a broken build.
spring-boot-starter-parent
Most Spring Boot projects declare spring-boot-starter-parent as their Maven <parent>. It supplies default versions for hundreds of common dependencies (including every Spring Boot starter), sensible plugin defaults, and a default Java version — all inherited automatically.
<parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>3.3.4</version></parent>
<dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> <!-- no <version> needed - inherited from the parent --> </dependency></dependencies>Bumping the single <version> on spring-boot-starter-parent (say, from 3.3.4 to 3.4.0) updates the default version of every managed dependency at once, all tested together as a compatible set by the Spring Boot team.
The BOM Alternative: spring-boot-dependencies
Sometimes your project already has a different required parent POM (for example, a company-wide corporate parent) and cannot also inherit from spring-boot-starter-parent — Maven only allows one <parent>. In that case, import spring-boot-dependencies as a Bill of Materials (BOM) inside <dependencyManagement> instead. This gives you the exact same version-management benefit without requiring it to be your parent.
<dependencyManagement> <dependencies> <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><type>pom</type> and <scope>import</scope> together tell Maven to merge that POM's <dependencyManagement> section into your own, rather than adding it as an actual dependency. This is the standard mechanism for consuming any BOM, not just Spring Boot's.
Inspecting the Dependency Tree
Every starter pulls in transitive dependencies of its own, and those can overlap or conflict across starters. Before assuming a version problem, always look at what Maven or Gradle actually resolved.
mvn dependency:treegradle dependenciesClick Run to see what this code prints.
Resolving a Version Conflict with Exclusions
Occasionally a third-party library you add pulls in an older or conflicting transitive version of something Spring Boot already manages (a classic example: an older logging library pulling in a conflicting SLF4J binding). The fix is an <exclusion> — tell Maven to skip that specific transitive dependency, then let the version supplied by spring-boot-starter-parent (or the BOM) win instead.
<dependency> <groupId>com.some-vendor</groupId> <artifactId>some-legacy-sdk</artifactId> <version>1.8.0</version> <exclusions> <exclusion> <groupId>org.slf4j</groupId> <artifactId>slf4j-log4j12</artifactId> </exclusion> </exclusions></dependency>Click Run to see what this code prints.
Common Mistakes
- Manually pinning a <version> on a starter "just to be safe" — this opts you out of Spring Boot's tested version set and is a common source of subtle incompatibilities.
- Trying to use both spring-boot-starter-parent and a different <parent> at the same time — Maven only allows one.
- Ignoring dependency:tree output and guessing at version conflicts instead of reading the actual resolved tree.
- Excluding a transitive dependency without understanding why it was pulled in, potentially breaking the library that needed it.
Best Practices
- Let spring-boot-starter-parent (or the BOM) manage versions for anything it already covers — do not override without a specific reason.
- Run mvn dependency:tree whenever you see an unexpected NoSuchMethodError or ClassNotFoundException at runtime — it is almost always a version conflict.
- Keep your Spring Boot version current; upgrades bring a coordinated, tested set of dependency versions, not just a numbers bump.
- Document why an exclusion exists with a code comment, since future maintainers will not know the history behind it.
Frequently Asked Questions
Your explicit version overrides the one from the parent/BOM for that dependency, which can silently break compatibility with the rest of the managed set — generally avoid it unless you have a specific, understood reason.
No, it provides the identical version management. The only difference is that it does not also set parent-level plugin defaults, so you would configure those yourself if needed.
Check the Spring Boot project's official releases page for the current stable version, and check compatibility if you are on an older Java version.
Summary
spring-boot-starter-parent (or the spring-boot-dependencies BOM when you cannot use it as your parent) is why you have not needed to specify a version number across this entire course. When something does conflict, dependency:tree shows you the truth, and <exclusion> lets you fix it precisely.
- You understand how spring-boot-starter-parent supplies default dependency versions.
- You know when and how to use the spring-boot-dependencies BOM instead.
- You can inspect a project's real dependency tree.
- You resolved a version conflict using an exclusion.