🍃 Section 5 · Question #22

What is a starter in Spring Boot

A Spring Boot Starter is an aggregated dependency descriptor that bundles a curated set of transitive libraries and automatic configuration hooks needed to enable a specific app...


🟢 Junior Level

A Spring Boot Starter is an aggregated dependency descriptor that bundles a curated set of transitive libraries and automatic configuration hooks needed to enable a specific application capability with a single dependency declaration in your pom.xml or build.gradle.

The Problem Starters Solve: Eliminating “JAR Hell”

Before Spring Boot (Traditional Spring Framework): To build a basic REST API with JSON serialization and validation, developers had to manually search for, declare, and resolve version compatibility across more than a dozen discrete libraries:

  • spring-web
  • spring-webmvc
  • jackson-core
  • jackson-databind
  • jackson-datatype-jsr310
  • tomcat-embed-core
  • hibernate-validator

A version mismatch between Jackson and Spring MVC frequently triggered runtime crashes (NoSuchMethodError, ClassNotFoundException), commonly known as JAR Hell.

With Spring Boot Starters: A developer declares a single aggregated dependency:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>

Spring Boot transitively pulls in tested, harmonized, and guaranteed-compatible versions of all required libraries.

  • spring-boot-starter-web: Builds RESTful web services and Spring MVC applications; includes Embedded Tomcat, Jackson, and Spring MVC.
  • spring-boot-starter-data-jpa: Integrates relational databases; bundles Spring Data JPA, Hibernate ORM, and the HikariCP connection pool.
  • spring-boot-starter-security: Implements authentication and authorization using Spring Security.
  • spring-boot-starter-validation: Provides JSR-380 / Jakarta Bean Validation using Hibernate Validator.
  • spring-boot-starter-actuator: Provides production-ready monitoring, metrics, and health check endpoints.
  • spring-boot-starter-test: Comprehensive testing suite including JUnit 5, Mockito, AssertJ, Hamcrest, and Spring Test.

🟡 Middle Level

Official vs Third-Party Naming Conventions

The Spring team enforces a strict naming convention for starter artifacts to distinguish official modules from community or internal corporate starters:

Official Spring / VMware Starters:
    spring-boot-starter-{name}
    Examples: spring-boot-starter-data-redis, spring-boot-starter-amqp

Community, Third-Party, and Corporate Starters:
    {name}-spring-boot-starter
    Examples: mybatis-spring-boot-starter, grpc-spring-boot-starter, acme-audit-spring-boot-starter

[!WARNING] Third-party and corporate starters must never begin with spring-boot-starter-*. That prefix is strictly reserved for the core Spring Boot ecosystem.

Centralized Version Management: The Bill of Materials (BOM)

Notice that starter dependencies declared in a Spring Boot application do not contain a <version> tag:

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

spring-boot-starter-parent transitively inherits spring-boot-dependencies—a specialized Bill of Materials (BOM) POM file. Inside its <dependencyManagement> section, versions for hundreds of common third-party libraries (PostgreSQL, MySQL, Hibernate, Netty, SLF4J, Kafka, Micrometer) are pinned and tested for seamless compatibility.

Using Spring Boot Without spring-boot-starter-parent

In enterprise environments where projects must inherit from an internal corporate parent POM, you can import Spring Boot’s BOM via scope=import:

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

This retains all automatic version-alignment benefits without overriding your project’s <parent>.


🔴 Senior Level

Canonical Custom Starter Architecture: The Two-Module Pattern

According to the official Spring Boot starter development guide, a production-grade custom starter should be split into two distinct modules:

                       ┌───────────────────────────────────────────────┐
                       │          acme-spring-boot-starter             │
                       │          (Empty "Umbrella" Aggregator)        │
                       └───────────────────────┬───────────────────────┘
                                               │ Transitively pulls
                                               ▼
         ┌─────────────────────────────────────┴─────────────────────────────────────┐
         ▼                                                                           ▼
┌─────────────────────────────────┐                         ┌─────────────────────────────────┐
│ acme-spring-boot-autoconfigure  │                         │            acme-core            │
│ (Auto-configuration classes,     │                         │ (Pure Java / Kotlin SDK; zero   │
│  @AutoConfiguration, BPPs)      │                         │  Spring Boot framework runtime) │
└─────────────────────────────────┘                         └─────────────────────────────────┘
  1. acme-core: The pure business client or SDK (e.g. an internal HTTP RPC client, encryption library, or audit logger). It contains zero Spring Boot dependencies, allowing non-Spring applications (plain Java tools, Micronaut, Quarkus) to use the core SDK.
  2. acme-spring-boot-autoconfigure: Contains Spring Boot configuration classes (@AutoConfiguration), @ConfigurationProperties, condition checks (@ConditionalOnClass), and bean definitions.
  3. acme-spring-boot-starter: An empty umbrella POM that brings acme-core and acme-spring-boot-autoconfigure together. This is the single dependency developers add to their applications.

Implementing a Custom Starter in Spring Boot 3.x

1. Configuration Properties Class

package com.acme.starter.properties;

import org.springframework.boot.context.properties.ConfigurationProperties;

@ConfigurationProperties(prefix = "acme.client")
public class AcmeClientProperties {
    private String apiKey;
    private int timeoutMs = 5000;
    private boolean enabled = true;

