CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/maven-org-springframework-boot--spring-boot

Core library providing essential Spring Boot functionality for bootstrapping, configuration, logging, and application lifecycle management.

Overview
Eval results
Files

Spring Boot Core Framework

The core library providing essential Spring Boot functionality for bootstrapping, configuration, logging, and application lifecycle management.

Package Information

  • Package Name: spring-boot

  • Group ID: org.springframework.boot

  • Package Type: maven

  • Language: Java

  • Installation:

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot</artifactId>
        <version>4.0.0</version>
    </dependency>

    Gradle:

    implementation 'org.springframework.boot:spring-boot:4.0.0'

Core Imports

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

Common imports for configuration:

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

Common imports for lifecycle:

import org.springframework.boot.ApplicationRunner;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.context.event.*;

Basic Usage

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.ApplicationRunner;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;

@SpringBootApplication
public class MyApplication {

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

    @Bean
    public ApplicationRunner runner() {
        return args -> {
            System.out.println("Application started!");
        };
    }
}

@ConfigurationProperties(prefix = "app")
class AppConfig {
    private String name;
    private int timeout = 30;

    // Getters and setters
    public String getName() { return name; }
    public void setName(String name) { this.name = name; }
    public int getTimeout() { return timeout; }
    public void setTimeout(int timeout) { this.timeout = timeout; }
}

Quick Reference

This documentation has been enhanced for AI coding agents with comprehensive examples, complete API signatures, thread safety notes, error handling patterns, and production-ready usage patterns.

Package: org.springframework.boot Maven: org.springframework.boot:spring-boot:4.0.0 Module: Core library providing essential Spring Boot functionality

Common Task Lookup

TaskPrimary ClassesKey MethodDoc Link
Bootstrap applicationSpringApplicationrun(Class, String[])bootstrapping.md
Type-safe config@ConfigurationPropertiesEnable with @EnableConfigurationPropertiesconfiguration-properties.md
Lifecycle hooksApplicationRunnerrun(ApplicationArguments)lifecycle-events.md
Health stateApplicationAvailabilitygetLivenessState(), getReadinessState()availability.md
Configure loggingLoggingSystemsetLogLevel(String, LogLevel)logging.md
SSL/TLS setupSslBundlesgetBundle(String)ssl-tls.md
Parse JSONJsonParserparseMap(String), parseList(String)json-support.md
Failure analysisFailureAnalyzeranalyze(Throwable, Throwable)diagnostics.md
Task executionThreadPoolTaskExecutorBuilderbuild()task-execution.md
Register servletServletRegistrationBeanConstructor + setUrlMappings()web-support.md

Package-to-Documentation Mapping

Package PatternDocumentation File
org.springframework.boot.SpringApplication*bootstrapping.md
org.springframework.boot.bootstrap.*bootstrap.md
org.springframework.boot.builder.*builder.md
org.springframework.boot.context.annotation.*configuration-annotations.md
org.springframework.boot.context.properties.*configuration-properties.md
org.springframework.boot.context.config.*configuration-data.md
org.springframework.boot.context.event.*lifecycle-events.md
org.springframework.boot.availability.*availability.md
org.springframework.boot.logging.*logging.md
org.springframework.boot.ssl.*ssl-tls.md
org.springframework.boot.json.*json-support.md
org.springframework.boot.diagnostics.*diagnostics.md
org.springframework.boot.web.*web-support.md
org.springframework.boot.task.*task-execution.md
org.springframework.boot.system.*system-utilities.md
org.springframework.boot.convert.*conversion.md
org.springframework.boot.env.*environment-property-sources.md
org.springframework.boot.info.*application-info.md
org.springframework.boot.cloud.*cloud-platform.md
org.springframework.boot.admin.*admin-jmx.md
org.springframework.boot.ansi.*ansi-support.md
org.springframework.boot.origin.*origin-tracking.md
org.springframework.boot.*Aot*aot-native-image.md
org.springframework.boot.support.*support.md
org.springframework.boot.validation.*validation.md
org.springframework.boot.thread.*threading.md
org.springframework.boot.util.*utilities.md
org.springframework.boot.io.*resource-loading.md

Decision Matrix: ApplicationRunner vs CommandLineRunner

CriterionApplicationRunnerCommandLineRunner
Parsed arguments neededUse this
Raw String[] neededUse this
Access named options (--opt=val)Use this
Simple arg processingEither (prefer ApplicationRunner)

Example:

// ApplicationRunner - parsed arguments
@Component
class MyRunner implements ApplicationRunner {
    public void run(ApplicationArguments args) {
        if (args.containsOption("debug")) { /* ... */ }
    }
}

// CommandLineRunner - raw arguments
@Component
class MyRunner implements CommandLineRunner {
    public void run(String... args) {
        // Process raw args
    }
}

Overview

This tile documents the Spring Boot Core library (org.springframework.boot:spring-boot@4.0.0), which provides the foundational infrastructure for bootstrapping, configuring, and running Spring Boot applications. It is the essential dependency for all Spring Boot applications.

Package Structure

org.springframework.boot
├── admin                    # JMX administration support
├── availability            # Application availability states (liveness/readiness)
├── cloud                   # Cloud platform detection
├── context
│   ├── config             # Configuration data loading
│   ├── event              # Application lifecycle events
│   ├── metrics            # Startup metrics and buffering
│   └── properties         # Configuration properties binding
├── convert                # Type conversion utilities
├── diagnostics            # Failure analysis framework
├── env                    # Environment and property sources
├── info                   # Application runtime information
├── io                     # Resource loading
├── json                   # JSON parsing and writing
├── logging                # Logging system configuration
├── retry                  # Retry policy support
├── ssl                    # SSL/TLS bundle management
├── system                 # System utilities (PID, home, temp)
├── task                   # Task executor builders
├── thread                 # Threading model detection
├── util                   # General utilities
├── web                    # Web application support
│   ├── context           # Web application contexts
│   ├── error             # Error page support
│   ├── server            # Web server abstraction
│   └── servlet           # Servlet registration
└── SpringApplication      # Main entry point

Core Components

Application Bootstrapping

  • SpringApplication: Main class for bootstrapping Spring Boot applications
  • SpringApplicationBuilder: Fluent builder API for SpringApplication configuration
  • ApplicationRunner/CommandLineRunner: Interfaces for executing code after startup

See: bootstrapping.md

Bootstrap Context and Registry

  • BootstrapRegistry: Early-stage object registry available during startup
  • BootstrapContext: Read-only access to bootstrap instances
  • BootstrapRegistryInitializer: Callback for initializing bootstrap registry
  • BootstrapContextClosedEvent: Event when bootstrap context closes

See: bootstrap.md

