Jesse A. Green / notebook

Spring Boot — User Guide

Generated May 2026 from spring-projects/spring-boot at b9ee76e

AI-generated documentation. The library is checked by sampling (three repositories so far); this guide was not individually reviewed. Verify against the project before relying on it.

1. Quick Start

Spring Boot is a Java framework that makes it easy to create stand-alone, production-grade Spring-based applications. It provides opinionated defaults, embedded servers, and auto-configuration so you can focus on writing business logic instead of boilerplate infrastructure code.

Key features:

  • Auto-configuration — automatically configures your application based on dependencies on the classpath
  • Embedded servers — runs Tomcat, Jetty, or Netty directly inside your application JAR
  • Starter dependencies — curated dependency sets that pull in everything needed for a feature
  • Production-ready features — health checks, metrics, and externalized configuration via Actuator
  • Spring Boot CLI — command-line tool for scaffolding and running Spring applications
  • Build plugins — Gradle and Maven plugins for creating executable JARs/WARs and container images
  • Docker Compose support — automatic service discovery and connection configuration from Docker Compose files
  • DevTools — automatic restart, live reload, and development-time property defaults

Prerequisites:

  • Java 17 or later (JDK)
  • Maven 3.6.3+ or Gradle 7.6.4+

Minimal application:

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@SpringBootApplication
@RestController
public class MyApplication {

    public static void main(String[] args) {
        SpringApplication.run(MyApplication.class, args);
    }

    @GetMapping("/hello")
    public String hello() {
        return "Hello, World!";
    }
}
./mvnw spring-boot:run
  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/

2026-05-07 10:00:00.123  INFO --- Started MyApplication in 2.345 seconds

Open http://localhost:8080/hello in a browser to see "Hello, World!".

Tip

The fastest way to scaffold a new project is with Spring Initializr — select your dependencies and download a ready-to-build project, or use spring init from the CLI.

What to try next: Add dependencies for web, data, or security starters, then let auto-configuration wire everything together. See the Installation section below to set up your environment, or jump to Core Usage for everyday tasks.


2. Installation

System Requirements

Requirement Minimum Version
Java (JDK) 17
Maven 3.6.3
Gradle 7.6.4 (8.x recommended)
Spring Framework 6.2+ (managed automatically)

Project Setup with Spring Initializr

The recommended way to create a new Spring Boot project:

Web (start.spring.io)

  1. Navigate to start.spring.io
  2. Select your project metadata (Group, Artifact, Java version)
  3. Add dependencies (e.g., Spring Web, Spring Data JPA)
  4. Click Generate to download the project ZIP
  5. Extract and open in your IDE

Spring Boot CLI

spring init --dependencies=web,data-jpa,h2 my-project

cURL

curl https://start.spring.io/starter.zip \
  -d dependencies=web,data-jpa \
  -d type=maven-project \
  -d language=java \
  -o my-project.zip

Maven Setup

Add the Spring Boot parent POM to your pom.xml:

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

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

<build>
    <plugins>
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
        </plugin>
    </plugins>
</build>

Important

The spring-boot-starter-parent manages dependency versions for the entire Spring ecosystem. If you cannot use a parent POM, import spring-boot-dependencies as a BOM in your <dependencyManagement> section instead.

Gradle Setup

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

group = 'com.example'
version = '0.0.1-SNAPSHOT'

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

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

Spring Boot CLI Installation

The Spring Boot CLI provides commands for project initialization, password encoding, and an interactive shell.

SDKMAN! (Linux/macOS)

sdk install springboot

Homebrew (macOS)

brew tap spring-io/tap
brew install spring-boot

Manual

Download the distribution from the Spring releases page, extract it, and add bin/ to your PATH.

Verify installation:

spring version
Spring CLI v3.4.0

Post-Install Verification

Maven:

./mvnw spring-boot:run

Gradle:

./gradlew bootRun

Both should start the application with the Spring Boot banner and report the startup time. If no web starter is present, the application starts and exits immediately — that is expected for non-web applications.

Warning