    // Getters and Setters
    public String getApiKey() { return apiKey; }
    public void setApiKey(String apiKey) { this.apiKey = apiKey; }
    public int getTimeoutMs() { return timeoutMs; }
    public void setTimeoutMs(int timeoutMs) { this.timeoutMs = timeoutMs; }
    public boolean isEnabled() { return enabled; }
    public void setEnabled(boolean enabled) { this.enabled = enabled; }
}

2. Auto-Configuration Class (@AutoConfiguration)

package com.acme.starter.autoconfigure;

import com.acme.core.AcmeClient;
import com.acme.starter.properties.AcmeClientProperties;
import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;

@AutoConfiguration
@ConditionalOnClass(AcmeClient.class)
@EnableConfigurationProperties(AcmeClientProperties.class)
@ConditionalOnProperty(prefix = "acme.client", name = "enabled", havingValue = "true", matchIfMissing = true)
public class AcmeClientAutoConfiguration {

    @Bean
    @ConditionalOnMissingBean
    public AcmeClient acmeClient(AcmeClientProperties properties) {
        return new AcmeClient(properties.getApiKey(), properties.getTimeoutMs());
    }
}

3. Registration in Spring Boot 3.x Imports Registry

Create src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports:

com.acme.starter.autoconfigure.AcmeClientAutoConfiguration

IDE Autocompletion Metadata Generation

To give developers IDE autocompletion, type checking, and documentation tooltips for custom properties in application.yml, include the annotation processor in the autoconfigure module:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-configuration-processor</artifactId>
    <optional>true</optional>
</dependency>

During build compilation, this processor scans @ConfigurationProperties classes and generates META-INF/spring-configuration-metadata.json, which is natively read by IntelliJ IDEA, Eclipse, and VS Code.


4 Tricky Questions

1. Why is an enterprise custom starter architecturally divided into two distinct modules (autoconfigure and starter)?

Answer: The two-module pattern separates reusable business functionality from Spring Boot framework integration:

  • The core module contains plain Java/Kotlin SDKs, network clients, or utility logic without any dependencies on spring-boot. This allows other non-Spring teams (e.g., CLI tools, legacy apps, Quarkus/Micronaut services) to use the core SDK without dragging in Spring dependencies.
  • The autoconfigure module contains the Spring Boot integration logic (@AutoConfiguration, conditions, properties).
  • The starter module is an empty aggregator POM that pulls both together. Developers get plug-and-play functionality in one line, while preserving a decoupled architecture.

2. How can you utilize Spring Boot’s dependency version management if your project’s pom.xml is already required to inherit from an internal corporate parent POM?

Answer: You cannot have multiple <parent> declarations in Maven. Instead, you declare spring-boot-dependencies inside the <dependencyManagement> block using the import scope:

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

Maven imports all dependency version rules from the Spring Boot BOM, allowing your project to retain its corporate <parent> while omitting version numbers on Spring Boot dependencies.

3. Why does Spring strictly enforce the naming convention spring-boot-starter-* vs *-spring-boot-starter?

Answer: This naming convention protects developers from confusing official, VMware-maintained starters with third-party or internal corporate starters:

  • The prefix spring-boot-starter-* is reserved strictly for official Spring Boot modules supported directly by the Spring engineering team.
  • Third-party open-source libraries (e.g., mybatis-spring-boot-starter, camel-spring-boot-starter) and internal company libraries must use the suffix pattern *-spring-boot-starter. Violating this convention leads to dependency confusion and risks collisions with future official Spring modules.

4. What is the role of spring-boot-configuration-processor, and what file does it generate during compilation?

Answer: spring-boot-configuration-processor is an annotation processor triggered by javac during the compilation phase. It inspects all classes annotated with @ConfigurationProperties and their Javadoc comments.

It generates a metadata file located at META-INF/spring-configuration-metadata.json. Modern IDEs (IntelliJ IDEA, VS Code, Eclipse) read this file to provide rich auto-completion, parameter descriptions, default value displays, and type validation directly inside application.properties and application.yml files.


🎯 Interview Cheat Sheet

30-Second Elevator Pitch

A Spring Boot Starter is an aggregated dependency descriptor that packages a curated set of libraries and automatic configuration hooks for a specific capability (Web, JPA, Security).

  • Eliminates “JAR Hell” by aligning compatible library versions via Spring Boot’s Bill of Materials (spring-boot-dependencies).
  • Naming convention: official starters use spring-boot-starter-*; third-party/custom starters must use *-spring-boot-starter.
  • Production starters use the two-module pattern: a pure Java SDK module (core) + an auto-configuration module (autoconfigure), tied together by an empty umbrella starter POM.
  • In Spring Boot 3.x, auto-configuration classes are registered in META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports.

Starter Architecture Summary

Module Role Core Dependencies
*-core Business SDK / Client Zero Spring Boot dependencies
*-autoconfigure Auto-configuration & properties spring-boot-autoconfigure
*-starter Empty aggregator POM Imports *-core and *-autoconfigure

Red Flags (DO NOT Say)

  • ❌ “A starter is just a plain JAR file that only contains compiled class code.” (A starter is an aggregator descriptor that bundles dependencies and triggers auto-configuration).
  • ❌ “You should name your company starter spring-boot-starter-company.” (Violates Spring naming standards; must be company-spring-boot-starter).
  • ❌ “Starters hardcode individual version numbers into the project’s dependency block.” (Versions are managed globally by the spring-boot-dependencies BOM).
  • ❌ “Spring Boot 3 still uses spring.factories to register starters.” (Boot 3 uses .imports files located in META-INF/spring/).