Configuration Annotations Support

  • Configurations: Manage sets of @Configuration classes with ordering
  • UserConfigurations: User-defined configuration classes with lowest precedence
  • ImportCandidates: Discover configuration imports from META-INF/spring/*.imports files
  • DeterminableImports: Interface for predictable ImportSelector implementations

See: configuration-annotations.md

Application Builder

  • SpringApplicationBuilder: Fluent builder with context hierarchy support
  • ParentContextApplicationContextInitializer: Set parent-child context relationships
  • Context hierarchy: Parent, child, and sibling context configurations

See: builder.md

Environment Post-Processing Support

  • EnvironmentPostProcessorsFactory: Factory for creating EnvironmentPostProcessors
  • SpringApplicationJsonEnvironmentPostProcessor: Process SPRING_APPLICATION_JSON
  • RandomValuePropertySourceEnvironmentPostProcessor: Add random value support
  • SystemEnvironmentPropertySourceEnvironmentPostProcessor: Configure system environment

See: support.md

Validation Support

  • MessageInterpolatorFactory: Create Bean Validation MessageInterpolators
  • MethodValidationExcludeFilter: Filter types from method validation
  • FilteredMethodValidationPostProcessor: Custom method validation with exclusions

See: validation.md

Threading Configuration

  • Threading: Enum for platform vs virtual threads (Java 21+)
  • Virtual thread support: Enable with spring.threads.virtual.enabled=true
  • Thread model detection: Automatic detection of active threading model

See: threading.md

Utility Classes

  • Instantiator: Generic object instantiation with parameter injection
  • LambdaSafe: Safe lambda invocation handling ClassCastException
  • Type-safe callbacks: Avoid type erasure issues in lambda expressions

See: utilities.md

Resource Loading

  • ApplicationResourceLoader: Enhanced resource loading with protocol resolvers
  • FilePathResolver: Resolve resources to file system paths
  • Protocol resolvers: Support for custom protocols (base64:, etc.)

See: resource-loading.md

Configuration System

  • ConfigurationProperties: Type-safe configuration property binding
  • ConfigData API: Extensible configuration data loading (properties, YAML, custom formats)
  • Environment: Unified property access across multiple sources
  • Profiles: Environment-specific configuration activation

See: configuration-properties.md See: configuration-data.md

Application Lifecycle

  • ApplicationEvent: Comprehensive event system covering all lifecycle phases
  • ApplicationListener: Type-safe event listener registration
  • ApplicationContextInitializer: Pre-refresh context customization
  • EnvironmentPostProcessor: Environment configuration before context creation

See: lifecycle-events.md

Logging

  • LoggingSystem: Abstraction over logging frameworks (Logback, Log4J2, JUL)
  • LogFile: Log file location and rotation configuration
  • LogLevel: Dynamic log level adjustment

See: logging.md

SSL/TLS Support

  • SslBundles: Central registry for SSL certificate and key management
  • SslBundle: Abstraction for PEM and JKS certificate bundles
  • Dynamic certificate updates: Runtime certificate rotation without restart

See: ssl-tls.md

JSON Support

  • JsonParser: Parse JSON to Maps and Lists
  • JsonWriter: Write objects to JSON with member filtering
  • Multiple implementations: Jackson, Gson, JSON-B, Simple JSON, basic fallback

See: json-support.md

Application Information

  • BuildProperties: Build-time metadata (version, artifact, timestamp)
  • GitProperties: Git commit information (branch, commit ID, time)
  • JavaInfo: Java runtime environment details
  • OsInfo: Operating system information
  • ProcessInfo: Process details (PID, memory, virtual threads)
  • SslInfo: SSL certificate chain information

See: application-info.md

Availability Management

  • LivenessState: Indicates if application's internal state is healthy
  • ReadinessState: Indicates if application is willing to accept traffic
  • ApplicationAvailability: Query current availability states
  • AvailabilityChangeEvent: Publish state transitions for Kubernetes probes

See: availability.md

Cloud Platform Integration

  • CloudPlatform: Auto-detect cloud environments (Kubernetes, Cloud Foundry, Heroku, AWS ECS, Azure)
  • CloudFoundryVcapEnvironmentPostProcessor: Parse and expose VCAP environment variables
  • Platform-specific behavior: Automatic configuration based on detected platform

See: cloud-platform.md

Type Conversion

  • ApplicationConversionService: Enhanced conversion service with Boot-specific converters
  • DurationStyle/PeriodStyle: Parse human-readable durations and periods
  • DataSizeUnit: Type-safe data size conversion
  • Delimiter annotation: Configure delimited string-to-collection conversion

See: conversion.md

Failure Analysis

  • FailureAnalyzer: SPI for analyzing startup failures
  • FailureAnalysis: Human-readable error descriptions with suggested actions
  • Built-in analyzers: 15+ analyzers for common failure scenarios
  • Custom analyzer support: Extensible via spring.factories

See: diagnostics.md

Environment Property Sources

  • RandomValuePropertySource: Generate random values, UUIDs, ports for testing
  • ConfigTreePropertySource: Read Kubernetes ConfigMaps and Secrets from file trees
  • PropertySourceInfo: Metadata about property sources (immutability, prefixes)

See: environment-property-sources.md

Retry Support

  • RetryPolicySettings: Configure retry policies with exponential backoff and jitter
  • Exception filtering: Retry only specific exception types
  • Integration: Works with Spring Retry's @Retryable and RetryTemplate

See: retry-support.md

Startup Metrics

  • BufferingApplicationStartup: Record startup steps with nanosecond precision
  • StartupTimeline: Timeline of startup events for performance analysis
  • Performance optimization: Identify bottlenecks during application initialization

See: startup-metrics.md

System Utilities

  • ApplicationHome: Detect application home directory (JAR or exploded)
  • ApplicationPid: Process ID management and PID file writing
  • ApplicationTemp: Application-specific temporary directories
  • JavaVersion: Java version detection and comparison
  • Threading: Detect platform vs virtual threads (Java 21+)

See: system-utilities.md

Task Execution

  • ThreadPoolTaskExecutorBuilder: Configure thread pool executors
  • ThreadPoolTaskSchedulerBuilder: Configure scheduled task executors
  • SimpleAsyncTaskExecutorBuilder: Configure simple async executors with virtual thread support
  • TaskDecorator: Decorate tasks (e.g., propagate security context)

See: task-execution.md

Web Support

  • ServletRegistrationBean: Register servlets programmatically
  • FilterRegistrationBean: Register servlet filters
  • ServletListenerRegistrationBean: Register event listeners
  • ErrorPage: Define custom error pages
  • WebServer: Embedded server abstraction (Tomcat, Jetty, Undertow, Netty)
  • Reactive support: Full WebFlux/Project Reactor integration

See: web-support.md

JMX Administration

  • SpringApplicationAdminMXBean: Remote management via JMX
  • Operations: Check readiness, inspect environment, trigger shutdown
  • Production monitoring: Integration with JConsole, VisualVM

See: admin-jmx.md

ANSI Terminal Support

  • AnsiOutput: Generate ANSI colored console output with automatic terminal detection
  • AnsiColor/AnsiBackground: Standard and bright color enums (16 colors)
  • AnsiStyle: Text styling (bold, italic, underline, faint)
  • Ansi8BitColor: Extended 256-color palette support
  • Terminal detection: Automatic ANSI capability detection

See: ansi-support.md

Origin Tracking

  • Origin: Interface for tracking source location of properties and resources
  • OriginProvider/OriginLookup: Interfaces for providing and looking up origins
  • OriginTrackedValue: Wrapper for values with origin information
  • TextResourceOrigin: Origin with file path and line/column numbers
  • PropertySourceOrigin: Origin from PropertySource with property name
  • Hierarchical tracking: Parent origin support for nested origins

See: origin-tracking.md

AOT Processing and Native Image

  • SpringApplicationAotProcessor: Entry point for AOT processing during build
  • AotInitializerNotFoundException: Exception when AOT initializer missing at runtime
  • RuntimeHints API: Register reflection, resources, proxies for GraalVM
  • Native image compilation: Build standalone executables with <100ms startup
  • Build tool integration: Maven and Gradle plugin support
  • Testing: Native test support for validation

See: aot-native-image.md

Quick Start

Basic Application Bootstrap

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class MyApplication {

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

Configuration Properties

import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.context.properties.bind.DefaultValue;
import java.time.Duration;

@ConfigurationProperties(prefix = "myapp")
public class MyAppProperties {

    private String name;
    private Duration timeout = Duration.ofSeconds(30);
    private int maxRetries = 3;

    // Getters and setters
    public String getName() { return name; }
    public void setName(String name) { this.name = name; }

    public Duration getTimeout() { return timeout; }
    public void setTimeout(Duration timeout) { this.timeout = timeout; }

    public int getMaxRetries() { return maxRetries; }
    public void setMaxRetries(int maxRetries) { this.maxRetries = maxRetries; }
}

Lifecycle Event Handling

import org.springframework.boot.context.event.ApplicationReadyEvent;
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Component;

@Component
public class StartupListener {

    @EventListener(ApplicationReadyEvent.class)
    public void onReady() {
        System.out.println("Application is ready to serve traffic");
    }
}

Availability State Management

import org.springframework.boot.availability.AvailabilityChangeEvent;
import org.springframework.boot.availability.LivenessState;
import org.springframework.boot.availability.ReadinessState;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.stereotype.Component;

@Component
public class HealthManager {

    private final ApplicationEventPublisher publisher;

    public HealthManager(ApplicationEventPublisher publisher) {
        this.publisher = publisher;
    }

    public void markAsReady() {
        AvailabilityChangeEvent.publish(publisher, this, ReadinessState.ACCEPTING_TRAFFIC);
    }

    public void markAsUnhealthy() {
        AvailabilityChangeEvent.publish(publisher, this, LivenessState.BROKEN);
    }
}

Common Patterns

Pattern 1: Complete Spring Boot Application with Configuration Properties

Production-ready application demonstrating configuration properties binding and lifecycle management:

package com.example.app;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.boot.context.event.ApplicationReadyEvent;
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;

import jakarta.validation.constraints.Min;
import jakarta.validation.constraints.NotBlank;
import java.time.Duration;

/**
 * Main application class with configuration properties.
 */