If you see Unsupported class file major version errors, your JDK version is too old. Spring Boot requires JDK 17 or later. Run java -version to check.

Install Troubleshooting

Error: Could not find artifact org.springframework.boot:spring-boot-starter-parent

Cause: Maven cannot reach Maven Central or a corporate proxy is blocking downloads.

Solution:

  1. Check your internet connection
  2. Verify ~/.m2/settings.xml proxy settings
  3. Run ./mvnw -U spring-boot:run to force snapshot updates

Prevention: Configure a local Maven mirror (Nexus, Artifactory) for reliable builds.

Error: Plugin 'org.springframework.boot' not found

Cause: Gradle cannot resolve the Spring Boot plugin from the Gradle Plugin Portal.

Solution:

  1. Check settings.gradle for pluginManagement blocks
  2. Ensure gradlePluginPortal() is listed in plugin repositories
  3. Run with --refresh-dependencies

Prevention: Pin plugin versions in settings.gradle pluginManagement.

Error: java.lang.UnsupportedClassVersionError

Cause: The JDK version running the application is older than the version used to compile.

Solution:

  1. Run java -version and javac -version
  2. Ensure both are JDK 17+
  3. Set JAVA_HOME to the correct JDK installation

Prevention: Use a Java version manager like SDKMAN! to manage JDK installations.

Error: Port 8080 already in use

Cause: Another process is bound to the default HTTP port.

Solution:

  1. Find the process: lsof -i :8080 (Linux/macOS) or netstat -ano | findstr :8080 (Windows)
  2. Stop the conflicting process, or set a different port:
    server.port=8081
    

Prevention: Use server.port=0 for random port assignment in tests and development.

Error: No auto configuration classes found in META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports

Cause: The project structure doesn't match Spring Boot expectations, or the main class is in the wrong package.

Solution:

  1. Ensure your @SpringBootApplication class is in a root package
  2. Component scanning starts from the package of the main class downward
  3. Move the main class to a parent package of all other classes

Prevention: Always place your main application class in a root package above other classes.


3. Configuration

Spring Boot uses a layered configuration system that loads properties from multiple sources in a defined order. Later sources override earlier ones.

Configuration Files

Spring Boot loads configuration from application.properties or application.yml in the following locations (highest priority first):

  1. Command-line arguments (--server.port=9090)
  2. Java system properties (-Dserver.port=9090)
  3. OS environment variables (SERVER_PORT=9090)
  4. application.properties / application.yml in the current directory
  5. application.properties / application.yml in config/ subdirectory
  6. application.properties / application.yml on the classpath (src/main/resources/)
  7. Default values from auto-configuration

Basic Configuration

# Server
server.port=8080
server.servlet.context-path=/api

# Logging
logging.level.root=INFO
logging.level.com.example=DEBUG
logging.file.name=app.log

# Data Source
spring.datasource.url=jdbc:postgresql://localhost:5432/mydb
spring.datasource.username=myuser
spring.datasource.password=secret

# JPA
spring.jpa.hibernate.ddl-auto=validate
spring.jpa.show-sql=false

YAML Configuration

server:
  port: 8080
  servlet:
    context-path: /api

spring:
  datasource:
    url: jdbc:postgresql://localhost:5432/mydb
    username: myuser
    password: secret
  jpa:
    hibernate:
      ddl-auto: validate
    show-sql: false

logging:
  level:
    root: INFO
    com.example: DEBUG

Note

YAML and properties files are interchangeable. Use whichever format your team prefers. YAML supports hierarchical structure and list syntax natively; properties files are simpler for flat key-value pairs.

Profiles

Profiles let you separate configuration by environment. Activate a profile with spring.profiles.active:

# application.properties (default)
spring.profiles.active=dev
# application-dev.properties
server.port=8080
spring.datasource.url=jdbc:h2:mem:devdb
logging.level.root=DEBUG
# application-prod.properties
server.port=443
spring.datasource.url=jdbc:postgresql://prod-db:5432/app
logging.level.root=WARN

Activate profiles via command line, environment variable, or JVM argument:

