Course topics

By WebNest Studio

Spring Boot Tutorial

Dependency Management and the Starter Parent

A typical Spring Boot application depends on hundreds of libraries — Spring modules, Hibernate, Jackson, Tomcat, logging, drivers — and they must all be compatible. Spring Boot solves this with dependency management: every release publishes a tested list of versions, so you declare dependencies without version numbers and get a combination known to work.

This lesson explains spring-boot-starter-parent, the spring-boot-dependencies BOM, how to use Boot without the parent, how to override a managed version safely, the Gradle equivalents, and tools to inspect your dependency tree.

spring-boot-starter-parent

Generated Maven projects inherit from spring-boot-starter-parent. The parent provides: dependency management via the spring-boot-dependencies BOM; the Java version from the java.version property; UTF-8 encoding; sensible plugin configuration (compiler with -parameters, surefire, the Spring Boot Maven plugin, resource filtering for @...@ placeholders); and a native profile for GraalVM builds.

The BOM Without the Parent

Companies often require their own parent POM. In that case import spring-boot-dependencies as a BOM in <dependencyManagement> with <scope>import</scope>. You keep version management, but you must configure plugins such as spring-boot-maven-plugin (with its repackage goal) yourself. Other projects publish their own BOMs the same way — spring-ai-bom, spring-cloud-dependencies, testcontainers-bom.

Overriding a Managed Version

Sometimes you need a newer patch of a library for a security fix. With the parent, override the version property — for example <jackson-bom.version> or <postgresql.version> — rather than adding a version to one dependency, so all related artifacts move together. The full list of property names is in the Spring Boot reference ("Dependency Versions"). Override sparingly and remove overrides when you upgrade Boot.

Gradle

In Gradle, applying the org.springframework.boot plugin together with io.spring.dependency-management gives the same behaviour. Alternatively use Gradle's native platform support: implementation(platform(SpringBootPlugin.BOM_COORDINATES)). Versions are overridden with ext["postgresql.version"] = "..." when using the dependency-management plugin.

Inspecting Dependencies

mvn dependency:tree or gradle dependencies show where each library comes from. mvn dependency:analyze finds declared-but-unused and used-but-undeclared dependencies. When two versions of the same library appear, Maven picks the nearest one in the tree — BOM management ensures that is the one Spring Boot tested.

Examples

Using the starter parent

Java
<project>
    <modelVersion>4.0.0</modelVersion>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>4.1.1</version>
        <relativePath/>
    </parent>

    <groupId>com.webnest</groupId>
    <artifactId>shop</artifactId>
    <version>1.0.0</version>

    <properties>
        <java.version>21</java.version>
        <postgresql.version>42.7.8</postgresql.version>   <!-- override one managed version -->
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-webmvc</artifactId>   <!-- no <version> -->
        </dependency>
        <dependency>
            <groupId>org.postgresql</groupId>
            <artifactId>postgresql</artifactId>
            <scope>runtime</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
</project>
Output
mvn help:effective-pom | findstr postgresql.version
<postgresql.version>42.7.8</postgresql.version>

Using the BOM with your own company parent

Java
<parent>
    <groupId>com.webnest</groupId>
    <artifactId>webnest-parent</artifactId>
    <version>7</version>
</parent>

<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>

<build>
    <plugins>
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
            <version>4.1.1</version>
            <executions>
                <execution>
                    <goals><goal>repackage</goal></goals>   <!-- needed without the parent -->
                </execution>
            </executions>
        </plugin>
    </plugins>
</build>
Output
mvn package -> target/shop-1.0.0.jar (executable, repackaged by the Spring Boot plugin)

Gradle equivalent and inspecting the tree

Java
// build.gradle.kts
plugins {
    java
    id("org.springframework.boot") version "4.1.1"
    id("io.spring.dependency-management") version "1.1.7"
}

java { toolchain { languageVersion = JavaLanguageVersion.of(21) } }

dependencies {
    implementation("org.springframework.boot:spring-boot-starter-webmvc")
    runtimeOnly("org.postgresql:postgresql")
    testImplementation("org.springframework.boot:spring-boot-starter-webmvc-test")
}

# Where does jackson come from?
./gradlew dependencyInsight --dependency tools.jackson.core:jackson-databind
mvn dependency:tree -Dincludes=tools.jackson.core
Output
tools.jackson.core:jackson-databind:3.0.x
   \--- org.springframework.boot:spring-boot-starter-jackson:4.1.1
        \--- org.springframework.boot:spring-boot-starter-webmvc:4.1.1

Common Mistakes

  • Adding explicit versions to Spring-managed dependencies, which drift out of sync on the next Boot upgrade.
  • Overriding one artifact's version instead of the BOM property, producing mixed versions of a library family.
  • Replacing the parent with the BOM but forgetting to configure the repackage goal, so the jar is not executable.
  • Leaving old version overrides in place after upgrading Spring Boot.
  • Importing two BOMs that manage the same library with different versions without checking which wins (the first declared).

Key Points to Remember

  • spring-boot-starter-parent provides dependency and plugin management for Maven projects.
  • spring-boot-dependencies is the BOM behind it; import it when you cannot use the parent.
  • Declare Spring-managed dependencies without versions; override via version properties when needed.
  • Gradle uses the Spring Boot plugin with dependency management or a platform BOM.
  • Inspect with dependency:tree / dependencyInsight to understand where versions come from.

Practice the examples

Change an input, predict the result, then compare it with the output. Explain why the result changes.

Use your local JDK or project IDE for these examples. Codelab currently runs Python and HTML/CSS/JavaScript; framework examples may need project dependencies.