@SpringBootApplication
@EnableConfigurationProperties(AppProperties.class)
public class MyApplication {

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

/**
 * Type-safe configuration properties with validation.
 */
@ConfigurationProperties(prefix = "app")
public class AppProperties {

    @NotBlank
    private String name;

    @Min(1)
    private int maxConnections = 10;

    private Duration timeout = Duration.ofSeconds(30);

    private Database database = new Database();
    private Cache cache = new Cache();

    // Getters and setters
    public String getName() { return name; }
    public void setName(String name) { this.name = name; }

    public int getMaxConnections() { return maxConnections; }
    public void setMaxConnections(int maxConnections) {
        this.maxConnections = maxConnections;
    }

    public Duration getTimeout() { return timeout; }
    public void setTimeout(Duration timeout) { this.timeout = timeout; }

    public Database getDatabase() { return database; }
    public void setDatabase(Database database) { this.database = database; }

    public Cache getCache() { return cache; }
    public void setCache(Cache cache) { this.cache = cache; }

    public static class Database {
        @NotBlank
        private String url;
        private String username;
        private String password;
        private int maxPoolSize = 20;

        // Getters and setters
        public String getUrl() { return url; }
        public void setUrl(String url) { this.url = url; }

        public String getUsername() { return username; }
        public void setUsername(String username) { this.username = username; }

        public String getPassword() { return password; }
        public void setPassword(String password) { this.password = password; }

        public int getMaxPoolSize() { return maxPoolSize; }
        public void setMaxPoolSize(int maxPoolSize) {
            this.maxPoolSize = maxPoolSize;
        }
    }

    public static class Cache {
        private boolean enabled = true;
        private Duration ttl = Duration.ofMinutes(10);
        private int maxSize = 1000;

        // Getters and setters
        public boolean isEnabled() { return enabled; }
        public void setEnabled(boolean enabled) { this.enabled = enabled; }

        public Duration getTtl() { return ttl; }
        public void setTtl(Duration ttl) { this.ttl = ttl; }

        public int getMaxSize() { return maxSize; }
        public void setMaxSize(int maxSize) { this.maxSize = maxSize; }
    }
}

/**
 * Service using configuration properties.
 */
@Service
public class ApplicationService {

    private final AppProperties properties;

    public ApplicationService(AppProperties properties) {
        this.properties = properties;
    }

    @EventListener(ApplicationReadyEvent.class)
    public void onApplicationReady() {
        System.out.println("Application Ready: " + properties.getName());
        System.out.println("Max Connections: " + properties.getMaxConnections());
        System.out.println("Timeout: " + properties.getTimeout());
        System.out.println("Database URL: " + properties.getDatabase().getUrl());
        System.out.println("Cache Enabled: " + properties.getCache().isEnabled());
    }