java -jar app.jar --spring.profiles.active=prod
SPRING_PROFILES_ACTIVE=prod java -jar app.jar

Tip

Use spring.profiles.group to combine multiple profiles into a single named group. For example, spring.profiles.group.production=proddb,prodmq activates both proddb and prodmq when production is active.

Type-Safe Configuration Properties

Bind configuration properties to Java classes using @ConfigurationProperties:

@ConfigurationProperties(prefix = "app.mail")
public class MailProperties {
    private String host;
    private int port = 25;
    private String username;

    // getters and setters
}
app.mail.host=smtp.example.com
app.mail.port=587
app.mail.username=noreply

Enable with @EnableConfigurationProperties(MailProperties.class) or @ConfigurationPropertiesScan.

Environment Variables

Spring Boot automatically maps environment variables to properties using relaxed binding:

Property Environment Variable
server.port SERVER_PORT
spring.datasource.url SPRING_DATASOURCE_URL
app.mail.host APP_MAIL_HOST

Rules: uppercase, replace . with _, remove -.

Warning

Never commit sensitive values (passwords, API keys) in application.properties. Use environment variables, Spring Cloud Vault, or externalized secret management for production secrets.

For the full configuration reference with every property, default value, and type, see the Admin Guide.


4. Core Usage

Creating a Web Application

REST Controllers

@RestController
@RequestMapping("/api/users")
public class UserController {

    private final UserService userService;

    public UserController(UserService userService) {
        this.userService = userService;
    }

    @GetMapping
    public List<User> listUsers() {
        return userService.findAll();
    }

    @GetMapping("/{id}")
    public User getUser(@PathVariable Long id) {
        return userService.findById(id);
    }

    @PostMapping
    @ResponseStatus(HttpStatus.CREATED)
    public User createUser(@Valid @RequestBody User user) {
        return userService.save(user);
    }

    @DeleteMapping("/{id}")
    @ResponseStatus(HttpStatus.NO_CONTENT)
    public void deleteUser(@PathVariable Long id) {
        userService.delete(id);
    }
}

Serving Static Content

Place static files in src/main/resources/static/ or src/main/resources/public/. Spring Boot serves them automatically at the root URL path.

Template Engines

Spring Boot auto-configures Thymeleaf, FreeMarker, Mustache, and Groovy Templates when the appropriate starter is on the classpath. Place templates in src/main/resources/templates/.

@Controller
public class HomeController {

    @GetMapping("/")
    public String home(Model model) {
        model.addAttribute("message", "Welcome!");
        return "home"; // resolves to templates/home.html
    }
}

Working with Data

Spring Data JPA

Add spring-boot-starter-data-jpa and a database driver:

@Entity
public class Customer {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String name;
    private String email;
    // getters, setters
}

public interface CustomerRepository extends JpaRepository<Customer, Long> {
    List<Customer> findByName(String name);
    Optional<Customer> findByEmail(String email);
}

Spring Boot auto-configures the DataSource, EntityManagerFactory, and transaction manager based on your properties.

Note

Spring Boot supports JPA, JDBC, R2DBC (reactive), MongoDB, Redis, Cassandra, Elasticsearch, Neo4j, Couchbase, and LDAP data stores through their respective starters. Each follows the same convention: add the starter, configure the connection, and define repositories.

Database Migrations

Spring Boot auto-runs Flyway or Liquibase migrations at startup when those dependencies are present:

# Flyway (default location: db/migration/)
spring.flyway.enabled=true
spring.flyway.locations=classpath:db/migration

# Liquibase
spring.liquibase.change-log=classpath:db/changelog/db.changelog-master.yaml

Place migration scripts in src/main/resources/db/migration/:

-- V1__Create_customer_table.sql
CREATE TABLE customer (
    id BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
    name VARCHAR(255) NOT NULL,
    email VARCHAR(255) UNIQUE
);

Security

Add spring-boot-starter-security and Spring Boot auto-configures:

  • Form-based login at /login
  • HTTP Basic authentication for API endpoints
  • CSRF protection enabled
  • A default user with username user and a generated password (printed at startup)
