How do you import a BOM in Maven, and what does it accomplish?
answer
- type=pom + scope=import
- BOM = only dependencyManagement
- frees the single parent slot
- import many BOMs
- local pin / first-import wins
basics
~20 sA BOM (Bill of Materials) is a POM that only declares versions in its <dependencyManagement>. You import it by adding it inside your own <dependencyManagement> with <type>pom</type> and <scope>import</scope>. Then you use its libraries without specifying versions.
solid answer
~40 sA BOM is a special POM whose only job is to publish a curated, mutually-compatible set of versions in its <dependencyManagement>. You consume it via import scope: inside YOUR <dependencyManagement>, add the BOM artifact with <type>pom</type> and <scope>import</scope>. Maven inlines all of the BOM's managed entries into yours. Now your modules list libraries in <dependencies> without versions and get the BOM-blessed ones. This is how spring-boot-dependencies, jackson-bom, etc. work. Import scope is specifically needed because a BOM is a POM, not a jar, and because Maven inheritance only allows a single parent — import lets you pull in many BOMs without consuming the parent slot. Your own <dependencyManagement> entries override imported ones, and import order matters (first-declared wins on conflicts).
code
xml · 11 lines<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>3.3.1</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>go deeper
Knows a BOM centralizes versions and is imported with type=pom and scope=import.
Can write the import block and explain why import frees the parent slot and lets you import many BOMs.
Understands override/ordering rules and chooses import vs parent-BOM deliberately.
Publishes an internal org BOM to standardize versions across teams and governs its upgrade cadence.
## What a BOM is **BOM = Bill of Materials.** It is a published `pom.xml` (packaging `pom`) that contains *only* a `<dependencyManagement>` block listing a coherent set of artifact versions that are known to work together. Examples: `spring-boot-dependencies`, `jackson-bom`, `junit-bom`, `testcontainers-bom`. A BOM ships no code — just version policy. ## Why 'import' scope exists Maven inheritance gives each POM exactly one `<parent>`. If your aggregator parent is already something else, you cannot also 'extend' a BOM. **Import scope** solves this: it copies a BOM's managed dependencies into your own `<dependencyManagement>` without using the parent slot, and you can import *several* BOMs. ## How to import ```xml <dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-dependencies</artifactId> <version>3.3.1</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> <!-- version supplied by the imported BOM --> </dependency> </dependencies> ``` The two required markers are **`<type>pom</type>`** (it's a POM, not a jar) and **`<scope>import</scope>`**. ## Resolution rules to know - **Import is resolved at the point of declaration**: the BOM's entries are flattened into your dependencyManagement as if you'd typed them there. - **Locally-declared management wins**: if you also pin a version directly in your <dependencyManagement>, it overrides the imported BOM. - **Order matters across multiple BOMs**: when two imported BOMs manage the same artifact, the *first declared* import wins (nearest-first within your management list). - Import scope is valid **only inside <dependencyManagement>**; using `scope=import` in a normal <dependencies> entry is meaningless. ## Alternative: parent BOM You can also make the BOM your `<parent>` (Spring Boot's classic pattern), which auto-applies its dependencyManagement plus plugin management. Import scope is the choice when you can't or don't want to give up the parent slot.
- Why use import scope instead of just making the BOM your parent?A POM has only one parent. Import scope lets you pull in many BOMs and keep your own aggregator parent.
- If two imported BOMs manage the same artifact at different versions, which wins?The first-declared import wins. Or you can override explicitly by pinning the version directly in your own dependencyManagement.
- Can you put scope=import on a normal <dependencies> entry?No — import scope is only meaningful inside <dependencyManagement> on a <type>pom</type> artifact.
saying these in an interview costs you the question
- Forgetting <type>pom</type> (defaults to jar, so the import fails to resolve as a BOM).
- Thinking import scope works inside <dependencies>.
- Believing a BOM adds dependencies to the classpath — it only manages versions.