    public void performOperation() {
        // Use properties for business logic
        if (properties.getCache().isEnabled()) {
            System.out.println("Using cache with TTL: " + properties.getCache().getTtl());
        }
    }
}

Configuration file (application.yml):

app:
  name: MyApplication
  max-connections: 50
  timeout: 60s
  database:
    url: jdbc:postgresql://localhost:5432/mydb
    username: admin
    password: secret
    max-pool-size: 30
  cache:
    enabled: true
    ttl: 15m
    max-size: 5000

Pattern 2: Comprehensive Lifecycle Event Handling

Complete event listener system covering all application lifecycle phases:

package com.example.lifecycle;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.availability.AvailabilityChangeEvent;
import org.springframework.boot.availability.LivenessState;
import org.springframework.boot.availability.ReadinessState;
import org.springframework.boot.context.event.*;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.event.ContextClosedEvent;
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Component;

import java.time.Instant;

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

/**
 * Comprehensive lifecycle event listener demonstrating all major events.
 */
@Component
public class ApplicationLifecycleListener {

    private final ApplicationEventPublisher publisher;
    private Instant startTime;

    public ApplicationLifecycleListener(ApplicationEventPublisher publisher) {
        this.publisher = publisher;
    }

    @EventListener
    public void onApplicationStartingEvent(ApplicationStartingEvent event) {
        // Very early in startup - before Spring context is created
        // Limited functionality available
        startTime = Instant.now();
        System.out.println("1. ApplicationStartingEvent - Bootstrap starting");
    }

    @EventListener
    public void onApplicationEnvironmentPreparedEvent(ApplicationEnvironmentPreparedEvent event) {
        // Environment is ready, but context not yet created
        // Can access/modify environment here
        System.out.println("2. ApplicationEnvironmentPreparedEvent - Environment ready");
        System.out.println("   Active profiles: " +
            String.join(",", event.getEnvironment().getActiveProfiles()));
    }

    @EventListener
    public void onApplicationContextInitializedEvent(ApplicationContextInitializedEvent event) {
        // Context created but not yet refreshed
        System.out.println("3. ApplicationContextInitializedEvent - Context initialized");
    }

    @EventListener
    public void onApplicationPreparedEvent(ApplicationPreparedEvent event) {
        // Context prepared and bean definitions loaded, but not yet refreshed
        System.out.println("4. ApplicationPreparedEvent - Context prepared, beans loading");
    }

    @EventListener
    public void onApplicationStartedEvent(ApplicationStartedEvent event) {
        // Context refreshed, application started but CommandLineRunners not yet called
        System.out.println("5. ApplicationStartedEvent - Context refreshed");

        // Now safe to publish availability events
        AvailabilityChangeEvent.publish(publisher, this, LivenessState.CORRECT);
    }

    @EventListener
    public void onApplicationReadyEvent(ApplicationReadyEvent event) {
        // Application fully started and ready to serve requests
        Instant now = Instant.now();
        long startupTime = now.toEpochMilli() - startTime.toEpochMilli();

        System.out.println("6. ApplicationReadyEvent - Application READY");
        System.out.println("   Startup time: " + startupTime + "ms");

        // Mark application as ready to accept traffic
        AvailabilityChangeEvent.publish(publisher, this, ReadinessState.ACCEPTING_TRAFFIC);

        // Perform post-startup initialization
        performPostStartupTasks();
    }

    @EventListener
    public void onApplicationFailedEvent(ApplicationFailedEvent event) {
        // Application failed to start
        System.err.println("7. ApplicationFailedEvent - Startup FAILED");
        System.err.println("   Error: " + event.getException().getMessage());

        // Mark application as broken
        AvailabilityChangeEvent.publish(publisher, this, LivenessState.BROKEN);
    }

    @EventListener
    public void onContextClosedEvent(ContextClosedEvent event) {
        // Application is shutting down
        System.out.println("8. ContextClosedEvent - Application shutting down");

        // Mark application as refusing traffic
        AvailabilityChangeEvent.publish(publisher, this, ReadinessState.REFUSING_TRAFFIC);

        // Perform cleanup
        performShutdownTasks();
    }

    @EventListener
    public void onAvailabilityChangeEvent(AvailabilityChangeEvent<?> event) {
        // Availability state changed
        System.out.println("   AvailabilityChangeEvent: " +
            event.getState().getClass().getSimpleName() + " -> " + event.getState());
    }

    private void performPostStartupTasks() {
        // Warm up caches, establish connections, etc.
        System.out.println("   Performing post-startup initialization...");
    }

    private void performShutdownTasks() {
        // Flush buffers, close connections, etc.
        System.out.println("   Performing graceful shutdown tasks...");
    }
}

Pattern 3: Custom Failure Analyzer

Production-ready failure analyzer for custom error handling:

package com.example.diagnostics;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.diagnostics.AbstractFailureAnalyzer;
import org.springframework.boot.diagnostics.FailureAnalysis;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Service;

import jakarta.annotation.PostConstruct;

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

/**
 * Custom exception for configuration errors.
 */
class InvalidConfigurationException extends RuntimeException {
    private final String configKey;
    private final String providedValue;
    private final String expectedFormat;

    public InvalidConfigurationException(String configKey, String providedValue,
                                        String expectedFormat) {
        super(String.format("Invalid configuration for '%s': '%s'", configKey, providedValue));
        this.configKey = configKey;
        this.providedValue = providedValue;
        this.expectedFormat = expectedFormat;
    }

    public String getConfigKey() { return configKey; }
    public String getProvidedValue() { return providedValue; }
    public String getExpectedFormat() { return expectedFormat; }
}

/**
 * Custom failure analyzer providing helpful error messages and solutions.
 */
public class InvalidConfigurationFailureAnalyzer
        extends AbstractFailureAnalyzer<InvalidConfigurationException> {

    @Override
    protected FailureAnalysis analyze(Throwable rootFailure,
                                     InvalidConfigurationException cause) {
        StringBuilder description = new StringBuilder();
        description.append("Application failed to start due to invalid configuration.\n\n");
        description.append("Configuration Key: ").append(cause.getConfigKey()).append("\n");
        description.append("Provided Value: ").append(cause.getProvidedValue()).append("\n");
        description.append("Expected Format: ").append(cause.getExpectedFormat()).append("\n");

        StringBuilder action = new StringBuilder();
        action.append("Update your configuration:\n\n");
        action.append("1. Check application.properties or application.yml\n");
        action.append("2. Ensure '").append(cause.getConfigKey())
              .append("' matches format: ").append(cause.getExpectedFormat()).append("\n");
        action.append("3. Example: ").append(getExample(cause.getConfigKey())).append("\n");
        action.append("\nFor more information, see: https://docs.example.com/config/")
              .append(cause.getConfigKey().replace('.', '-'));

        return new FailureAnalysis(description.toString(), action.toString(), cause);
    }

    private String getExample(String configKey) {
        return switch (configKey) {
            case "app.database.url" ->
                "app.database.url=jdbc:postgresql://localhost:5432/mydb";
            case "app.timeout" ->
                "app.timeout=30s";
            case "app.max-connections" ->
                "app.max-connections=50";
            default ->
                configKey + "=<valid-value>";
        };
    }
}

/**
 * Service that validates configuration during startup.
 */
@Service
class ConfigurationValidator {

