In the last tutorial we saw how to use Spring Boot starter dependencies by inheriting from spring-boot-starter-parent. A Maven project can have only one parent, so inheriting from the spring-boot-starter-parent POM is not always possible, for example when our organization already requires its own corporate parent POM. In that case, Maven gives us another option: importing spring-boot-dependencies, which is itself the parent of spring-boot-starter-parent. Importing dependencies effectively replaces the import declaration with the <dependencyManagement> section of the imported POM. The import scope is only valid for dependencies of type pom that are declared inside <dependencyManagement>.
Let's see this in action by modifying our last example.
This time we use Maven's <dependencyManagement> section and declare spring-boot-dependencies as a dependency with scope=import and type=pom. Because we no longer inherit from the starter parent, we also have to set the Java version ourselves.
pom.xml<?xml version="1.0" encoding="UTF-8"?>
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"
xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<modelVersion>4.0.0</modelVersion>
<groupId>com.logicbig.example</groupId>
<artifactId>spring-boot-parent-pom-import</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<maven.compiler.release>25</maven.compiler.release>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>4.1.1</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>commons-codec</groupId>
<artifactId>commons-codec</artifactId>
</dependency>
</dependencies>
</project>
Main class
package com.logicbig.example;
import org.apache.commons.codec.binary.Hex;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import java.nio.charset.StandardCharsets;
@SpringBootApplication
public class ApplicationExample {
@Bean
public MyBean myBean() {
return new MyBean();
}
public static void main(String[] args) {
ApplicationContext ctx =
SpringApplication.run(ApplicationExample.class, args);
MyBean bean = ctx.getBean(MyBean.class);
bean.doSomething();
}
private static class MyBean {
public void doSomething() {
System.out.println("Doing something in MyBean");
System.out.println(Hex.encodeHexString(
"ONE".getBytes(StandardCharsets.UTF_8)));
System.out.println(Hex.class.getProtectionDomain()
.getCodeSource()
.getLocation());
}
}
}
Output . ____ _ __ _ _ /\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \ ( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \ \\/ ___)| |_)| | | | | || (_| | ) ) ) ) ' |____| .__|_| |_|_| |_\__, | / / / / =========|_|==============|___/=/_/_/_/
:: Spring Boot :: (v4.1.1)
2026-10-13T08:53:42.144-05:00 INFO 25928 --- [nExample.main()] c.logicbig.example.ApplicationExample : Starting ApplicationExample using Java 25 with PID 25928 (D:\LogicBig\example-projects\spring-boot\spring-boot-parent-pom-import\target\classes started by joe2 in D:\LogicBig\example-projects\spring-boot\spring-boot-parent-pom-import) 2026-10-13T08:53:42.149-05:00 INFO 25928 --- [nExample.main()] c.logicbig.example.ApplicationExample : No active profile set, falling back to 1 default profile: "default" 2026-10-13T08:53:43.277-05:00 INFO 25928 --- [nExample.main()] c.logicbig.example.ApplicationExample : Started ApplicationExample in 1.843 seconds (process running for 5.541) Doing something in MyBean 4f4e45 file:/C:/Users/Joe/.m2/repository/commons-codec/commons-codec/1.21.0/commons-codec-1.21.0.jar
Inheriting vs Importing the Parent Starter
There are several reasons to import the Spring Boot BOM instead of inheriting from the starter parent. The most common one is that our project already has a parent POM that we have to inherit from. Another is that our design policies simply do not allow inheriting from a framework POM.
With the import option we keep the benefit of dependency management, but we do not get everything else that spring-boot-starter-parent provides:
- Plugin management: we have to declare plugins such as spring-boot-maven-plugin ourselves, including their versions and executions.
- Build defaults: settings such as the Java release, the source encoding and resource filtering must be configured by us, as we did with the <properties> section above.
- Version properties: properties like spring-framework.version are not inherited, so overriding a managed version by setting a property does not work. Instead, declare the artifact with the desired version in our own <dependencies> section; a local declaration takes precedence over the imported one.
Changing the Java Version
When we import the BOM, there is no default Java version at all. The <java.version> property, together with a sensible default, comes from spring-boot-starter-parent, and importing spring-boot-dependencies does not bring it along. Without it, the compiler falls back to the default of whatever maven-compiler-plugin version Maven binds, which may be a very old language level. Newer Spring Boot versions then fail to compile with errors like invalid source release. So when importing, we should always set the Java version ourselves.
We can set the standard Maven compiler property maven.compiler.release ourselves:
<properties>
<maven.compiler.release>17</maven.compiler.release>
</properties>
The release option above requires the JDK that runs Maven to be 9 or later. The target can still be an older Java version, for example 8. If we build on JDK 8, we use source and target instead:
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
</properties>
Alternatively, we can configure the maven-compiler-plugin directly in the build section (this needs plugin version 3.6.0 or later for the release option):
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<release>17</release>
</configuration>
</plugin>
</plugins>
</build>
If we build on JDK 8, where release is not available, we configure source and target instead:
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>8</source>
<target>8</target>
</configuration>
</plugin>
</plugins>
</build>
On Maven older than 3.9, the default maven-compiler-plugin version is very old, so it is a good idea to pin a recent version with a <version> element in either variant.
A few things to keep in mind:
Example ProjectDependencies and Technologies Used: - Spring Boot 4.1.1
Corresponding Spring Version 7.0.9 Version Compatibility: 1.4.0.RELEASE - 4.1.1
- spring-boot-starter (Core starter, including auto-configuration support, logging and YAML)
- commons-codec 1.21.0 (The Apache Commons Codec component contains encoders and decoders for
formats such as Base16, Base32, Base64, digest, and Hexadecimal. In addition to these
widely used encoders and decoders, the codec package also maintains a
collection of phonetic encoding utilities. [Description from commons-codec-1.21.0.pom])
- JDK 25
- Maven 3.9.11
|