Home / Spring Boot / Getting Started / Starters and Dependency Management

Starters and Dependency Management

A starter is a single dependency that pulls in everything you need for one feature, with versions that are tested together. Spring Boot manages the versions of hundreds of libraries for you through a Bill of Materials (BOM).

Common starters

Starter (Boot 3.x names)Gives you
spring-boot-starter-webSpring MVC, embedded Tomcat, Jackson (Boot 4 name: spring-boot-starter-webmvc)
spring-boot-starter-webfluxReactive web with Netty
spring-boot-starter-data-jpaSpring Data JPA, Hibernate, HikariCP
spring-boot-starter-data-jdbc / jdbcJDBC with JdbcTemplate and Hikari
spring-boot-starter-data-mongodb / redisMongoDB and Redis support
spring-boot-starter-securitySpring Security
spring-boot-starter-oauth2-resource-serverJWT and OAuth2 resource server
spring-boot-starter-validationBean Validation (Hibernate Validator)
spring-boot-starter-actuatorHealth, metrics and management endpoints
spring-boot-starter-thymeleafServer-side HTML templates
spring-boot-starter-cache / mail / aopCaching, email sending, AOP
spring-boot-starter-testJUnit 5, Mockito, AssertJ, MockMvc, JsonPath

What spring-boot-starter-parent gives you

Override a version

<properties>
    <java.version>21</java.version>
    <postgresql.version>42.7.4</postgresql.version>   <!-- override the managed version -->
</properties>

If you cannot use the parent: import the BOM

<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-dependencies</artifactId>
            <version>3.5.10</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>

Gradle version

plugins {
    id 'java'
    id 'org.springframework.boot' version '3.5.10'
    id 'io.spring.dependency-management' version '1.1.7'
}

dependencies {
    implementation 'org.springframework.boot:spring-boot-starter-web'
    testImplementation 'org.springframework.boot:spring-boot-starter-test'
}

Switch the embedded server from Tomcat to Jetty

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
    <exclusions>
        <exclusion>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-tomcat</artifactId>
        </exclusion>
    </exclusions>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-jetty</artifactId>
</dependency>

See the dependency tree

./mvnw dependency:tree
./gradlew dependencies

Build your own starter (two modules)

greeting-spring-boot/
├── greeting-spring-boot-autoconfigure/        the real code
│   ├── pom.xml                                (depends on spring-boot-autoconfigure, optional spring-boot-configuration-processor)
│   └── src/main/java/com/example/greeting/
│   │       ├── GreetingService.java
│   │       ├── GreetingProperties.java        @ConfigurationProperties("greeting")
│   │       └── GreetingAutoConfiguration.java @AutoConfiguration
│   └── src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
└── greeting-spring-boot-starter/              only a pom: depends on the autoconfigure module + needed libraries
Naming: your own starters are  <name>-spring-boot-starter.   spring-boot-starter-<name> is reserved for the Spring team.
<!-- greeting-spring-boot-starter/pom.xml : no code at all -->
<dependencies>
    <dependency>
        <groupId>com.example</groupId>
        <artifactId>greeting-spring-boot-autoconfigure</artifactId>
        <version>${project.version}</version>
    </dependency>
</dependencies>

<!-- autoconfigure module: generate IDE help for the properties -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-configuration-processor</artifactId>
    <optional>true</optional>
</dependency>

The configuration processor creates META-INF/spring-configuration-metadata.json from your @ConfigurationProperties classes, so IntelliJ and VS Code show auto-completion and descriptions for greeting.message in application.properties.

// src/main/resources/META-INF/additional-spring-configuration-metadata.json : hand-written extras
{ "properties": [ {
    "name": "greeting.message",
    "type": "java.lang.String",
    "description": "Text used at the start of every greeting.",
    "defaultValue": "Hello"
} ] }

Dependency scopes that matter

ScopeOn compile classpathIn the final jarExample
compile (default)YesYesspring-boot-starter-web
runtimeNoYesPostgreSQL JDBC driver, Prometheus registry
providedYesNo (server supplies it)Servlet API when deploying a WAR
testOnly for testsNospring-boot-starter-test
optionalYesNot passed on transitivelyDevTools, configuration processor, Lombok

Find and fix version conflicts

./mvnw dependency:tree -Dincludes=com.fasterxml.jackson.core     # who brings Jackson and which version
./mvnw dependency:tree -Dverbose | grep -i "omitted for conflict"
./mvnw enforcer:enforce                                          # with maven-enforcer-plugin rules dependencyConvergence, banDuplicateClasses
<!-- Override a managed version only for a real reason (security fix), and write down why -->
<properties>
    <jackson-bom.version>2.18.2</jackson-bom.version>   <!-- example: newer security patch than the Boot BOM -->
</properties>

Common mistake: Writing version numbers for libraries that Spring Boot already manages. This can create version conflicts. Remove the version and let the BOM decide, or override it with a property.

Interview questions

What is the difference between a starter and a normal library?

A starter has almost no code. It is a pom that brings a group of compatible libraries, and auto-configuration then wires them.

How do I write my own starter?

Create an autoconfigure module with the auto-configuration and the imports file, and a starter module named xyz-spring-boot-starter that depends on it.

Why do I get a version conflict?

Usually because a version is set manually. Check with dependency:tree and remove the manual version.

What is the difference between spring-boot-starter and spring-boot-autoconfigure?

The autoconfigure jar contains the auto-configuration code for all supported libraries. A starter is only a pom that brings the libraries for one feature; the auto-configuration activates when those libraries are on the classpath.

Why is optional true on the configuration processor?

It is only needed at compile time to generate metadata. Optional prevents it from being passed to projects that use your library.