    private final String databaseUrl;

    public ConfigurationValidator(@org.springframework.beans.factory.annotation.Value("${app.database.url}")
                                  String databaseUrl) {
        this.databaseUrl = databaseUrl;
    }

    @PostConstruct
    public void validate() {
        // Validate database URL format
        if (!databaseUrl.startsWith("jdbc:")) {
            throw new InvalidConfigurationException(
                "app.database.url",
                databaseUrl,
                "jdbc:<database-type>://<host>:<port>/<database>"
            );
        }

        System.out.println("Configuration validated successfully");
    }
}

Register the analyzer in META-INF/spring.factories:

org.springframework.boot.diagnostics.FailureAnalyzer=\
com.example.diagnostics.InvalidConfigurationFailureAnalyzer

Pattern 4: Multi-Environment Application Runner

Application runner with environment-specific initialization:

package com.example.runner;

import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Profile;
import org.springframework.core.annotation.Order;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Component;

import java.util.Arrays;

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

/**
 * Ordered runner that executes first - performs critical initialization.
 */
@Component
@Order(1)
class DatabaseInitializationRunner implements ApplicationRunner {

    @Override
    public void run(ApplicationArguments args) throws Exception {
        System.out.println("1. Database Initialization Runner");
        System.out.println("   Initializing database schema...");
        System.out.println("   Creating indexes...");

        // Access command-line arguments
        if (args.containsOption("force-recreate")) {
            System.out.println("   Force recreate enabled");
        }

        // Access non-option args
        if (!args.getNonOptionArgs().isEmpty()) {
            System.out.println("   Additional args: " + args.getNonOptionArgs());
        }
    }
}

/**
 * Ordered runner that executes second - loads reference data.
 */
@Component
@Order(2)
class DataLoadingRunner implements CommandLineRunner {

    @Override
    public void run(String... args) throws Exception {
        System.out.println("2. Data Loading Runner");
        System.out.println("   Loading reference data...");
        System.out.println("   Command-line args: " + Arrays.toString(args));
    }
}

/**
 * Profile-specific runner for development environment.
 */
@Component
@Order(3)
@Profile("dev")
class DevelopmentDataRunner implements ApplicationRunner {

    @Override
    public void run(ApplicationArguments args) throws Exception {
        System.out.println("3. Development Data Runner (dev profile only)");
        System.out.println("   Loading test users...");
        System.out.println("   Loading sample data...");
    }
}

/**
 * Profile-specific runner for production environment.
 */
@Component
@Order(3)
@Profile("prod")
class ProductionVerificationRunner implements ApplicationRunner {

    private final Environment environment;

    public ProductionVerificationRunner(Environment environment) {
        this.environment = environment;
    }

    @Override
    public void run(ApplicationArguments args) throws Exception {
        System.out.println("3. Production Verification Runner (prod profile only)");

        // Verify critical configuration
        String dbUrl = environment.getProperty("app.database.url");
        if (dbUrl == null || dbUrl.contains("localhost")) {
            throw new IllegalStateException(
                "Invalid database URL for production: " + dbUrl
            );
        }

        System.out.println("   Production environment verified");
        System.out.println("   Database: " + dbUrl);
    }
}

/**
 * Runner with error handling and retry logic.
 */
@Component
@Order(4)
class ExternalServiceHealthCheckRunner implements ApplicationRunner {

    private static final int MAX_RETRIES = 3;

    @Override
    public void run(ApplicationArguments args) throws Exception {
        System.out.println("4. External Service Health Check Runner");

        int attempt = 0;
        boolean healthy = false;

        while (attempt < MAX_RETRIES && !healthy) {
            attempt++;
            System.out.println("   Health check attempt " + attempt + "/" + MAX_RETRIES);

            try {
                // Simulate health check
                Thread.sleep(1000);
                healthy = checkExternalServices();

                if (healthy) {
                    System.out.println("   All external services healthy");
                }
            } catch (Exception e) {
                System.err.println("   Health check failed: " + e.getMessage());

                if (attempt >= MAX_RETRIES) {
                    throw new IllegalStateException(
                        "External services not available after " + MAX_RETRIES + " attempts"
                    );
                }

                // Exponential backoff
                Thread.sleep(1000L * attempt);
            }
        }
    }

    private boolean checkExternalServices() {
        // Check external APIs, databases, message queues, etc.
        return true;
    }
}

Run with arguments:

java -jar app.jar --force-recreate --spring.profiles.active=dev additional-arg

Pattern 5: Advanced SSL/TLS Configuration with Hot Reload

Complete SSL bundle management with certificate rotation:

package com.example.ssl;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.ssl.SslBundle;
import org.springframework.boot.ssl.SslBundles;
import org.springframework.boot.web.server.Ssl;
import org.springframework.boot.web.server.WebServerFactoryCustomizer;
import org.springframework.boot.web.servlet.server.ConfigurableServletWebServerFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import java.time.Instant;
import java.util.concurrent.atomic.AtomicReference;

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

/**
 * SSL configuration with hot reload support.
 */
@Component
class SslConfigurationManager {

    private final SslBundles sslBundles;
    private final AtomicReference<Instant> lastReload = new AtomicReference<>(Instant.now());

    public SslConfigurationManager(SslBundles sslBundles) {
        this.sslBundles = sslBundles;
    }

    /**
     * Check for certificate updates every hour.
     */
    @Scheduled(fixedRate = 3600000) // Every hour
    public void checkCertificateExpiry() {
        try {
            SslBundle bundle = sslBundles.getBundle("server");

            // Get certificate details (implementation depends on bundle type)
            System.out.println("Checking SSL certificate status...");
            System.out.println("Last reload: " + lastReload.get());

            // Trigger reload if certificate is close to expiry or has been updated
            // In production, check actual certificate expiry dates
            boolean needsReload = shouldReloadCertificate(bundle);

            if (needsReload) {
                reloadCertificate();
            }
        } catch (Exception e) {
            System.err.println("Failed to check certificate status: " + e.getMessage());
        }
    }

    private boolean shouldReloadCertificate(SslBundle bundle) {
        // Check if certificate file has been modified
        // Check if certificate is within 30 days of expiry
        // Implementation depends on your certificate management strategy
        return false;
    }