Using generated security password: 8a2f4e9b-1234-5678-abcd-ef0123456789

Customize with a SecurityFilterChain bean:

@Configuration
@EnableWebSecurity
public class SecurityConfig {

    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        http
            .authorizeHttpRequests(auth -> auth
                .requestMatchers("/api/public/**").permitAll()
                .anyRequest().authenticated()
            )
            .httpBasic(Customizer.withDefaults());
        return http.build();
    }
}

Important

The default generated password changes on every restart and is intended for development only. For production, configure a proper user store (JDBC, LDAP, or OAuth2 provider).

Messaging

Spring Boot supports JMS (ActiveMQ, Artemis), AMQP (RabbitMQ), Kafka, Pulsar, and RSocket through starters.

Kafka example:

@Component
public class OrderListener {

    @KafkaListener(topics = "orders")
    public void handleOrder(String message) {
        // process order
    }
}
spring.kafka.bootstrap-servers=localhost:9092
spring.kafka.consumer.group-id=order-service
spring.kafka.consumer.auto-offset-reset=earliest

Reactive Applications with WebFlux

For non-blocking reactive applications, use spring-boot-starter-webflux instead of spring-boot-starter-web:

@RestController
public class ReactiveController {

    @GetMapping("/flux")
    public Flux<String> flux() {
        return Flux.just("Hello", "Reactive", "World");
    }

    @GetMapping("/mono")
    public Mono<String> mono() {
        return Mono.just("Hello Reactive");
    }
}

WebFlux runs on Netty by default instead of Tomcat. Error handling follows the same ErrorAttributes pattern as MVC, with DefaultErrorAttributes providing timestamp, status, error, message, and path fields.

Warning

Do not add both spring-boot-starter-web and spring-boot-starter-webflux to the same project. Spring Boot defaults to MVC (Servlet) when both are present. Choose one paradigm per application.

gRPC Support

Spring Boot includes built-in gRPC server and client support:

spring.grpc.server.port=9090
spring.grpc.client.my-service.address=static://localhost:9090

Define gRPC services by implementing the generated stubs and annotating with @GrpcService:

@GrpcService
public class GreeterService extends GreeterGrpc.GreeterImplBase {
    @Override
    public void sayHello(HelloRequest request, StreamObserver<HelloReply> observer) {
        HelloReply reply = HelloReply.newBuilder()
            .setMessage("Hello " + request.getName())
            .build();
        observer.onNext(reply);
        observer.onCompleted();
    }
}

GraphQL

Add spring-boot-starter-graphql for GraphQL API support:

@Controller
public class BookController {

    @QueryMapping
    public List<Book> books() {
        return bookService.findAll();
    }

    @MutationMapping
    public Book addBook(@Argument BookInput input) {
        return bookService.save(input);
    }
}

Place your schema in src/main/resources/graphql/:

type Query {
    books: [Book]
}

type Book {
    id: ID!
    title: String!
    author: String!
}

5. Common Tasks

Running Your Application

Development

# Maven
./mvnw spring-boot:run

# Gradle
./gradlew bootRun

# With arguments
./mvnw spring-boot:run -Dspring-boot.run.arguments="--server.port=9090"

Production

# Build executable JAR
./mvnw package
# or
./gradlew bootJar

# Run
java -jar target/my-app-0.0.1-SNAPSHOT.jar

Tip

Use java -jar app.jar --server.port=9090 --spring.profiles.active=prod to override any configuration property at launch time.

Building Executable JARs and WARs

Spring Boot creates self-contained JARs with embedded servers. The JAR contains your classes, all dependencies, and the embedded web server.

Maven:

