skip to content

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

level: middleimportance: must knowfreq 65%

answer

  1. type=pom + scope=import
  2. inside dependencyManagement only
  3. one-parent limit workaround
  4. lose maven-plugin/filtering, re-add
  5. override by redeclaring dep version

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.

solid answer

~40 s

Add a <dependencyManagement> section to your POM and, inside it, a dependency on org.springframework.boot:spring-boot-dependencies with <type>pom</type> and <scope>import</scope>. The import scope tells Maven to inline that BOM's own dependencyManagement entries into yours, so all Boot-managed versions apply and you can declare starters without versions. You do this when your project already has another <parent> (Maven allows only one parent) or you simply don't want the Boot parent's extra plugin/resource configuration. The trade-off: you lose what the parent adds — the configured spring-boot-maven-plugin, resource filtering of application.properties, sensible plugin versions, and the Java release setting — so you configure those yourself. To override a managed version when using import scope, declare that dependency's version earlier/explicitly in your own dependencyManagement, since the first matching entry wins.

code

java · 27 lines
java
// pom.xml — import the BOM without the Spring Boot 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>
//
// <dependencies>
//   <dependency>
//     <groupId>org.springframework.boot</groupId>
//     <artifactId>spring-boot-starter-web</artifactId>   <!-- no version -->
//   </dependency>
// </dependencies>
//
// <build><plugins>
//   <plugin>
//     <groupId>org.springframework.boot</groupId>
//     <artifactId>spring-boot-maven-plugin</artifactId>
//     <version>3.3.4</version>   <!-- must supply: no parent to inherit it -->
//   </plugin>
// </plugins></build>

go deeper

for a junior

Recognize that import scope exists as an alternative to the Boot parent.

for a middle

Write the exact dependencyManagement entry with type=pom and scope=import.

for a senior

Enumerate what the parent adds that import loses and how to re-add it.

for a principal

Reason about corporate-parent constraints, multi-BOM ordering, and override strategy differences between parent vs import.

## The problem The usual Spring Boot setup makes `spring-boot-starter-parent` your project's `<parent>`. That parent transitively imports the `spring-boot-dependencies` BOM and *also* adds: a preconfigured `spring-boot-maven-plugin`, dependency-plugin versions, UTF-8/Java `release` settings, and property-filtering of `application.properties`/`application.yml`. But Maven allows a project to have **only one parent**. If your organization mandates a corporate parent POM, you can't also inherit the Boot parent. ## The solution: import scope Maven's `<scope>import</scope>` (only valid on a `<dependency>` of `<type>pom</type>` inside `<dependencyManagement>`) tells Maven: 'take that POM's `<dependencyManagement>` block and merge its entries into mine'. So you get every Boot-managed version without any parent relationship: ```xml <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> ``` After this, `spring-boot-starter-web` and friends can be declared with no `<version>`. ## What you give up (and must re-add) With import-only you do **not** inherit the parent's build configuration, so you typically add manually: - The `spring-boot-maven-plugin` in `<build><plugins>` (for `repackage`, `bootRun`) — and you must give it a `<version>` since no parent supplies one. - Java version via `<maven.compiler.release>` or the compiler plugin. - Resource filtering if you want `@...@` placeholder substitution in `application.properties`. ## Overriding a managed version Because import merges the BOM's entries into your dependencyManagement, and Maven resolves managed versions by the **first declared match**, you override a Boot-pinned library by declaring your own `<dependency>` for it in your `<dependencyManagement>` **before/above** the BOM import, or simply anywhere in your own dependencyManagement since your explicit entry takes precedence. (With the *parent* approach you instead override by setting the documented Maven property, e.g. `<jackson-bom.version>`.) ## Gotchas - `<scope>import</scope>` is legal **only** inside `<dependencyManagement>` and only with `<type>pom</type>`; using it on a normal `<dependency>` does nothing useful. - Import scope is **not transitive** and imports only the `dependencyManagement` section, not the BOM's plugins or properties. So Boot-parent property-style overrides (`<xyz.version>`) generally won't work through a plain import — override by redeclaring the dependency version. - You can import multiple BOMs; order matters because first-match wins on conflicts.

  • Why can't you just add spring-boot-starter-parent as a second parent?
    Maven permits only one <parent> per POM. If you already inherit another parent, importing the BOM with scope=import is the way to still get Boot's managed versions.
  • With the import approach, how do you override Jackson's version?
    Declare an explicit dependencyManagement entry for jackson-databind (or import the jackson BOM) in your own POM; your entry wins over the Boot BOM. Property overrides like <jackson-bom.version> only work reliably with the parent, not a plain import.

saying these in an interview costs you the question

  • Using <scope>import</scope> outside dependencyManagement or without type=pom.
  • Assuming import also brings the spring-boot-maven-plugin and resource filtering.
  • Trying to add the Boot parent as an additional parent.

context