    public void reloadCertificate() {
        System.out.println("Reloading SSL certificate...");

        try {
            // Reload certificate from disk or certificate store
            // This triggers bundle update listeners
            SslBundle bundle = sslBundles.getBundle("server");

            lastReload.set(Instant.now());
            System.out.println("SSL certificate reloaded successfully at " + lastReload.get());
        } catch (Exception e) {
            System.err.println("Failed to reload certificate: " + e.getMessage());
            throw new RuntimeException("Certificate reload failed", e);
        }
    }
}

/**
 * Web server customizer for SSL configuration.
 */
@Component
class SslWebServerCustomizer implements WebServerFactoryCustomizer<ConfigurableServletWebServerFactory> {

    private final SslBundles sslBundles;

    public SslWebServerCustomizer(SslBundles sslBundles) {
        this.sslBundles = sslBundles;
    }

    @Override
    public void customize(ConfigurableServletWebServerFactory factory) {
        try {
            SslBundle bundle = sslBundles.getBundle("server");

            Ssl ssl = new Ssl();
            ssl.setEnabled(true);

            // Configure SSL from bundle
            factory.setSsl(ssl);

            System.out.println("SSL configured from bundle 'server'");
        } catch (Exception e) {
            System.err.println("Failed to configure SSL: " + e.getMessage());
        }
    }
}

Configuration (application.yml):

spring:
  ssl:
    bundle:
      pem:
        server:
          keystore:
            certificate: classpath:ssl/server.crt
            private-key: classpath:ssl/server.key
          truststore:
            certificate: classpath:ssl/ca.crt
      jks:
        client:
          keystore:
            location: classpath:ssl/client-keystore.jks
            password: changeit
            type: JKS
          truststore:
            location: classpath:ssl/client-truststore.jks
            password: changeit

server:
  port: 8443
  ssl:
    enabled: true
    bundle: server

Best Practices

  1. Configuration Properties Best Practices

    • Use @ConfigurationProperties for type-safe configuration instead of @Value
    • Enable validation with @Validated and JSR-303 annotations
    • Provide sensible defaults for all properties
    • Use nested classes for complex hierarchical configuration
    • Document properties with Javadoc for IDE autocomplete support
  2. Application Lifecycle Management

    • Use ApplicationReadyEvent for post-startup initialization, not @PostConstruct
    • Handle ApplicationFailedEvent for proper error reporting
    • Publish availability state changes for Kubernetes liveness/readiness probes
    • Use @Order to control ApplicationRunner/CommandLineRunner execution sequence
    • Implement graceful shutdown with ContextClosedEvent listeners
  3. Error Handling and Diagnostics

    • Create custom FailureAnalyzer implementations for domain-specific errors
    • Provide actionable error messages with specific solutions
    • Include links to documentation in failure analysis descriptions
    • Log failures with sufficient context for troubleshooting
    • Use fail-fast validation during startup for critical configuration
  4. Environment-Specific Configuration

    • Use Spring profiles for environment-specific beans and configuration
    • Externalize configuration using environment variables in production
    • Never hardcode credentials or secrets in application code
    • Use different property files per environment (application-{profile}.yml)
    • Validate production configuration during startup
  5. Dependency Injection Best Practices

    • Prefer constructor injection over field injection for required dependencies
    • Use @Autowired only for optional dependencies
    • Make injected fields final to ensure immutability
    • Avoid circular dependencies by redesigning component relationships
    • Use ObjectProvider<T> for lazy or optional bean resolution
  6. Logging Configuration

    • Configure logging levels per package, not globally
    • Use structured logging with correlation IDs for request tracking
    • Set appropriate log levels for third-party libraries (reduce noise)
    • Enable debug logging only for specific packages during troubleshooting
    • Use async appenders in high-throughput applications
  7. Performance and Resource Management

    • Configure appropriate thread pool sizes for task executors
    • Set connection pool limits based on expected load
    • Enable lazy initialization (spring.main.lazy-initialization=true) for faster startup in development
    • Use @ConditionalOnProperty to disable features not needed in certain environments
    • Monitor startup time with BufferingApplicationStartup and optimize bottlenecks
  8. Security Configuration

    • Always use SSL/TLS in production (configure via spring.ssl.bundle)
    • Implement certificate rotation with SslBundles hot reload
    • Never log sensitive configuration values (passwords, tokens, keys)
    • Use Spring Boot's secrets management for encrypted properties
    • Validate all external configuration inputs during binding
  9. Testing Strategies

    • Use @SpringBootTest for full integration tests
    • Use @TestPropertySource to override configuration in tests
    • Test each Spring profile configuration separately
    • Mock external dependencies with @MockBean for unit tests
    • Verify startup behavior with OutputCaptureExtension for log assertions
  10. Production Readiness

    • Enable Spring Boot Actuator endpoints for monitoring
    • Configure health indicators for all critical dependencies
    • Set up proper logging aggregation and monitoring
    • Implement distributed tracing (Micrometer Tracing + Zipkin)
    • Use build metadata (spring-boot-maven-plugin with build-info goal) for version tracking

Common Pitfalls

1. Missing @EnableConfigurationProperties

Problem: @ConfigurationProperties class not registered as a bean

Error:

Parameter 0 of constructor in com.example.MyService required a bean of type 'com.example.AppProperties' that could not be found.

Solution:

// Solution 1: Enable in main application class
@SpringBootApplication
@EnableConfigurationProperties(AppProperties.class)
public class MyApplication {
    // ...
}

// Solution 2: Add @Component to properties class
@Component
@ConfigurationProperties(prefix = "app")
public class AppProperties {
    // ...
}

// Solution 3: Use @ConfigurationPropertiesScan
@SpringBootApplication
@ConfigurationPropertiesScan("com.example.config")
public class MyApplication {
    // ...
}

Rationale: Spring Boot requires explicit registration of @ConfigurationProperties classes. Without registration, the class is not instantiated as a bean and cannot be injected into other components.

2. Incorrect Property Naming Convention

Problem: Properties not binding due to naming mismatch

Error: Properties remain null despite being set in application.properties

Solution:

# WRONG - uses dots in compound words
app.maxconnections=50
app.database.maxpoolsize=20

# CORRECT - use kebab-case (recommended)
app.max-connections=50
app.database.max-pool-size=20

# Also works - camelCase
app.maxConnections=50
app.database.maxPoolSize=20
// Java property names use camelCase
@ConfigurationProperties(prefix = "app")
public class AppProperties {
    private int maxConnections;  // Binds to app.max-connections or app.maxConnections