./mvnw clean package
ls target/*.jar
target/my-app-0.0.1-SNAPSHOT.jar

Gradle:

./gradlew bootJar
ls build/libs/*.jar

The resulting JAR is directly executable with java -jar.

WAR packaging (for external servlet containers):

<packaging>war</packaging>
apply plugin: 'war'

Building Container Images

Spring Boot builds OCI container images directly from your application using Cloud Native Buildpacks — no Dockerfile required:

Maven:

./mvnw spring-boot:build-image

Gradle:

./gradlew bootBuildImage
Successfully built image 'docker.io/library/my-app:0.0.1-SNAPSHOT'

Customize the image:

bootBuildImage {
    imageName = "example.com/myapp:${version}"
    builder = "paketobuildpacks/builder-jammy-base:latest"
    pullPolicy = "IF_NOT_PRESENT"
    environment = [
        "BP_JVM_VERSION": "17",
        "BP_LIVE_RELOAD_ENABLED": "true"
    ]
    tags = ["example.com/myapp:latest"]
}

Command-line options for bootBuildImage:

Option Description
--imageName Custom image name
--builder Builder image to use
--runImage Run image for the final layer
--pullPolicy ALWAYS, NEVER, IF_NOT_PRESENT
--trustBuilder Trust the builder (runs in single-phase mode)
--createdDate Set image creation date
--applicationDirectory Application directory in the image
--environment Environment variables for the build

Using DevTools

Add spring-boot-devtools for an enhanced development experience:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-devtools</artifactId>
    <scope>runtime</scope>
    <optional>true</optional>
</dependency>

Features:

  • Automatic restart — the application restarts when classpath files change
  • LiveReload — browser automatically refreshes when resources change
  • Property defaults — development-friendly defaults (e.g., caching disabled)
  • Remote debugging — support for remote development against running applications

Configure restart behavior in META-INF/spring-devtools.properties:

restart.include.my-library=/my-library-[\w\d-\.]+\.jar
restart.exclude.my-static=/my-static-[\w\d-\.]+\.jar

Note

DevTools is automatically disabled when running a fully packaged application (java -jar). It only activates when launched from an IDE or with spring-boot:run. The build plugins exclude it from production JARs.

Using Docker Compose

Spring Boot automatically detects and manages Docker Compose services during development. Add spring-boot-docker-compose:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-docker-compose</artifactId>
    <scope>runtime</scope>
    <optional>true</optional>
</dependency>

With a compose.yaml in your project root:

services:
  postgres:
    image: postgres:16
    ports:
      - "5432:5432"
    environment:
      POSTGRES_DB: mydb
      POSTGRES_USER: myuser
      POSTGRES_PASSWORD: secret
  redis:
    image: redis:7
    ports:
      - "6379:6379"

Spring Boot will:

  1. Detect the compose file at startup
  2. Run docker compose up if services are not already running
  3. Discover service ports (including ephemeral port mapping)
  4. Auto-configure DataSource, RedisConnectionFactory, etc. from the running containers
  5. Optionally run docker compose down on shutdown

Monitoring with Actuator

Add spring-boot-starter-actuator for production monitoring endpoints:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
# Expose all endpoints over HTTP
management.endpoints.web.exposure.include=health,info,metrics,env,loggers

# Show full health details
management.endpoint.health.show-details=always

Key endpoints:

Endpoint Description
/actuator/health Application health status (UP/DOWN)
/actuator/info Application metadata
/actuator/metrics Application metrics (JVM, HTTP, custom)
/actuator/env Environment properties
/actuator/loggers View and change log levels at runtime
/actuator/httptrace Recent HTTP request/response trace
/actuator/beans All registered Spring beans
/actuator/conditions Auto-configuration evaluation report
curl http://localhost:8080/actuator/health
{
  "status": "UP",
  "components": {
    "db": { "status": "UP" },
    "diskSpace": { "status": "UP" }
  }
}

Warning

In production, restrict Actuator endpoint exposure. Use management.endpoints.web.exposure.include to expose only what is needed, and secure endpoints with Spring Security. Some endpoints (like env and beans) reveal sensitive configuration details.

Testing

Spring Boot provides comprehensive testing support through spring-boot-starter-test:

@SpringBootTest
class MyApplicationTests {

    @Autowired
    private MockMvc mockMvc;

    @Test
    void shouldReturnHello() throws Exception {
        mockMvc.perform(get("/hello"))
            .andExpect(status().isOk())
            .andExpect(content().string("Hello, World!"));
    }
}

Test slice annotations for focused testing:

Annotation Scope
@WebMvcTest MVC controllers only
@WebFluxTest WebFlux controllers only
@DataJpaTest JPA repositories with in-memory DB
@JsonTest JSON serialization/deserialization
@RestClientTest REST client with mock server
@WebMvcTest(UserController.class)
class UserControllerTests {

    @Autowired
    private MockMvc mockMvc;

    @MockitoBean
    private UserService userService;

    @Test
    void shouldListUsers() throws Exception {
        when(userService.findAll()).thenReturn(List.of(new User("Alice")));
        mockMvc.perform(get("/api/users"))
            .andExpect(status().isOk())
            .andExpect(jsonPath("$[0].name").value("Alice"));
    }
}

Testcontainers Integration

Spring Boot integrates with Testcontainers for integration tests against real databases and services:

@SpringBootTest
@Testcontainers
class IntegrationTests {

    @Container
    @ServiceConnection
    static PostgreSQLContainer<?> postgres = new PostgreSQLContainer<>("postgres:16");

    @Test
    void shouldConnectToDatabase(@Autowired DataSource dataSource) {
        assertThat(dataSource.getConnection()).isNotNull();
    }
}

The @ServiceConnection annotation automatically configures the data source connection from the container.

Structured Logging

Spring Boot supports structured logging output for integration with log aggregation systems:

# JSON-formatted log output
logging.structured.format.console=ecs
logging.structured.format.file=logstash

Supported formats include ECS (Elastic Common Schema) and Logstash JSON.

Password Encoding (CLI)

The Spring Boot CLI provides a password encoding utility:

spring encodepassword mypassword
{bcrypt}$2a$10$...

This generates a BCrypt-encoded password suitable for use in Spring Security configuration.

Using Starters

Starters are curated dependency descriptors. Add a single starter instead of tracking individual library versions:

Starter Purpose
spring-boot-starter-web Web applications (Tomcat, Spring MVC)
spring-boot-starter-webflux Reactive web (Netty, WebFlux)
spring-boot-starter-data-jpa JPA with Hibernate
spring-boot-starter-data-mongodb MongoDB
spring-boot-starter-data-redis Redis
spring-boot-starter-security Spring Security
spring-boot-starter-actuator Production monitoring
spring-boot-starter-test Testing (JUnit, Mockito, AssertJ)
spring-boot-starter-validation Bean Validation (Hibernate Validator)
spring-boot-starter-cache Caching abstraction
spring-boot-starter-amqp RabbitMQ
spring-boot-starter-mail Email sending
spring-boot-starter-batch Spring Batch
spring-boot-starter-quartz Quartz Scheduler
spring-boot-starter-websocket WebSocket support
spring-boot-starter-graphql GraphQL API
spring-boot-starter-hateoas HATEOAS REST APIs
spring-boot-starter-oauth2-resource-server OAuth2 resource server
spring-boot-starter-rsocket RSocket messaging

Observability with Micrometer and OpenTelemetry

Spring Boot auto-configures Micrometer metrics and tracing:

# Prometheus metrics export
management.prometheus.metrics.export.enabled=true

# Distributed tracing
management.tracing.sampling.probability=1.0

# OpenTelemetry
management.otlp.tracing.endpoint=http://localhost:4318/v1/traces
management.otlp.metrics.export.url=http://localhost:4318/v1/metrics

Custom metrics:

@Component
public class OrderMetrics {

    private final Counter ordersPlaced;

    public OrderMetrics(MeterRegistry registry) {
        this.ordersPlaced = registry.counter("orders.placed");
    }

    public void recordOrder() {
        ordersPlaced.increment();
    }
}

6. Troubleshooting

Diagnostic Decision Tree

Application won't start?
├── Port conflict? → Check server.port, kill conflicting process
├── Bean creation failure? → Check dependency injection, missing beans
├── Database connection? → Verify connection URL, credentials, driver
├── Class not found? → Check dependencies, classpath
└── Configuration error? → Validate property names, types, profiles

Application starts but behaves unexpectedly?
├── Wrong profile active? → Check spring.profiles.active
├── Properties not loading? → Check file location, property name spelling
├── Auto-config not applying? → Run with --debug, check /actuator/conditions
└── Security blocking requests? → Check SecurityFilterChain, CSRF settings

Error: BeanCurrentlyInCreationException: Error creating bean

Cause: Circular dependency between beans — Bean A requires Bean B, which requires Bean A.

Solution:

  1. Redesign to break the cycle (extract shared logic into a third bean)
  2. Use @Lazy on one of the injection points as a temporary workaround
  3. Use setter injection instead of constructor injection for one side

Prevention: Follow the dependency inversion principle. Keep the dependency graph acyclic.

Error: DataSource: Failed to determine suitable driver class

Cause: Spring Boot detected a data-related dependency but cannot find a JDBC driver on the classpath.

Solution:

  1. Add the appropriate database driver dependency (e.g., postgresql, mysql-connector-j, h2)
  2. If you don't need a database, exclude DataSourceAutoConfiguration:
    @SpringBootApplication(exclude = DataSourceAutoConfiguration.class)
    

Prevention: Only include data starters when you actually need database access.

Error: WebMvcTest fails with NPE while evaluating controller method default argument

Cause: A known issue when @WebMvcTest encounters controller methods with default parameter values in Kotlin or certain Java patterns. (Community issue #49859)

Solution:

  1. Provide explicit values in test request parameters
  2. Avoid default method arguments in controller methods used with @WebMvcTest

Prevention: Use explicit parameter binding with @RequestParam(required = false, defaultValue = "...").

Error: Slf4JBridgeHandler.uninstall called too early in context close

Cause: During application shutdown, the SLF4J bridge handler is removed before all JUL (java.util.logging) log output has been flushed, swallowing late shutdown messages. (Community issue #33697)

Solution:

  1. If you need to see JUL output during shutdown, add a custom DisposableBean that delays handler removal
  2. Use SLF4J-native loggers throughout your application to avoid the bridge

Prevention: Prefer SLF4J/Logback for all logging to avoid JUL bridge timing issues.

Error: Spring Boot CLI shows configurationFileFormat option which is not available

Cause: The CLI's spring init command displays the configurationFileFormat option in help, but the option is not functional when creating projects. (Community issue #49960)

Solution: Ignore this option. Use --type to specify Maven/Gradle and --language for Java/Kotlin/Groovy instead.

Prevention: This is a known CLI cosmetic issue.

Error: Tomcat connector failure with HTTPS and virtual threads

Cause: Misconfiguration when combining embedded Tomcat HTTPS with virtual threads.

Solution:

  1. Verify your SSL keystore configuration:
    server.ssl.key-store=classpath:keystore.p12
    server.ssl.key-store-password=changeit
    server.ssl.key-store-type=PKCS12
    
  2. Ensure your JDK supports virtual threads (Java 21+) when using spring.threads.virtual.enabled=true

Prevention: Test HTTPS and virtual thread configurations together before deploying.

Cause: When the PID file path involves symbolic links, the writer may fail to create or update the file. (Community issue #50186)

Solution:

  1. Use a direct path (no symlinks) for the PID file location:
    spring.pid.file=/var/run/myapp.pid
    
  2. Ensure the target directory of the symlink exists and is writable

Prevention: Avoid symlinked paths for PID file locations.

Error: RandomValuePropertySource is not suitable for secrets

Cause: Using ${random.value} or ${random.uuid} in properties for secrets generates new values on every restart and is not cryptographically secure. (Community issue #50184)

Solution: Use a proper secret management system (environment variables, Vault, Kubernetes secrets) instead of random property sources for sensitive values.

Prevention: Never use random.* property sources for passwords, tokens, or keys.

Error: Cassandra auto-configuration misconfigures CqlSessionBuilder

Cause: Auto-configuration may apply incorrect default settings for Cassandra connections in certain configurations. (Community issue #50182)

Solution:

  1. Explicitly configure the CqlSessionBuilder bean
  2. Override the auto-configured properties:
    spring.cassandra.contact-points=localhost
    spring.cassandra.port=9042
    spring.cassandra.local-datacenter=datacenter1
    

Prevention: Always specify spring.cassandra.local-datacenter explicitly.

Caution

When troubleshooting auto-configuration issues, run your application with --debug or set debug=true in properties. This prints a comprehensive conditions evaluation report showing which auto-configurations were applied and which were skipped, and why.


7. FAQ

Q: How do I change the default port?

Set server.port in application.properties, via environment variable SERVER_PORT, or command-line argument --server.port=9090. Use server.port=0 for a random available port.

Q: How do I create a non-web application?

Don't include any web starter. Implement CommandLineRunner or ApplicationRunner for startup logic:

@SpringBootApplication
public class BatchApp implements CommandLineRunner {
    public static void main(String[] args) {
        SpringApplication.run(BatchApp.class, args);
    }

    @Override
    public void run(String... args) {
        // your batch logic
    }
}

Q: How do I use multiple data sources?

Define each DataSource as a @Bean with @ConfigurationProperties pointing to different property prefixes. Mark one as @Primary. See the Admin Guide for a complete multi-datasource configuration example.

Q: Can I use Spring Boot with Kotlin?

Yes. Spring Boot has first-class Kotlin support. Use the kotlin-spring compiler plugin (for open classes) and kotlin-jpa (for no-arg constructors). All documentation examples are available in both Java and Kotlin.

Q: How do I disable a specific auto-configuration?

Use the exclude attribute on @SpringBootApplication:

@SpringBootApplication(exclude = {
    DataSourceAutoConfiguration.class,
    SecurityAutoConfiguration.class
})

Or set spring.autoconfigure.exclude in properties.

Q: How do I serve my application behind a reverse proxy?

Configure server.forward-headers-strategy=native or framework to handle X-Forwarded-* headers:

server.forward-headers-strategy=framework
server.tomcat.remoteip.remote-ip-header=X-Forwarded-For
server.tomcat.remoteip.protocol-header=X-Forwarded-Proto

Q: How do I enable HTTPS?

server.port=8443
server.ssl.key-store=classpath:keystore.p12
server.ssl.key-store-password=changeit
server.ssl.key-store-type=PKCS12
server.ssl.enabled=true

Q: How do I externalize configuration for Docker/Kubernetes?

Use environment variables (Spring Boot maps them automatically) or mount configuration files. In Kubernetes, use ConfigMaps and Secrets:

env:
  - name: SPRING_DATASOURCE_URL
    value: jdbc:postgresql://db:5432/mydb
  - name: SPRING_PROFILES_ACTIVE
    value: prod

Q: How does auto-configuration work?

Spring Boot scans META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports for auto-configuration classes. Each class uses @Conditional annotations to check whether its requirements are met (class on classpath, bean not already defined, property set, etc.). If conditions pass, the auto-configuration creates and configures beans automatically.

Q: How do I create a custom starter?

Create two modules: an autoconfigure module (with @AutoConfiguration class and META-INF/spring/...imports registration) and a starter module (which depends on autoconfigure and pulls in required libraries). See the Admin Guide for the complete starter development pattern.

Q: How do I handle validation errors in REST APIs?

With spring-boot-starter-validation, annotate request bodies with @Valid. Spring Boot returns 400 Bad Request with error details:

@PostMapping("/users")
public User create(@Valid @RequestBody User user) { ... }

Customize error responses by implementing ErrorAttributes or using @ExceptionHandler.

Q: What is the difference between @Component, @Service, @Repository, and @Controller?

They are all specializations of @Component and mark classes for component scanning. @Service indicates a business logic class, @Repository a data access class (with automatic exception translation), and @Controller / @RestController an MVC controller. Functionally they behave the same for dependency injection — the distinction is semantic.

Tip

Run your application with --debug to see a comprehensive auto-configuration report showing exactly which auto-configurations matched or failed, and why.