    public int getMaxConnections() { return maxConnections; }
    public void setMaxConnections(int maxConnections) {
        this.maxConnections = maxConnections;
    }
}

Rationale: Spring Boot uses relaxed binding to map property names. Use kebab-case in properties files (recommended) or camelCase. Always use camelCase in Java code. Spring Boot automatically converts between formats.

3. ApplicationRunner vs CommandLineRunner Confusion

Problem: Using wrong interface or expecting wrong argument format

Error: Cannot access parsed command-line options

Solution:

// Use ApplicationRunner when you need parsed arguments
@Component
class MyApplicationRunner implements ApplicationRunner {
    @Override
    public void run(ApplicationArguments args) throws Exception {
        // Access options: --option=value
        if (args.containsOption("debug")) {
            System.out.println("Debug mode enabled");
        }

        // Access non-option args
        List<String> nonOptionArgs = args.getNonOptionArgs();
    }
}

// Use CommandLineRunner when you need raw String[] args
@Component
class MyCommandLineRunner implements CommandLineRunner {
    @Override
    public void run(String... args) throws Exception {
        // Access raw arguments
        System.out.println("Args: " + Arrays.toString(args));
    }
}

Rationale: ApplicationRunner provides parsed arguments via ApplicationArguments, making it easier to access named options. CommandLineRunner provides raw String[] array. Use ApplicationRunner unless you specifically need raw access.

4. Lifecycle Event Timing Issues

Problem: Accessing beans or context too early in lifecycle

Error:

BeanCreationNotAllowedException: Error creating bean with name 'myBean'
NullPointerException when accessing ApplicationContext

Solution:

// WRONG - Too early, context not ready
@Component
public class EarlyInitializer {
    private final ApplicationContext context;

    public EarlyInitializer(ApplicationContext context) {
        // DON'T access beans in constructor
        context.getBean(MyService.class); // MAY FAIL
    }
}

// CORRECT - Use appropriate lifecycle callback
@Component
public class ProperInitializer {

    @Autowired
    private MyService myService; // Injected after construction

    @PostConstruct
    public void init() {
        // Safe to use injected beans here
        myService.initialize();
    }

    @EventListener(ApplicationReadyEvent.class)
    public void onReady() {
        // Safest - application fully started
        myService.performOperation();
    }
}

Rationale: Constructor execution happens during bean creation, before all dependencies are wired. Use @PostConstruct for bean initialization or ApplicationReadyEvent for application-wide initialization after full startup.

5. Missing Validation Annotations

Problem: Invalid configuration accepted without errors

Error: Application starts with invalid configuration, fails later at runtime

Solution:

import jakarta.validation.constraints.*;

@Validated  // REQUIRED for validation to work
@ConfigurationProperties(prefix = "app")
public class AppProperties {

    @NotBlank(message = "Application name is required")
    private String name;

    @Min(value = 1, message = "Max connections must be at least 1")
    @Max(value = 100, message = "Max connections cannot exceed 100")
    private int maxConnections = 10;

    @Pattern(regexp = "^jdbc:.*", message = "Database URL must start with 'jdbc:'")
    private String databaseUrl;

    @NotNull
    @DurationMin(seconds = 1)
    @DurationMax(minutes = 5)
    private Duration timeout;

    // Getters and setters with validation
}

Configuration to trigger validation failure:

app.name=
app.max-connections=150
app.database-url=invalid-url
app.timeout=10m

Rationale: Without @Validated annotation on the properties class, JSR-303 validation annotations are ignored. Application accepts invalid configuration and fails unpredictably later. Always validate critical configuration.

6. Circular Dependency in ApplicationRunner

Problem: ApplicationRunner depends on beans that depend on runner completion

Error:

The dependencies of some of the beans in the application context form a cycle

Solution:

// WRONG - Circular dependency
@Component
class DataLoader implements ApplicationRunner {
    private final MyService service; // MyService depends on DataLoader completion

    @Override
    public void run(ApplicationArguments args) {
        service.loadData(); // Circular!
    }
}

// CORRECT - Break circular dependency
@Component
class DataLoader implements ApplicationRunner {
    private final ApplicationContext context;

    public DataLoader(ApplicationContext context) {
        this.context = context;
    }

    @Override
    public void run(ApplicationArguments args) {
        // Lazy lookup breaks circular dependency
        MyService service = context.getBean(MyService.class);
        service.loadData();
    }
}

// BETTER - Use event listener instead
@Component
class DataLoader {

    private final MyService service;

    public DataLoader(MyService service) {
        this.service = service;
    }

    @EventListener(ApplicationReadyEvent.class)
    public void onReady() {
        service.loadData();
    }
}

Rationale: ApplicationRunner beans are created during startup, which can create circular dependencies. Use lazy lookup via ApplicationContext or switch to @EventListener(ApplicationReadyEvent.class) which fires after all beans are created.

7. Forgetting to Set spring.application.name

Problem: Application identified as "application" in logs and monitoring

Error: Cannot distinguish between multiple applications in distributed systems

Solution:

# application.properties
spring.application.name=my-service

# Or application.yml
spring:
  application:
    name: my-service
// Access programmatically
@Component
public class AppNameChecker {

    @Value("${spring.application.name}")
    private String applicationName;

    @PostConstruct
    public void checkName() {
        if ("application".equals(applicationName)) {
            throw new IllegalStateException(
                "Application name not configured. Set spring.application.name in properties"
            );
        }
    }
}

Rationale: Default application name is "application", which makes it impossible to identify services in logs, metrics, and distributed tracing. Always set a unique application name for each service.

8. Incorrect SSL Bundle Configuration

Problem: SSL certificate not loaded or server won't start with SSL

Error:

java.io.FileNotFoundException: class path resource [ssl/server.crt] cannot be opened
SSL handshake failed

Solution:

# Correct PEM configuration
spring:
  ssl:
    bundle:
      pem:
        server:
          keystore:
            certificate: "file:/etc/ssl/certs/server.crt"  # Use file: for filesystem
            private-key: "file:/etc/ssl/private/server.key"
          truststore:
            certificate: "file:/etc/ssl/certs/ca.crt"

# Or use classpath (must be in resources/)
spring:
  ssl:
    bundle:
      pem:
        server:
          keystore:
            certificate: "classpath:ssl/server.crt"
            private-key: "classpath:ssl/server.key"

# Enable SSL on server
server:
  port: 8443
  ssl:
    enabled: true
    bundle: server
// Verify SSL configuration at startup
@Component
public class SslConfigurationValidator {

    @Value("${server.ssl.enabled:false}")
    private boolean sslEnabled;

    @Value("${server.ssl.bundle:}")
    private String sslBundle;

    @PostConstruct
    public void validate() {
        if (sslEnabled && sslBundle.isEmpty()) {
            throw new IllegalStateException(
                "SSL enabled but no bundle configured. Set server.ssl.bundle"
            );
        }
    }
}

Rationale: SSL bundle configuration requires correct resource prefix (file: or classpath:) and valid certificate files. Without proper configuration, server fails to start with cryptic SSL errors. Always validate SSL configuration at startup.

9. Not Handling Failed Application Start

Problem: Application fails silently or with unhelpful error messages

Error: Startup fails but root cause is buried in stack trace

Solution:

@Component
public class StartupFailureHandler {

    @EventListener
    public void onApplicationFailed(ApplicationFailedEvent event) {
        Throwable exception = event.getException();

        System.err.println("=================================");
        System.err.println("APPLICATION FAILED TO START");
        System.err.println("=================================");
        System.err.println("Reason: " + exception.getMessage());
        System.err.println("Exception type: " + exception.getClass().getName());

        // Log specific failure types
        if (exception instanceof BeanCreationException) {
            System.err.println("Bean creation failed - check configuration and dependencies");
        } else if (exception instanceof BindException) {
            System.err.println("Configuration binding failed - check properties");
        } else if (exception instanceof DataAccessException) {
            System.err.println("Database connection failed - check database configuration");
        }

        System.err.println("\nFull stack trace:");
        exception.printStackTrace();

        // Optionally send alerts
        sendStartupFailureAlert(exception);
    }

    private void sendStartupFailureAlert(Throwable exception) {
        // Send to monitoring system, Slack, PagerDuty, etc.
    }
}

Rationale: Default Spring Boot error messages can be difficult to diagnose. Listening to ApplicationFailedEvent allows custom error handling, better logging, and alerting. Essential for production troubleshooting.

10. Property Precedence Confusion

Problem: Properties from wrong source taking effect

Error: Expected property value not being used

Solution:

// Understand property source precedence (highest to lowest):
// 1. Command line arguments
// 2. SPRING_APPLICATION_JSON properties
// 3. ServletConfig init parameters
// 4. ServletContext init parameters
// 5. JNDI attributes from java:comp/env
// 6. Java System properties (System.getProperties())
// 7. OS environment variables
// 8. Profile-specific application properties (application-{profile}.properties)
// 9. Application properties (application.properties)
// 10. @PropertySource annotations
// 11. Default properties (SpringApplication.setDefaultProperties)

// Example: Debug property sources
@Component
public class PropertySourceDebugger {

    private final ConfigurableEnvironment environment;

    public PropertySourceDebugger(ConfigurableEnvironment environment) {
        this.environment = environment;
    }

    @EventListener(ApplicationReadyEvent.class)
    public void debugPropertySources() {
        String propertyKey = "app.database.url";
        String value = environment.getProperty(propertyKey);

        System.out.println("\n=== Property Source Debug ===");
        System.out.println("Property: " + propertyKey);
        System.out.println("Final value: " + value);
        System.out.println("\nProperty sources (in precedence order):");

        environment.getPropertySources().forEach(source -> {
            if (source instanceof EnumerablePropertySource) {
                EnumerablePropertySource<?> enumerable = (EnumerablePropertySource<?>) source;
                for (String name : enumerable.getPropertyNames()) {
                    if (name.equals(propertyKey)) {
                        System.out.println("  " + source.getName() + ": " +
                            enumerable.getProperty(name));
                    }
                }
            }
        });
    }
}
# Override in specific environments
# application.properties (default)
app.database.url=jdbc:postgresql://localhost:5432/devdb

# application-prod.properties (production override)
app.database.url=jdbc:postgresql://prod-db:5432/proddb

# Can also override via environment variable
# APP_DATABASE_URL=jdbc:postgresql://override-db:5432/db

# Or command line (highest precedence)
# java -jar app.jar --app.database.url=jdbc:postgresql://cmdline-db:5432/db

Rationale: Spring Boot has complex property precedence rules. Properties can be overridden from multiple sources, leading to unexpected values. Use environment-specific property files and understand precedence order to avoid conflicts.

Import Statements

// Core application
import org.springframework.boot.SpringApplication;
import org.springframework.boot.SpringApplicationRunListener;
import org.springframework.boot.autoconfigure.SpringBootApplication;

// Configuration
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.boot.context.config.*;

// Lifecycle
import org.springframework.boot.context.event.*;
import org.springframework.boot.ApplicationRunner;
import org.springframework.boot.CommandLineRunner;

// Availability
import org.springframework.boot.availability.*;

// Logging
import org.springframework.boot.logging.*;

// SSL/TLS
import org.springframework.boot.ssl.*;

// JSON
import org.springframework.boot.json.*;

// Info
import org.springframework.boot.info.*;

// Cloud
import org.springframework.boot.cloud.*;

// Conversion
import org.springframework.boot.convert.*;

// Diagnostics
import org.springframework.boot.diagnostics.*;

// System
import org.springframework.boot.system.*;

// Task execution
import org.springframework.boot.task.*;

// Web
import org.springframework.boot.web.server.*;
import org.springframework.boot.web.servlet.*;
import org.springframework.boot.web.error.*;

Key Characteristics

Thread Safety

  • All core services (ApplicationConversionService, SslBundles, etc.) are thread-safe
  • Events can be published from any thread
  • Configuration properties are immutable after binding

Lifecycle Guarantees

  • Events are published in guaranteed order during startup and shutdown
  • ApplicationReadyEvent signals the application is fully initialized
  • ContextClosedEvent signals the start of shutdown

Extension Points

  • EnvironmentPostProcessor: Customize environment before context refresh
  • ApplicationContextInitializer: Customize context before refresh
  • FailureAnalyzer: Provide custom failure analysis (via spring.factories)
  • ConfigDataLoader/ConfigDataLocationResolver: Load custom configuration formats
  • WebServerFactoryCustomizer: Customize embedded web server

Production Features

  • Graceful shutdown support for web servers
  • Startup performance metrics with nanosecond precision
  • JMX-based remote administration
  • SSL certificate hot-reloading
  • Comprehensive failure analysis and diagnostics

Related Documentation

  • Spring Framework: For core Spring features (dependency injection, AOP, transactions)
  • Spring Boot Autoconfigure: For auto-configuration of common libraries
  • Spring Boot Actuator: For production-ready monitoring and management endpoints

Version Information

  • Current version: 4.0.0
  • Minimum Java: 17
  • Java 21+ features: Virtual threads, improved process information
  • Breaking changes from 3.x: Web server factory API refactored for improved configurability

Install with Tessl CLI

npx tessl i tessl/maven-org-springframework-boot--spring-boot
Workspace
tessl
Visibility
Public
Created
Last updated
Describes
mavenpkg:maven/org.springframework.boot/spring-boot@4.0.x