• 1.6.1. Liveness State
  • 1.6.2. Readiness State
  • 1.6.3. Managing the Application Availability State
  • 1.7. Application Events and Listeners
  • 1.8. Web Environment
  • 1.9. Accessing Application Arguments
  • 1.10. Using the ApplicationRunner or CommandLineRunner
  • 1.11. Application Exit
  • 1.12. Admin Features
  • 1.13. Application Startup tracking
  • 2. Externalized Configuration
  • 2.1. Accessing Command Line Properties
  • 2.2. JSON Application Properties
  • 2.3. External Application Properties
  • 2.3.1. Optional Locations
  • 2.3.2. Wildcard Locations
  • 2.3.3. Profile Specific Files
  • 2.3.4. Importing Additional Data
  • 2.3.5. Importing Extensionless Files
  • 2.3.6. Using Configuration Trees
  • 2.3.7. Property Placeholders
  • 2.3.8. Working With Multi-Document Files
  • 2.3.9. Activation Properties
  • 2.4. Encrypting Properties
  • 2.5. Working With YAML
  • 2.5.1. Mapping YAML to Properties
  • 2.5.2. Directly Loading YAML
  • 2.6. Configuring Random Values
  • 2.7. Configuring System Environment Properties
  • 2.8. Type-safe Configuration Properties
  • 2.8.1. JavaBean Properties Binding
  • 2.8.2. Constructor Binding
  • 2.8.3. Enabling @ConfigurationProperties-annotated Types
  • 2.8.4. Using @ConfigurationProperties-annotated Types
  • 2.8.5. Third-party Configuration
  • 2.8.6. Relaxed Binding
  • Binding Maps
  • Binding From Environment Variables
  • 2.8.7. Merging Complex Types
  • 2.8.8. Properties Conversion
  • Converting Durations
  • Converting Periods
  • Converting Data Sizes
  • 2.8.9. @ConfigurationProperties Validation
  • 2.8.10. @ConfigurationProperties vs. @Value
  • 3.2. Profile Groups
  • 3.3. Programmatically Setting Profiles
  • 3.4. Profile-specific Configuration Files
  • 4. Logging
  • 4.1. Log Format
  • 4.2. Console Output
  • 4.2.1. Color-coded Output
  • 4.3. File Output
  • 4.4. File Rotation
  • 4.5. Log Levels
  • 4.6. Log Groups
  • 4.7. Using a Log Shutdown Hook
  • 4.8. Custom Log Configuration
  • 4.9. Logback Extensions
  • 4.9.1. Profile-specific Configuration
  • 4.9.2. Environment Properties
  • 4.10. Log4j2 Extensions
  • 4.10.1. Profile-specific Configuration
  • 4.10.2. Environment Properties Lookup
  • 4.10.3. Log4j2 System Properties
  • 8.1. Test Scope Dependencies
  • 8.2. Testing Spring Applications
  • 8.3. Testing Spring Boot Applications
  • 8.3.1. Detecting Web Application Type
  • 8.3.2. Detecting Test Configuration
  • 8.3.3. Using the Test Configuration Main Method
  • 8.3.4. Excluding Test Configuration
  • 8.3.5. Using Application Arguments
  • 8.3.6. Testing With a Mock Environment
  • 8.3.7. Testing With a Running Server
  • 8.3.8. Customizing WebTestClient
  • 8.3.9. Using JMX
  • 8.3.10. Using Metrics
  • 8.3.11. Using Tracing
  • 8.3.12. Mocking and Spying Beans
  • 8.3.13. Auto-configured Tests
  • 8.3.14. Auto-configured JSON Tests
  • 8.3.15. Auto-configured Spring MVC Tests
  • 8.3.16. Auto-configured Spring WebFlux Tests
  • 8.3.17. Auto-configured Spring GraphQL Tests
  • 8.3.18. Auto-configured Data Cassandra Tests
  • 8.3.19. Auto-configured Data Couchbase Tests
  • 8.3.20. Auto-configured Data Elasticsearch Tests
  • 8.3.21. Auto-configured Data JPA Tests
  • 8.3.22. Auto-configured JDBC Tests
  • 8.3.23. Auto-configured Data JDBC Tests
  • 8.3.24. Auto-configured jOOQ Tests
  • 8.3.25. Auto-configured Data MongoDB Tests
  • 8.3.26. Auto-configured Data Neo4j Tests
  • 8.3.27. Auto-configured Data Redis Tests
  • 8.3.28. Auto-configured Data LDAP Tests
  • 8.3.29. Auto-configured REST Clients
  • 8.3.30. Auto-configured Spring REST Docs Tests
  • Auto-configured Spring REST Docs Tests With Mock MVC
  • Auto-configured Spring REST Docs Tests With WebTestClient
  • Auto-configured Spring REST Docs Tests With REST Assured
  • 8.3.31. Auto-configured Spring Web Services Tests
  • Auto-configured Spring Web Services Client Tests
  • Auto-configured Spring Web Services Server Tests
  • 8.3.32. Additional Auto-configuration and Slicing
  • 8.3.33. User Configuration and Slicing
  • 8.3.34. Using Spock to Test Spring Boot Applications
  • 8.4. Test Utilities
  • 8.4.1. ConfigDataApplicationContextInitializer
  • 8.4.2. TestPropertyValues
  • 8.4.3. OutputCapture
  • 8.4.4. TestRestTemplate
  • 9.1. Understanding Auto-configured Beans
  • 9.2. Locating Auto-configuration Candidates
  • 9.3. Condition Annotations
  • 9.3.1. Class Conditions
  • 9.3.2. Bean Conditions
  • 9.3.3. Property Conditions
  • 9.3.4. Resource Conditions
  • 9.3.5. Web Application Conditions
  • 9.3.6. SpEL Expression Conditions
  • 9.4. Testing your Auto-configuration
  • 9.4.1. Simulating a Web Context
  • 9.4.2. Overriding the Classpath
  • 9.5. Creating Your Own Starter
  • 9.5.1. Naming
  • 9.5.2. Configuration keys
  • 9.5.3. The “autoconfigure” Module
  • 9.5.4. Starter Module
  • This section dives into the details of Spring Boot. Here you can learn about the key features that you may want to use and customize. If you have not already done so, you might want to read the " Getting Started " and " Developing with Spring Boot " sections, so that you have a good grounding of the basics.

    The SpringApplication class provides a convenient way to bootstrap a Spring application that is started from a main() method. In many situations, you can delegate to the static SpringApplication.run method, as shown in the following example:

    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);
    
    import org.springframework.boot.autoconfigure.SpringBootApplication
    import org.springframework.boot.runApplication
    @SpringBootApplication
    class MyApplication
    fun main(args: Array<String>) {
        runApplication<MyApplication>(*args)
    
      .   ____          _            __ _ _
     /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
    ( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
     \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
      '  |____| .__|_| |_|_| |_\__, | / / / /
     =========|_|==============|___/=/_/_/_/
     :: Spring Boot ::                (v3.0.6)
    2023-04-20T10:09:01.134Z  INFO 20343 --- [           main] o.s.b.d.f.s.MyApplication                : Starting MyApplication using Java 17.0.6 with PID 20343 (/opt/apps/myapp.jar started by myuser in /opt/apps/)
    2023-04-20T10:09:01.144Z  INFO 20343 --- [           main] o.s.b.d.f.s.MyApplication                : No active profile set, falling back to 1 default profile: "default"
    2023-04-20T10:09:03.394Z  INFO 20343 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat initialized with port(s): 8080 (http)
    2023-04-20T10:09:03.664Z  INFO 20343 --- [           main] o.apache.catalina.core.StandardService   : Starting service [Tomcat]
    2023-04-20T10:09:03.664Z  INFO 20343 --- [           main] o.apache.catalina.core.StandardEngine    : Starting Servlet engine: [Apache Tomcat/10.1.8]
    2023-04-20T10:09:03.840Z  INFO 20343 --- [           main] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring embedded WebApplicationContext
    2023-04-20T10:09:03.843Z  INFO 20343 --- [           main] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 2345 ms
    2023-04-20T10:09:04.616Z  INFO 20343 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat started on port(s): 8080 (http) with context path ''
    2023-04-20T10:09:04.642Z  INFO 20343 --- [           main] o.s.b.d.f.s.MyApplication                : Started MyApplication in 5.022 seconds (process running for 6.616)
                                                                                                    2023-04-20T10:09:04.834Z  INFO 20343 --- [ionShutdownHook] o.apache.catalina.core.StandardService   : Stopping service [Tomcat]

    By default, INFO logging messages are shown, including some relevant startup details, such as the user that launched the application. If you need a log level other than INFO, you can set it, as described in Log Levels. The application version is determined using the implementation version from the main application class’s package. Startup information logging can be turned off by setting spring.main.log-startup-info to false. This will also turn off logging of the application’s active profiles.

    1.1. Startup Failure

    If your application fails to start, registered FailureAnalyzers get a chance to provide a dedicated error message and a concrete action to fix the problem. For instance, if you start a web application on port 8080 and that port is already in use, you should see something similar to the following message:

    ***************************
    APPLICATION FAILED TO START
    ***************************
    Description:
    Embedded servlet container failed to start. Port 8080 was already in use.
    Action:
    Identify and stop the process that is listening on port 8080 or configure this application to listen on another port.

    If no failure analyzers are able to handle the exception, you can still display the full conditions report to better understand what went wrong. To do so, you need to enable the debug property or enable DEBUG logging for org.springframework.boot.autoconfigure.logging.ConditionEvaluationReportLoggingListener.

    For instance, if you are running your application by using java -jar, you can enable the debug property as follows:

    $ java -jar myproject-0.0.1-SNAPSHOT.jar --debug

    1.2. Lazy Initialization

    SpringApplication allows an application to be initialized lazily. When lazy initialization is enabled, beans are created as they are needed rather than during application startup. As a result, enabling lazy initialization can reduce the time that it takes your application to start. In a web application, enabling lazy initialization will result in many web-related beans not being initialized until an HTTP request is received.

    A downside of lazy initialization is that it can delay the discovery of a problem with the application. If a misconfigured bean is initialized lazily, a failure will no longer occur during startup and the problem will only become apparent when the bean is initialized. Care must also be taken to ensure that the JVM has sufficient memory to accommodate all of the application’s beans and not just those that are initialized during startup. For these reasons, lazy initialization is not enabled by default and it is recommended that fine-tuning of the JVM’s heap size is done before enabling lazy initialization.

    Lazy initialization can be enabled programmatically using the lazyInitialization method on SpringApplicationBuilder or the setLazyInitialization method on SpringApplication. Alternatively, it can be enabled using the spring.main.lazy-initialization property as shown in the following example:

    Properties
    spring.main.lazy-initialization=true
    spring:
      main:
        lazy-initialization: true

    1.3. Customizing the Banner

    The banner that is printed on start up can be changed by adding a banner.txt file to your classpath or by setting the spring.banner.location property to the location of such a file. If the file has an encoding other than UTF-8, you can set spring.banner.charset.

    Inside your banner.txt file, you can use any key available in the Environment as well as any of the following placeholders:

    Table 1. Banner variables

    ${application.version}

    The version number of your application, as declared in MANIFEST.MF. For example, Implementation-Version: 1.0 is printed as 1.0.

    ${application.formatted-version}

    The version number of your application, as declared in MANIFEST.MF and formatted for display (surrounded with brackets and prefixed with v). For example (v1.0).

    ${spring-boot.version}

    The Spring Boot version that you are using. For example 3.0.6.

    ${spring-boot.formatted-version}

    The Spring Boot version that you are using, formatted for display (surrounded with brackets and prefixed with v). For example (v3.0.6).

    ${Ansi.NAME} (or ${AnsiColor.NAME}, ${AnsiBackground.NAME}, ${AnsiStyle.NAME})

    Where NAME is the name of an ANSI escape code. See AnsiPropertySource for details.

    ${application.title}

    The title of your application, as declared in MANIFEST.MF. For example Implementation-Title: MyApp is printed as MyApp.

    The SpringApplication.setBanner(…​) method can be used if you want to generate a banner programmatically. Use the org.springframework.boot.Banner interface and implement your own printBanner() method.

    You can also use the spring.main.banner-mode property to determine if the banner has to be printed on System.out (console), sent to the configured logger (log), or not produced at all (off).

    The printed banner is registered as a singleton bean under the following name: springBootBanner.

    The ${application.version} and ${application.formatted-version} properties are only available if you are using Spring Boot launchers. The values will not be resolved if you are running an unpacked jar and starting it with java -cp <classpath> <mainclass>.

    This is why we recommend that you always launch unpacked jars using java org.springframework.boot.loader.JarLauncher. This will initialize the application.* banner variables before building the classpath and launching your app.

    1.4. Customizing SpringApplication

    If the SpringApplication defaults are not to your taste, you can instead create a local instance and customize it. For example, to turn off the banner, you could write:

    import org.springframework.boot.Banner;
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    @SpringBootApplication
    public class MyApplication {
        public static void main(String[] args) {
            SpringApplication application = new SpringApplication(MyApplication.class);
            application.setBannerMode(Banner.Mode.OFF);
            application.run(args);
    
    import org.springframework.boot.Banner
    import org.springframework.boot.autoconfigure.SpringBootApplication
    import org.springframework.boot.runApplication
    @SpringBootApplication
    class MyApplication
    fun main(args: Array<String>) {
        runApplication<MyApplication>(*args) {
            setBannerMode(Banner.Mode.OFF)
    The constructor arguments passed to SpringApplication are configuration sources for Spring beans.
    In most cases, these are references to @Configuration classes, but they could also be direct references @Component classes.
    

    It is also possible to configure the SpringApplication by using an application.properties file. See Externalized Configuration for details.

    For a complete list of the configuration options, see the SpringApplication Javadoc.

    1.5. Fluent Builder API

    If you need to build an ApplicationContext hierarchy (multiple contexts with a parent/child relationship) or if you prefer using a “fluent” builder API, you can use the SpringApplicationBuilder.

    The SpringApplicationBuilder lets you chain together multiple method calls and includes parent and child methods that let you create a hierarchy, as shown in the following example:

    new SpringApplicationBuilder()
            .sources(Parent.class)
            .child(Application.class)
            .bannerMode(Banner.Mode.OFF)
            .run(args);
    There are some restrictions when creating an ApplicationContext hierarchy.
    For example, Web components must be contained within the child context, and the same Environment is used for both parent and child contexts.
    See the SpringApplicationBuilder Javadoc for full details.
    

    1.6. Application Availability

    When deployed on platforms, applications can provide information about their availability to the platform using infrastructure such as Kubernetes Probes. Spring Boot includes out-of-the box support for the commonly used “liveness” and “readiness” availability states. If you are using Spring Boot’s “actuator” support then these states are exposed as health endpoint groups.

    In addition, you can also obtain availability states by injecting the ApplicationAvailability interface into your own beans.

    1.6.1. Liveness State

    The “Liveness” state of an application tells whether its internal state allows it to work correctly, or recover by itself if it is currently failing. A broken “Liveness” state means that the application is in a state that it cannot recover from, and the infrastructure should restart the application.

    In general, the "Liveness" state should not be based on external checks, such as
    Health checks. If it did, a failing external system (a database, a Web API, an external cache) would trigger massive restarts and cascading failures across the platform.

    The internal state of Spring Boot applications is mostly represented by the Spring ApplicationContext. If the application context has started successfully, Spring Boot assumes that the application is in a valid state. An application is considered live as soon as the context has been refreshed, see Spring Boot application lifecycle and related Application Events.

    1.6.2. Readiness State

    The “Readiness” state of an application tells whether the application is ready to handle traffic. A failing “Readiness” state tells the platform that it should not route traffic to the application for now. This typically happens during startup, while CommandLineRunner and ApplicationRunner components are being processed, or at any time if the application decides that it is too busy for additional traffic.

    An application is considered ready as soon as application and command-line runners have been called, see Spring Boot application lifecycle and related Application Events.

    1.6.3. Managing the Application Availability State

    Application components can retrieve the current availability state at any time, by injecting the ApplicationAvailability interface and calling methods on it. More often, applications will want to listen to state updates or update the state of the application.

    For example, we can export the "Readiness" state of the application to a file so that a Kubernetes "exec Probe" can look at this file:

    import org.springframework.boot.availability.AvailabilityChangeEvent;
    import org.springframework.boot.availability.ReadinessState;
    import org.springframework.context.event.EventListener;
    import org.springframework.stereotype.Component;
    @Component
    public class MyReadinessStateExporter {
        @EventListener
        public void onStateChange(AvailabilityChangeEvent<ReadinessState> event) {
            switch (event.getState()) {
                case ACCEPTING_TRAFFIC:
                    // create file /tmp/healthy
                    break;
                case REFUSING_TRAFFIC:
                    // remove file /tmp/healthy
                    break;
    
    import org.springframework.boot.availability.AvailabilityChangeEvent
    import org.springframework.boot.availability.ReadinessState
    import org.springframework.context.event.EventListener
    import org.springframework.stereotype.Component
    @Component
    class MyReadinessStateExporter {
        @EventListener
        fun onStateChange(event: AvailabilityChangeEvent<ReadinessState?>) {
            when (event.state) {
                ReadinessState.ACCEPTING_TRAFFIC -> {
                    // create file /tmp/healthy
                ReadinessState.REFUSING_TRAFFIC -> {
                    // remove file /tmp/healthy
                else -> {
                    // ...
    

    We can also update the state of the application, when the application breaks and cannot recover:

    import org.springframework.boot.availability.AvailabilityChangeEvent;
    import org.springframework.boot.availability.LivenessState;
    import org.springframework.context.ApplicationEventPublisher;
    import org.springframework.stereotype.Component;
    @Component
    public class MyLocalCacheVerifier {
        private final ApplicationEventPublisher eventPublisher;
        public MyLocalCacheVerifier(ApplicationEventPublisher eventPublisher) {
            this.eventPublisher = eventPublisher;
        public void checkLocalCache() {
            try {
                // ...
            catch (CacheCompletelyBrokenException ex) {
                AvailabilityChangeEvent.publish(this.eventPublisher, ex, LivenessState.BROKEN);
    
    import org.springframework.boot.availability.AvailabilityChangeEvent
    import org.springframework.boot.availability.LivenessState
    import org.springframework.context.ApplicationEventPublisher
    import org.springframework.stereotype.Component
    @Component
    class MyLocalCacheVerifier(private val eventPublisher: ApplicationEventPublisher) {
        fun checkLocalCache() {
            try {
                // ...
            } catch (ex: CacheCompletelyBrokenException) {
                AvailabilityChangeEvent.publish(eventPublisher, ex, LivenessState.BROKEN)
    

    Spring Boot provides Kubernetes HTTP probes for "Liveness" and "Readiness" with Actuator Health Endpoints. You can get more guidance about deploying Spring Boot applications on Kubernetes in the dedicated section.

    Some events are actually triggered before the ApplicationContext is created, so you cannot register a listener on those as a @Bean. You can register them with the SpringApplication.addListeners(…​) method or the SpringApplicationBuilder.listeners(…​) method.

    If you want those listeners to be registered automatically, regardless of the way the application is created, you can add a META-INF/spring.factories file to your project and reference your listener(s) by using the org.springframework.context.ApplicationListener key, as shown in the following example:

    org.springframework.context.ApplicationListener=com.example.project.MyListener

    An ApplicationStartingEvent is sent at the start of a run but before any processing, except for the registration of listeners and initializers.

    An ApplicationEnvironmentPreparedEvent is sent when the Environment to be used in the context is known but before the context is created.

    An ApplicationContextInitializedEvent is sent when the ApplicationContext is prepared and ApplicationContextInitializers have been called but before any bean definitions are loaded.

    An ApplicationPreparedEvent is sent just before the refresh is started but after bean definitions have been loaded.

    An ApplicationStartedEvent is sent after the context has been refreshed but before any application and command-line runners have been called.

    An AvailabilityChangeEvent is sent right after with LivenessState.CORRECT to indicate that the application is considered as live.

    An ApplicationReadyEvent is sent after any application and command-line runners have been called.

    An AvailabilityChangeEvent is sent right after with ReadinessState.ACCEPTING_TRAFFIC to indicate that the application is ready to service requests.

    An ApplicationFailedEvent is sent if there is an exception on startup.

    The above list only includes SpringApplicationEvents that are tied to a SpringApplication. In addition to these, the following events are also published after ApplicationPreparedEvent and before ApplicationStartedEvent:

    A WebServerInitializedEvent is sent after the WebServer is ready. ServletWebServerInitializedEvent and ReactiveWebServerInitializedEvent are the servlet and reactive variants respectively.

    A ContextRefreshedEvent is sent when an ApplicationContext is refreshed.

    Event listeners should not run potentially lengthy tasks as they execute in the same thread by default. Consider using application and command-line runners instead.

    Application events are sent by using Spring Framework’s event publishing mechanism. Part of this mechanism ensures that an event published to the listeners in a child context is also published to the listeners in any ancestor contexts. As a result of this, if your application uses a hierarchy of SpringApplication instances, a listener may receive multiple instances of the same type of application event.

    To allow your listener to distinguish between an event for its context and an event for a descendant context, it should request that its application context is injected and then compare the injected context with the context of the event. The context can be injected by implementing ApplicationContextAware or, if the listener is a bean, by using @Autowired.

    1.8. Web Environment

    A SpringApplication attempts to create the right type of ApplicationContext on your behalf. The algorithm used to determine a WebApplicationType is the following:

    If Spring MVC is not present and Spring WebFlux is present, an AnnotationConfigReactiveWebServerApplicationContext is used

    Otherwise, AnnotationConfigApplicationContext is used

    This means that if you are using Spring MVC and the new WebClient from Spring WebFlux in the same application, Spring MVC will be used by default. You can override that easily by calling setWebApplicationType(WebApplicationType).

    It is also possible to take complete control of the ApplicationContext type that is used by calling setApplicationContextFactory(…​).

    1.9. Accessing Application Arguments

    If you need to access the application arguments that were passed to SpringApplication.run(…​), you can inject a org.springframework.boot.ApplicationArguments bean. The ApplicationArguments interface provides access to both the raw String[] arguments as well as parsed option and non-option arguments, as shown in the following example:

    import java.util.List;
    import org.springframework.boot.ApplicationArguments;
    import org.springframework.stereotype.Component;
    @Component
    public class MyBean {
        public MyBean(ApplicationArguments args) {
            boolean debug = args.containsOption("debug");
            List<String> files = args.getNonOptionArgs();
            if (debug) {
                System.out.println(files);
            // if run with "--debug logfile.txt" prints ["logfile.txt"]
    
    import org.springframework.boot.ApplicationArguments
    import org.springframework.stereotype.Component
    @Component
    class MyBean(args: ApplicationArguments) {
        init {
            val debug = args.containsOption("debug")
            val files = args.nonOptionArgs
            if (debug) {
                println(files)
            // if run with "--debug logfile.txt" prints ["logfile.txt"]
    

    1.10. Using the ApplicationRunner or CommandLineRunner

    If you need to run some specific code once the SpringApplication has started, you can implement the ApplicationRunner or CommandLineRunner interfaces. Both interfaces work in the same way and offer a single run method, which is called just before SpringApplication.run(…​) completes.

    The CommandLineRunner interfaces provides access to application arguments as a string array, whereas the ApplicationRunner uses the ApplicationArguments interface discussed earlier. The following example shows a CommandLineRunner with a run method:

    import org.springframework.boot.CommandLineRunner;
    import org.springframework.stereotype.Component;
    @Component
    public class MyCommandLineRunner implements CommandLineRunner {
        @Override
        public void run(String... args) {
            // Do something...
    
    import org.springframework.boot.CommandLineRunner
    import org.springframework.stereotype.Component
    @Component
    class MyCommandLineRunner : CommandLineRunner {
        override fun run(vararg args: String) {
            // Do something...
    

    1.11. Application Exit

    Each SpringApplication registers a shutdown hook with the JVM to ensure that the ApplicationContext closes gracefully on exit. All the standard Spring lifecycle callbacks (such as the DisposableBean interface or the @PreDestroy annotation) can be used.

    In addition, beans may implement the org.springframework.boot.ExitCodeGenerator interface if they wish to return a specific exit code when SpringApplication.exit() is called. This exit code can then be passed to System.exit() to return it as a status code, as shown in the following example:

    import org.springframework.boot.ExitCodeGenerator;
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.context.annotation.Bean;
    @SpringBootApplication
    public class MyApplication {
        @Bean
        public ExitCodeGenerator exitCodeGenerator() {
            return () -> 42;
        public static void main(String[] args) {
            System.exit(SpringApplication.exit(SpringApplication.run(MyApplication.class, args)));
    
    import org.springframework.boot.ExitCodeGenerator
    import org.springframework.boot.SpringApplication
    import org.springframework.boot.autoconfigure.SpringBootApplication
    import org.springframework.boot.runApplication
    import org.springframework.context.annotation.Bean
    import kotlin.system.exitProcess
    @SpringBootApplication
    class MyApplication {
        @Bean
        fun exitCodeGenerator() = ExitCodeGenerator { 42 }
    fun main(args: Array<String>) {
        exitProcess(SpringApplication.exit(
            runApplication<MyApplication>(*args)))
    

    Also, the ExitCodeGenerator interface may be implemented by exceptions. When such an exception is encountered, Spring Boot returns the exit code provided by the implemented getExitCode() method.

    If there is more than one ExitCodeGenerator, the first non-zero exit code that is generated is used. To control the order in which the generators are called, additionally implement the org.springframework.core.Ordered interface or use the org.springframework.core.annotation.Order annotation.

    1.12. Admin Features

    It is possible to enable admin-related features for the application by specifying the spring.application.admin.enabled property. This exposes the SpringApplicationAdminMXBean on the platform MBeanServer. You could use this feature to administer your Spring Boot application remotely. This feature could also be useful for any service wrapper implementation.

    1.13. Application Startup tracking

    During the application startup, the SpringApplication and the ApplicationContext perform many tasks related to the application lifecycle, the beans lifecycle or even processing application events. With ApplicationStartup, Spring Framework allows you to track the application startup sequence with StartupStep objects. This data can be collected for profiling purposes, or just to have a better understanding of an application startup process.

    You can choose an ApplicationStartup implementation when setting up the SpringApplication instance. For example, to use the BufferingApplicationStartup, you could write:

    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.boot.context.metrics.buffering.BufferingApplicationStartup;
    @SpringBootApplication
    public class MyApplication {
        public static void main(String[] args) {
            SpringApplication application = new SpringApplication(MyApplication.class);
            application.setApplicationStartup(new BufferingApplicationStartup(2048));
            application.run(args);
    
    import org.springframework.boot.autoconfigure.SpringBootApplication
    import org.springframework.boot.context.metrics.buffering.BufferingApplicationStartup
    import org.springframework.boot.runApplication
    @SpringBootApplication
    class MyApplication
    fun main(args: Array<String>) {
        runApplication<MyApplication>(*args) {
            applicationStartup = BufferingApplicationStartup(2048)
    

    The first available implementation, FlightRecorderApplicationStartup is provided by Spring Framework. It adds Spring-specific startup events to a Java Flight Recorder session and is meant for profiling applications and correlating their Spring context lifecycle with JVM events (such as allocations, GCs, class loading…​). Once configured, you can record data by running the application with the Flight Recorder enabled:

    $ java -XX:StartFlightRecording:filename=recording.jfr,duration=10s -jar demo.jar

    Spring Boot ships with the BufferingApplicationStartup variant; this implementation is meant for buffering the startup steps and draining them into an external metrics system. Applications can ask for the bean of type BufferingApplicationStartup in any component.

    Spring Boot can also be configured to expose a startup endpoint that provides this information as a JSON document.

    Spring Boot lets you externalize your configuration so that you can work with the same application code in different environments. You can use a variety of external configuration sources including Java properties files, YAML files, environment variables, and command-line arguments.

    Property values can be injected directly into your beans by using the @Value annotation, accessed through Spring’s Environment abstraction, or be bound to structured objects through @ConfigurationProperties.

    Spring Boot uses a very particular PropertySource order that is designed to allow sensible overriding of values. Later property sources can override the values defined in earlier ones. Sources are considered in the following order:

    @PropertySource annotations on your @Configuration classes. Please note that such property sources are not added to the Environment until the application context is being refreshed. This is too late to configure certain properties such as logging.* and spring.main.* which are read before refresh begins.

    Config data (such as application.properties files).

    A RandomValuePropertySource that has properties only in random.*.

    OS environment variables.

    Java System properties (System.getProperties()).

    JNDI attributes from java:comp/env.

    ServletContext init parameters.

    ServletConfig init parameters.

    Properties from SPRING_APPLICATION_JSON (inline JSON embedded in an environment variable or system property).

    Command line arguments.

    properties attribute on your tests. Available on @SpringBootTest and the test annotations for testing a particular slice of your application.

    @TestPropertySource annotations on your tests.

    Devtools global settings properties in the $HOME/.config/spring-boot directory when devtools is active.

    Application properties packaged inside your jar (application.properties and YAML variants).

    Profile-specific application properties packaged inside your jar (application-{profile}.properties and YAML variants).

    Application properties outside of your packaged jar (application.properties and YAML variants).

    Profile-specific application properties outside of your packaged jar (application-{profile}.properties and YAML variants).

    To provide a concrete example, suppose you develop a @Component that uses a name property, as shown in the following example:

    import org.springframework.beans.factory.annotation.Value;
    import org.springframework.stereotype.Component;
    @Component
    public class MyBean {
        @Value("${name}")
        private String name;
        // ...
    
    import org.springframework.beans.factory.annotation.Value
    import org.springframework.stereotype.Component
    @Component
    class MyBean {
        @Value("\${name}")
        private val name: String? = null
        // ...
    

    On your application classpath (for example, inside your jar) you can have an application.properties file that provides a sensible default property value for name. When running in a new environment, an application.properties file can be provided outside of your jar that overrides the name. For one-off testing, you can launch with a specific command line switch (for example, java -jar app.jar --name="Spring").

    The env and configprops endpoints can be useful in determining why a property has a particular value. You can use these two endpoints to diagnose unexpected property values. See the "Production ready features" section for details.

    2.1. Accessing Command Line Properties

    By default, SpringApplication converts any command line option arguments (that is, arguments starting with --, such as --server.port=9000) to a property and adds them to the Spring Environment. As mentioned previously, command line properties always take precedence over file-based property sources.

    If you do not want command line properties to be added to the Environment, you can disable them by using SpringApplication.setAddCommandLineProperties(false).

    2.2. JSON Application Properties

    Environment variables and system properties often have restrictions that mean some property names cannot be used. To help with this, Spring Boot allows you to encode a block of properties into a single JSON structure.

    When your application starts, any spring.application.json or SPRING_APPLICATION_JSON properties will be parsed and added to the Environment.

    For example, the SPRING_APPLICATION_JSON property can be supplied on the command line in a UN*X shell as an environment variable:

    $ SPRING_APPLICATION_JSON='{"my":{"name":"test"}}' java -jar myapp.jar

    In the preceding example, you end up with my.name=test in the Spring Environment.

    The same JSON can also be provided as a system property:

    $ java -Dspring.application.json='{"my":{"name":"test"}}' -jar myapp.jar

    Or you could supply the JSON by using a command line argument:

    $ java -jar myapp.jar --spring.application.json='{"my":{"name":"test"}}'

    If you are deploying to a classic Application Server, you could also use a JNDI variable named java:comp/env/spring.application.json.

    Although null values from the JSON will be added to the resulting property source, the PropertySourcesPropertyResolver treats null properties as missing values. This means that the JSON cannot override properties from lower order property sources with a null value.

    The list is ordered by precedence (with values from lower items overriding earlier ones). Documents from the loaded files are added as PropertySources to the Spring Environment.

    If you do not like application as the configuration file name, you can switch to another file name by specifying a spring.config.name environment property. For example, to look for myproject.properties and myproject.yaml files you can run your application as follows:

    $ java -jar myproject.jar --spring.config.name=myproject

    You can also refer to an explicit location by using the spring.config.location environment property. This property accepts a comma-separated list of one or more locations to check.

    The following example shows how to specify two distinct files:

    $ java -jar myproject.jar --spring.config.location=\
        optional:classpath:/default.properties,\
        optional:classpath:/override.properties
    spring.config.name, spring.config.location, and spring.config.additional-location are used very early to determine which files have to be loaded. They must be defined as an environment property (typically an OS environment variable, a system property, or a command-line argument).

    If spring.config.location contains directories (as opposed to files), they should end in /. At runtime they will be appended with the names generated from spring.config.name before being loaded. Files specified in spring.config.location are imported directly.

    Both directory and file location values are also expanded to check for
    profile-specific files. For example, if you have a spring.config.location of classpath:myconfig.properties, you will also find appropriate classpath:myconfig-<profile>.properties files are loaded.

    In most situations, each spring.config.location item you add will reference a single file or directory. Locations are processed in the order that they are defined and later ones can override the values of earlier ones.

    If you have a complex location setup, and you use profile-specific configuration files, you may need to provide further hints so that Spring Boot knows how they should be grouped. A location group is a collection of locations that are all considered at the same level. For example, you might want to group all classpath locations, then all external locations. Items within a location group should be separated with ;. See the example in the “Profile Specific Files” section for more details.

    Locations configured by using spring.config.location replace the default locations. For example, if spring.config.location is configured with the value optional:classpath:/custom-config/,optional:file:./custom-config/, the complete set of locations considered is:

    If you prefer to add additional locations, rather than replacing them, you can use spring.config.additional-location. Properties loaded from additional locations can override those in the default locations. For example, if spring.config.additional-location is configured with the value optional:classpath:/custom-config/,optional:file:./custom-config/, the complete set of locations considered is:

    This search ordering lets you specify default values in one configuration file and then selectively override those values in another. You can provide default values for your application in application.properties (or whatever other basename you choose with spring.config.name) in one of the default locations. These default values can then be overridden at runtime with a different file located in one of the custom locations.

    If you use environment variables rather than system properties, most operating systems disallow period-separated key names, but you can use underscores instead (for example, SPRING_CONFIG_NAME instead of spring.config.name). See Binding From Environment Variables for details.

    2.3.1. Optional Locations

    By default, when a specified config data location does not exist, Spring Boot will throw a ConfigDataLocationNotFoundException and your application will not start.

    If you want to specify a location, but you do not mind if it does not always exist, you can use the optional: prefix. You can use this prefix with the spring.config.location and spring.config.additional-location properties, as well as with spring.config.import declarations.

    For example, a spring.config.import value of optional:file:./myconfig.properties allows your application to start, even if the myconfig.properties file is missing.

    If you want to ignore all ConfigDataLocationNotFoundExceptions and always continue to start your application, you can use the spring.config.on-not-found property. Set the value to ignore using SpringApplication.setDefaultProperties(…​) or with a system/environment variable.

    2.3.2. Wildcard Locations

    If a config file location includes the * character for the last path segment, it is considered a wildcard location. Wildcards are expanded when the config is loaded so that immediate subdirectories are also checked. Wildcard locations are particularly useful in an environment such as Kubernetes when there are multiple sources of config properties.

    For example, if you have some Redis configuration and some MySQL configuration, you might want to keep those two pieces of configuration separate, while requiring that both those are present in an application.properties file. This might result in two separate application.properties files mounted at different locations such as /config/redis/application.properties and /config/mysql/application.properties. In such a case, having a wildcard location of config/*/, will result in both files being processed.

    By default, Spring Boot includes config/*/ in the default search locations. It means that all subdirectories of the /config directory outside of your jar will be searched.

    You can use wildcard locations yourself with the spring.config.location and spring.config.additional-location properties.

    A wildcard location must contain only one * and end with */ for search locations that are directories or */<filename> for search locations that are files. Locations with wildcards are sorted alphabetically based on the absolute path of the file names.

    2.3.3. Profile Specific Files

    As well as application property files, Spring Boot will also attempt to load profile-specific files using the naming convention application-{profile}. For example, if your application activates a profile named prod and uses YAML files, then both application.yml and application-prod.yml will be considered.

    Profile-specific properties are loaded from the same locations as standard application.properties, with profile-specific files always overriding the non-specific ones. If several profiles are specified, a last-wins strategy applies. For example, if profiles prod,live are specified by the spring.profiles.active property, values in application-prod.properties can be overridden by those in application-live.properties.

    The last-wins strategy applies at the location group level. A spring.config.location of classpath:/cfg/,classpath:/ext/ will not have the same override rules as classpath:/cfg/;classpath:/ext/.

    For example, continuing our prod,live example above, we might have the following files:

    application-live.properties application-live.properties application-prod.properties

    When we have a spring.config.location of classpath:/cfg/,classpath:/ext/ we process all /cfg files before all /ext files:

    The Environment has a set of default profiles (by default, [default]) that are used if no active profiles are set. In other words, if no profiles are explicitly activated, then properties from application-default are considered.

    2.3.4. Importing Additional Data

    Application properties may import further config data from other locations using the spring.config.import property. Imports are processed as they are discovered, and are treated as additional documents inserted immediately below the one that declares the import.

    For example, you might have the following in your classpath application.properties file:

    Properties
    spring.application.name=myapp
    spring.config.import=optional:file:./dev.properties
    spring:
      application:
        name: "myapp"
      config:
        import: "optional:file:./dev.properties"

    This will trigger the import of a dev.properties file in current directory (if such a file exists). Values from the imported dev.properties will take precedence over the file that triggered the import. In the above example, the dev.properties could redefine spring.application.name to a different value.

    An import will only be imported once no matter how many times it is declared. The order an import is defined inside a single document within the properties/yaml file does not matter. For instance, the two examples below produce the same result:

    Properties
    spring.config.import=my.properties
    my.property=value
    spring:
      config:
        import: "my.properties"
      property: "value"
    Properties
    my.property=value
    spring.config.import=my.properties
    property: "value" spring: config: import: "my.properties"

    In both of the above examples, the values from the my.properties file will take precedence over the file that triggered its import.

    Several locations can be specified under a single spring.config.import key. Locations will be processed in the order that they are defined, with later imports taking precedence.

    Spring Boot includes pluggable API that allows various different location addresses to be supported. By default you can import Java Properties, YAML and “configuration trees”.

    Third-party jars can offer support for additional technologies (there is no requirement for files to be local). For example, you can imagine config data being from external stores such as Consul, Apache ZooKeeper or Netflix Archaius.

    If you want to support your own locations, see the ConfigDataLocationResolver and ConfigDataLoader classes in the org.springframework.boot.context.config package.

    2.3.5. Importing Extensionless Files

    Some cloud platforms cannot add a file extension to volume mounted files. To import these extensionless files, you need to give Spring Boot a hint so that it knows how to load them. You can do this by putting an extension hint in square brackets.

    For example, suppose you have a /etc/config/myconfig file that you wish to import as yaml. You can import it from your application.properties using the following:

    Properties
    spring.config.import=file:/etc/config/myconfig[.yaml]
    spring:
      config:
        import: "file:/etc/config/myconfig[.yaml]"

    2.3.6. Using Configuration Trees

    When running applications on a cloud platform (such as Kubernetes) you often need to read config values that the platform supplies. It is not uncommon to use environment variables for such purposes, but this can have drawbacks, especially if the value is supposed to be kept secret.

    As an alternative to environment variables, many cloud platforms now allow you to map configuration into mounted data volumes. For example, Kubernetes can volume mount both ConfigMaps and Secrets.

    There are two common volume mount patterns that can be used:

    For the first case, you can import the YAML or Properties file directly using spring.config.import as described above. For the second case, you need to use the configtree: prefix so that Spring Boot knows it needs to expose all the files as properties.

    As an example, let’s imagine that Kubernetes has mounted the following volume:

    config/ myapp/ username password

    The contents of the username file would be a config value, and the contents of password would be a secret.

    To import these properties, you can add the following to your application.properties or application.yaml file:

    Properties
    spring.config.import=optional:configtree:/etc/config/
    spring:
      config:
        import: "optional:configtree:/etc/config/"

    You can then access or inject myapp.username and myapp.password properties from the Environment in the usual way.

    If you have multiple config trees to import from the same parent folder you can use a wildcard shortcut. Any configtree: location that ends with /*/ will import all immediate children as config trees.

    For example, given the following volume:

    config/ dbconfig/ username password mqconfig/ username password

    You can use configtree:/etc/config/*/ as the import location:

    Properties
    spring.config.import=optional:configtree:/etc/config/*/
    spring:
      config:
        import: "optional:configtree:/etc/config/*/"

    This will add db.username, db.password, mq.username and mq.password properties.

    Configuration trees can also be used for Docker secrets. When a Docker swarm service is granted access to a secret, the secret gets mounted into the container. For example, if a secret named db.password is mounted at location /run/secrets/, you can make db.password available to the Spring environment using the following:

    Properties
    spring.config.import=optional:configtree:/run/secrets/
    spring:
      config:
        import: "optional:configtree:/run/secrets/"

    2.3.7. Property Placeholders

    The values in application.properties and application.yml are filtered through the existing Environment when they are used, so you can refer back to previously defined values (for example, from System properties or environment variables). The standard ${name} property-placeholder syntax can be used anywhere within a value. Property placeholders can also specify a default value using a : to separate the default value from the property name, for example ${name:default}.

    The use of placeholders with and without defaults is shown in the following example:

    Properties
    app.name=MyApp
    app.description=${app.name} is a Spring Boot application written by ${username:Unknown}
    name: "MyApp" description: "${app.name} is a Spring Boot application written by ${username:Unknown}"

    Assuming that the username property has not been set elsewhere, app.description will have the value MyApp is a Spring Boot application written by Unknown.

    You should always refer to property names in the placeholder using their canonical form (kebab-case using only lowercase letters). This will allow Spring Boot to use the same logic as it does when relaxed binding @ConfigurationProperties.

    For example, ${demo.item-price} will pick up demo.item-price and demo.itemPrice forms from the application.properties file, as well as DEMO_ITEMPRICE from the system environment. If you used ${demo.itemPrice} instead, demo.item-price and DEMO_ITEMPRICE would not be considered.

    You can also use this technique to create “short” variants of existing Spring Boot properties. See the howto.html how-to for details.

    2.3.8. Working With Multi-Document Files

    Spring Boot allows you to split a single physical file into multiple logical documents which are each added independently. Documents are processed in order, from top to bottom. Later documents can override the properties defined in earlier ones.

    For application.yml files, the standard YAML multi-document syntax is used. Three consecutive hyphens represent the end of one document, and the start of the next.

    For example, the following file has two logical documents:

    spring:
      application:
        name: "MyApp"
    spring:
      application:
        name: "MyCloudApp"
      config:
        activate:
          on-cloud-platform: "kubernetes"

    For application.properties files a special #--- or !--- comment is used to mark the document splits:

    spring.application.name=MyApp
    spring.application.name=MyCloudApp
    spring.config.activate.on-cloud-platform=kubernetes
    Property file separators must not have any leading whitespace and must have exactly three hyphen characters. The lines immediately before and after the separator must not be same comment prefix. Multi-document property files are often used in conjunction with activation properties such as spring.config.activate.on-profile. See the
    next section for details.

    2.3.9. Activation Properties

    It is sometimes useful to only activate a given set of properties when certain conditions are met. For example, you might have properties that are only relevant when a specific profile is active.

    You can conditionally activate a properties document using spring.config.activate.*.

    The following activation properties are available:

    Table 2. activation properties

    For example, the following specifies that the second document is only active when running on Kubernetes, and only when either the “prod” or “staging” profiles are active:

    Properties
    myprop=always-set
    spring.config.activate.on-cloud-platform=kubernetes
    spring.config.activate.on-profile=prod | staging
    myotherprop=sometimes-set
    myprop:
      "always-set"
    spring:
      config:
        activate:
          on-cloud-platform: "kubernetes"
          on-profile: "prod | staging"
    myotherprop: "sometimes-set"

    2.4. Encrypting Properties

    Spring Boot does not provide any built-in support for encrypting property values, however, it does provide the hook points necessary to modify values contained in the Spring Environment. The EnvironmentPostProcessor interface allows you to manipulate the Environment before the application starts. See howto.html for details.

    If you need a secure way to store credentials and passwords, the Spring Cloud Vault project provides support for storing externalized configuration in HashiCorp Vault.

    2.5. Working With YAML

    YAML is a superset of JSON and, as such, is a convenient format for specifying hierarchical configuration data. The SpringApplication class automatically supports YAML as an alternative to properties whenever you have the SnakeYAML library on your classpath.

    2.5.1. Mapping YAML to Properties

    YAML documents need to be converted from their hierarchical format to a flat structure that can be used with the Spring Environment. For example, consider the following YAML document:

    environments:
        url: "https://dev.example.com"
        name: "Developer Setup"
      prod:
        url: "https://another.example.com"
        name: "My Cool App"

    In order to access these properties from the Environment, they would be flattened as follows:

    environments.dev.url=https://dev.example.com
    environments.dev.name=Developer Setup
    environments.prod.url=https://another.example.com
    environments.prod.name=My Cool App

    Likewise, YAML lists also need to be flattened. They are represented as property keys with [index] dereferencers. For example, consider the following YAML:

    servers: - "dev.example.com" - "another.example.com"

    The preceding example would be transformed into these properties:

    my.servers[0]=dev.example.com
    my.servers[1]=another.example.com
    Properties that use the [index] notation can be bound to Java List or Set objects using Spring Boot’s Binder class. For more details see the “
    Type-safe Configuration Properties” section below. YAML files cannot be loaded by using the @PropertySource or @TestPropertySource annotations. So, in the case that you need to load values that way, you need to use a properties file.

    2.5.2. Directly Loading YAML

    Spring Framework provides two convenient classes that can be used to load YAML documents. The YamlPropertiesFactoryBean loads YAML as Properties and the YamlMapFactoryBean loads YAML as a Map.

    You can also use the YamlPropertySourceLoader class if you want to load YAML as a Spring PropertySource.

    2.6. Configuring Random Values

    The RandomValuePropertySource is useful for injecting random values (for example, into secrets or test cases). It can produce integers, longs, uuids, or strings, as shown in the following example:

    Properties
    my.secret=${random.value}
    my.number=${random.int}
    my.bignumber=${random.long}
    my.uuid=${random.uuid}
    my.number-less-than-ten=${random.int(10)}
    my.number-in-range=${random.int[1024,65536]}
    secret: "${random.value}" number: "${random.int}" bignumber: "${random.long}" uuid: "${random.uuid}" number-less-than-ten: "${random.int(10)}" number-in-range: "${random.int[1024,65536]}"

    The random.int* syntax is OPEN value (,max) CLOSE where the OPEN,CLOSE are any character and value,max are integers. If max is provided, then value is the minimum value and max is the maximum value (exclusive).

    2.7. Configuring System Environment Properties

    Spring Boot supports setting a prefix for environment properties. This is useful if the system environment is shared by multiple Spring Boot applications with different configuration requirements. The prefix for system environment properties can be set directly on SpringApplication.

    For example, if you set the prefix to input, a property such as remote.timeout will also be resolved as input.remote.timeout in the system environment.

    2.8. Type-safe Configuration Properties

    Using the @Value("${property}") annotation to inject configuration properties can sometimes be cumbersome, especially if you are working with multiple properties or your data is hierarchical in nature. Spring Boot provides an alternative method of working with properties that lets strongly typed beans govern and validate the configuration of your application.

    2.8.1. JavaBean Properties Binding

    It is possible to bind a bean declaring standard JavaBean properties as shown in the following example:

    import java.net.InetAddress;
    import java.util.ArrayList;
    import java.util.Collections;
    import java.util.List;
    import org.springframework.boot.context.properties.ConfigurationProperties;
    @ConfigurationProperties("my.service")
    public class MyProperties {
        private boolean enabled;
        private InetAddress remoteAddress;
        private final Security security = new Security();
        // getters / setters...
        public boolean isEnabled() {
            return this.enabled;
        public void setEnabled(boolean enabled) {
            this.enabled = enabled;
        public InetAddress getRemoteAddress() {
            return this.remoteAddress;
        public void setRemoteAddress(InetAddress remoteAddress) {
            this.remoteAddress = remoteAddress;
        public Security getSecurity() {
            return this.security;
        public static class Security {
            private String username;
            private String password;
            private List<String> roles = new ArrayList<>(Collections.singleton("USER"));
            // getters / setters...
            public String getUsername() {
                return this.username;
            public void setUsername(String username) {
                this.username = username;
            public String getPassword() {
                return this.password;
            public void setPassword(String password) {
                this.password = password;
            public List<String> getRoles() {
                return this.roles;
            public void setRoles(List<String> roles) {
                this.roles = roles;
    
    import org.springframework.boot.context.properties.ConfigurationProperties
    import java.net.InetAddress
    @ConfigurationProperties("my.service")
    class MyProperties {
        var isEnabled = false
        var remoteAddress: InetAddress? = null
        val security = Security()
        class Security {
            var username: String? = null
            var password: String? = null
            var roles: List<String> = ArrayList(setOf("USER"))
    

    my.service.security.username, with a nested "security" object whose name is determined by the name of the property. In particular, the type is not used at all there and could have been SecurityProperties.

    my.service.security.password.

    my.service.security.roles, with a collection of String that defaults to USER.

    Such arrangement relies on a default empty constructor and getters and setters are usually mandatory, since binding is through standard Java Beans property descriptors, just like in Spring MVC. A setter may be omitted in the following cases:

    Maps, as long as they are initialized, need a getter but not necessarily a setter, since they can be mutated by the binder.

    Collections and arrays can be accessed either through an index (typically with YAML) or by using a single comma-separated value (properties). In the latter case, a setter is mandatory. We recommend to always add a setter for such types. If you initialize a collection, make sure it is not immutable (as in the preceding example).

    If nested POJO properties are initialized (like the Security field in the preceding example), a setter is not required. If you want the binder to create the instance on the fly by using its default constructor, you need a setter.

    Some people use Project Lombok to add getters and setters automatically. Make sure that Lombok does not generate any particular constructor for such a type, as it is used automatically by the container to instantiate the object.

    Finally, only standard Java Bean properties are considered and binding on static properties is not supported.

    2.8.2. Constructor Binding

    The example in the previous section can be rewritten in an immutable fashion as shown in the following example:

    import java.net.InetAddress;
    import java.util.List;
    import org.springframework.boot.context.properties.ConfigurationProperties;
    import org.springframework.boot.context.properties.bind.DefaultValue;
    @ConfigurationProperties("my.service")
    public class MyProperties {
        // fields...
        private final boolean enabled;
        private final InetAddress remoteAddress;
        private final Security security;
        public MyProperties(boolean enabled, InetAddress remoteAddress, Security security) {
            this.enabled = enabled;
            this.remoteAddress = remoteAddress;
            this.security = security;
        // getters...
        public boolean isEnabled() {
            return this.enabled;
        public InetAddress getRemoteAddress() {
            return this.remoteAddress;
        public Security getSecurity() {
            return this.security;
        public static class Security {
            // fields...
            private final String username;
            private final String password;
            private final List<String> roles;
            public Security(String username, String password, @DefaultValue("USER") List<String> roles) {
                this.username = username;
                this.password = password;
                this.roles = roles;
            // getters...
            public String getUsername() {
                return this.username;
            public String getPassword() {
                return this.password;
            public List<String> getRoles() {
                return this.roles;
    
    import org.springframework.boot.context.properties.ConfigurationProperties
    import org.springframework.boot.context.properties.bind.DefaultValue
    import java.net.InetAddress
    @ConfigurationProperties("my.service")
    class MyProperties(val enabled: Boolean, val remoteAddress: InetAddress,
            val security: Security) {
        class Security(val username: String, val password: String,
                @param:DefaultValue("USER") val roles: List<String>)
    

    In this setup, the presence of a single parameterized constructor implies that constructor binding should be used. This means that the binder will find a constructor with the parameters that you wish to have bound. If your class has multiple constructors, the @ConstructorBinding annotation can be used to specify which constructor to use for constructor binding. To opt out of constructor binding for a class with a single parameterized constructor, the constructor must be annotated with @Autowired. Constructor binding can be used with records. Unless your record has multiple constructors, there is no need to use @ConstructorBinding.

    Nested members of a constructor bound class (such as Security in the example above) will also be bound through their constructor.

    Default values can be specified using @DefaultValue on constructor parameters and record components. The conversion service will be applied to coerce the annotation’s String value to the target type of a missing property.

    Referring to the previous example, if no properties are bound to Security, the MyProperties instance will contain a null value for security. To make it contain a non-null instance of Security even when no properties are bound to it (when using Kotlin, this will require the username and password parameters of Security to be declared as nullable as they do not have default values), use an empty @DefaultValue annotation:

    public MyProperties(boolean enabled, InetAddress remoteAddress, @DefaultValue Security security) {
        this.enabled = enabled;
        this.remoteAddress = remoteAddress;
        this.security = security;
    
    class MyProperties(val enabled: Boolean, val remoteAddress: InetAddress,
            @DefaultValue val security: Security) {
        class Security(val username: String?, val password: String?,
                @param:DefaultValue("USER") val roles: List<String>)
    To use constructor binding the class must be enabled using @EnableConfigurationProperties or configuration property scanning.
    You cannot use constructor binding with beans that are created by the regular Spring mechanisms (for example @Component beans, beans created by using @Bean methods or beans loaded by using @Import)
    To use constructor binding in a native image the class must be compiled with -parameters.
    This will happen automatically if you use Spring Boot’s Gradle plugin or if you use Maven and spring-boot-starter-parent.
    The use of java.util.Optional with @ConfigurationProperties is not recommended as it is primarily intended for use as a return type.
    As such, it is not well-suited to configuration property injection.
    For consistency with properties of other types, if you do declare an Optional property and it has no value, null rather than an empty Optional will be bound.
    

    2.8.3. Enabling @ConfigurationProperties-annotated Types

    Spring Boot provides infrastructure to bind @ConfigurationProperties types and register them as beans. You can either enable configuration properties on a class-by-class basis or enable configuration property scanning that works in a similar manner to component scanning.

    Sometimes, classes annotated with @ConfigurationProperties might not be suitable for scanning, for example, if you’re developing your own auto-configuration or you want to enable them conditionally. In these cases, specify the list of types to process using the @EnableConfigurationProperties annotation. This can be done on any @Configuration class, as shown in the following example:

    import org.springframework.boot.context.properties.EnableConfigurationProperties;
    import org.springframework.context.annotation.Configuration;
    @Configuration(proxyBeanMethods = false)
    @EnableConfigurationProperties(SomeProperties.class)
    public class MyConfiguration {
    
    import org.springframework.boot.context.properties.EnableConfigurationProperties
    import org.springframework.context.annotation.Configuration
    @Configuration(proxyBeanMethods = false)
    @EnableConfigurationProperties(SomeProperties::class)
    class MyConfiguration
    
    import org.springframework.boot.context.properties.ConfigurationProperties;
    @ConfigurationProperties("some.properties")
    public class SomeProperties {
    
    import org.springframework.boot.context.properties.ConfigurationProperties
    @ConfigurationProperties("some.properties")
    class SomeProperties
    

    To use configuration property scanning, add the @ConfigurationPropertiesScan annotation to your application. Typically, it is added to the main application class that is annotated with @SpringBootApplication but it can be added to any @Configuration class. By default, scanning will occur from the package of the class that declares the annotation. If you want to define specific packages to scan, you can do so as shown in the following example:

    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.boot.context.properties.ConfigurationPropertiesScan;
    @SpringBootApplication
    @ConfigurationPropertiesScan({ "com.example.app", "com.example.another" })
    public class MyApplication {
    
    import org.springframework.boot.autoconfigure.SpringBootApplication
    import org.springframework.boot.context.properties.ConfigurationPropertiesScan
    @SpringBootApplication
    @ConfigurationPropertiesScan("com.example.app", "com.example.another")
    class MyApplication
    

    When the @ConfigurationProperties bean is registered using configuration property scanning or through @EnableConfigurationProperties, the bean has a conventional name: <prefix>-<fqn>, where <prefix> is the environment key prefix specified in the @ConfigurationProperties annotation and <fqn> is the fully qualified name of the bean. If the annotation does not provide any prefix, only the fully qualified name of the bean is used.

    Assuming that it is in the com.example.app package, the bean name of the SomeProperties example above is some.properties-com.example.app.SomeProperties.

    We recommend that @ConfigurationProperties only deal with the environment and, in particular, does not inject other beans from the context. For corner cases, setter injection can be used or any of the *Aware interfaces provided by the framework (such as EnvironmentAware if you need access to the Environment). If you still want to inject other beans using the constructor, the configuration properties bean must be annotated with @Component and use JavaBean-based property binding.

    2.8.4. Using @ConfigurationProperties-annotated Types

    This style of configuration works particularly well with the SpringApplication external YAML configuration, as shown in the following example:

    service: remote-address: 192.168.1.1 security: username: "admin" roles: - "USER" - "ADMIN"

    To work with @ConfigurationProperties beans, you can inject them in the same way as any other bean, as shown in the following example:

    import org.springframework.stereotype.Service;
    @Service
    public class MyService {
        private final MyProperties properties;
        public MyService(MyProperties properties) {
            this.properties = properties;
        public void openConnection() {
            Server server = new Server(this.properties.getRemoteAddress());
            server.start();
            // ...
        // ...
    Using @ConfigurationProperties also lets you generate metadata files that can be used by IDEs to offer auto-completion for your own keys.
    See the appendix for details.
    

    2.8.5. Third-party Configuration

    As well as using @ConfigurationProperties to annotate a class, you can also use it on public @Bean methods. Doing so can be particularly useful when you want to bind properties to third-party components that are outside of your control.

    To configure a bean from the Environment properties, add @ConfigurationProperties to its bean registration, as shown in the following example:

    import org.springframework.boot.context.properties.ConfigurationProperties;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    @Configuration(proxyBeanMethods = false)
    public class ThirdPartyConfiguration {
        @Bean
        @ConfigurationProperties(prefix = "another")
        public AnotherComponent anotherComponent() {
            return new AnotherComponent();
    
    import org.springframework.boot.context.properties.ConfigurationProperties
    import org.springframework.context.annotation.Bean
    import org.springframework.context.annotation.Configuration
    @Configuration(proxyBeanMethods = false)
    class ThirdPartyConfiguration {
        @Bean
        @ConfigurationProperties(prefix = "another")
        fun anotherComponent(): AnotherComponent = AnotherComponent()
    

    2.8.6. Relaxed Binding

    Spring Boot uses some relaxed rules for binding Environment properties to @ConfigurationProperties beans, so there does not need to be an exact match between the Environment property name and the bean property name. Common examples where this is useful include dash-separated environment properties (for example, context-path binds to contextPath), and capitalized environment properties (for example, PORT binds to port).

    As an example, consider the following @ConfigurationProperties class:

    import org.springframework.boot.context.properties.ConfigurationProperties;
    @ConfigurationProperties(prefix = "my.main-project.person")
    public class MyPersonProperties {
        private String firstName;
        public String getFirstName() {
            return this.firstName;
        public void setFirstName(String firstName) {
            this.firstName = firstName;
    
    import org.springframework.boot.context.properties.ConfigurationProperties
    @ConfigurationProperties(prefix = "my.main-project.person")
    class MyPersonProperties {
        var firstName: String? = null
    

    my.main-project.person.first-name

    Kebab case, which is recommended for use in .properties and .yml files.

    my.main-project.person.firstName

    Standard camel case syntax.

    my.main-project.person.first_name

    Underscore notation, which is an alternative format for use in .properties and .yml files.

    MY_MAINPROJECT_PERSON_FIRSTNAME

    Upper case format, which is recommended when using system environment variables.

    Properties Files

    Camel case, kebab case, or underscore notation

    Standard list syntax using [ ] or comma-separated values

    YAML Files

    Camel case, kebab case, or underscore notation

    Standard YAML list syntax or comma-separated values

    Environment Variables

    Upper case format with underscore as the delimiter (see Binding From Environment Variables).

    Numeric values surrounded by underscores (see Binding From Environment Variables)

    System properties

    Camel case, kebab case, or underscore notation

    Standard list syntax using [ ] or comma-separated values

    Binding Maps

    When binding to Map properties you may need to use a special bracket notation so that the original key value is preserved. If the key is not surrounded by [], any characters that are not alpha-numeric, - or . are removed.

    For example, consider binding the following properties to a Map<String,String>:

    Properties
    my.map.[/key1]=value1
    my.map.[/key2]=value2
    my.map./key3=value3
    "[/key1]": "value1" "[/key2]": "value2" "/key3": "value3"

    The properties above will bind to a Map with /key1, /key2 and key3 as the keys in the map. The slash has been removed from key3 because it was not surrounded by square brackets.

    When binding to scalar values, keys with . in them do not need to be surrounded by []. Scalar values include enums and all types in the java.lang package except for Object. Binding a.b=c to Map<String, String> will preserve the . in the key and return a Map with the entry {"a.b"="c"}. For any other types you need to use the bracket notation if your key contains a .. For example, binding a.b=c to Map<String, Object> will return a Map with the entry {"a"={"b"="c"}} whereas [a.b]=c will return a Map with the entry {"a.b"="c"}.

    Binding From Environment Variables

    Most operating systems impose strict rules around the names that can be used for environment variables. For example, Linux shell variables can contain only letters (a to z or A to Z), numbers (0 to 9) or the underscore character (_). By convention, Unix shell variables will also have their names in UPPERCASE.

    Spring Boot’s relaxed binding rules are, as much as possible, designed to be compatible with these naming restrictions.

    To convert a property name in the canonical-form to an environment variable name you can follow these rules:

    For example, the configuration property spring.main.log-startup-info would be an environment variable named SPRING_MAIN_LOGSTARTUPINFO.

    Environment variables can also be used when binding to object lists. To bind to a List, the element number should be surrounded with underscores in the variable name.

    For example, the configuration property my.service[0].other would use an environment variable named MY_SERVICE_0_OTHER.

    2.8.7. Merging Complex Types

    When lists are configured in more than one place, overriding works by replacing the entire list.

    For example, assume a MyPojo object with name and description attributes that are null by default. The following example exposes a list of MyPojo objects from MyProperties:

    import java.util.ArrayList;
    import java.util.List;
    import org.springframework.boot.context.properties.ConfigurationProperties;
    @ConfigurationProperties("my")
    public class MyProperties {
        private final List<MyPojo> list = new ArrayList<>();
        public List<MyPojo> getList() {
            return this.list;
    
    import org.springframework.boot.context.properties.ConfigurationProperties
    @ConfigurationProperties("my")
    class MyProperties {
        val list: List<MyPojo> = ArrayList()
    

    If the dev profile is not active, MyProperties.list contains one MyPojo entry, as previously defined. If the dev profile is enabled, however, the list still contains only one entry (with a name of my another name and a description of null). This configuration does not add a second MyPojo instance to the list, and it does not merge the items.

    When a List is specified in multiple profiles, the one with the highest priority (and only that one) is used. Consider the following example:

    Properties
    my.list[0].name=my name
    my.list[0].description=my description
    my.list[1].name=another name
    my.list[1].description=another description
    spring.config.activate.on-profile=dev
    my.list[0].name=my another name
    list: - name: "my name" description: "my description" - name: "another name" description: "another description" spring: config: activate: on-profile: "dev" list: - name: "my another name"

    In the preceding example, if the dev profile is active, MyProperties.list contains one MyPojo entry (with a name of my another name and a description of null). For YAML, both comma-separated lists and YAML lists can be used for completely overriding the contents of the list.

    For Map properties, you can bind with property values drawn from multiple sources. However, for the same property in multiple sources, the one with the highest priority is used. The following example exposes a Map<String, MyPojo> from MyProperties:

    import java.util.LinkedHashMap;
    import java.util.Map;
    import org.springframework.boot.context.properties.ConfigurationProperties;
    @ConfigurationProperties("my")
    public class MyProperties {
        private final Map<String, MyPojo> map = new LinkedHashMap<>();
        public Map<String, MyPojo> getMap() {
            return this.map;
    
    import org.springframework.boot.context.properties.ConfigurationProperties
    @ConfigurationProperties("my")
    class MyProperties {
        val map: Map<String, MyPojo> = LinkedHashMap()
    spring.config.activate.on-profile=dev
    my.map.key1.name=dev name 1
    my.map.key2.name=dev name 2
    my.map.key2.description=dev description 2
    key1: name: "my name 1" description: "my description 1" spring: config: activate: on-profile: "dev" key1: name: "dev name 1" key2: name: "dev name 2" description: "dev description 2"

    If the dev profile is not active, MyProperties.map contains one entry with key key1 (with a name of my name 1 and a description of my description 1). If the dev profile is enabled, however, map contains two entries with keys key1 (with a name of dev name 1 and a description of my description 1) and key2 (with a name of dev name 2 and a description of dev description 2).

    2.8.8. Properties Conversion

    Spring Boot attempts to coerce the external application properties to the right type when it binds to the @ConfigurationProperties beans. If you need custom type conversion, you can provide a ConversionService bean (with a bean named conversionService) or custom property editors (through a CustomEditorConfigurer bean) or custom Converters (with bean definitions annotated as @ConfigurationPropertiesBinding).

    As this bean is requested very early during the application lifecycle, make sure to limit the dependencies that your ConversionService is using. Typically, any dependency that you require may not be fully initialized at creation time. You may want to rename your custom ConversionService if it is not required for configuration keys coercion and only rely on custom converters qualified with @ConfigurationPropertiesBinding.

    A regular long representation (using milliseconds as the default unit unless a @DurationUnit has been specified)

    The standard ISO-8601 format used by java.time.Duration

    A more readable format where the value and the unit are coupled (10s means 10 seconds)

    import java.time.temporal.ChronoUnit; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.boot.convert.DurationUnit; @ConfigurationProperties("my") public class MyProperties { @DurationUnit(ChronoUnit.SECONDS) private Duration sessionTimeout = Duration.ofSeconds(30); private Duration readTimeout = Duration.ofMillis(1000); // getters / setters... public Duration getSessionTimeout() { return this.sessionTimeout; public void setSessionTimeout(Duration sessionTimeout) { this.sessionTimeout = sessionTimeout; public Duration getReadTimeout() { return this.readTimeout; public void setReadTimeout(Duration readTimeout) { this.readTimeout = readTimeout;
    import org.springframework.boot.context.properties.ConfigurationProperties
    import org.springframework.boot.convert.DurationUnit
    import java.time.Duration
    import java.time.temporal.ChronoUnit
    @ConfigurationProperties("my")
    class MyProperties {
        @DurationUnit(ChronoUnit.SECONDS)
        var sessionTimeout = Duration.ofSeconds(30)
        var readTimeout = Duration.ofMillis(1000)
    

    To specify a session timeout of 30 seconds, 30, PT30S and 30s are all equivalent. A read timeout of 500ms can be specified in any of the following form: 500, PT0.5S and 500ms.

    You can also use any of the supported units. These are:

    The default unit is milliseconds and can be overridden using @DurationUnit as illustrated in the sample above.

    If you prefer to use constructor binding, the same properties can be exposed, as shown in the following example:

    import java.time.Duration;
    import java.time.temporal.ChronoUnit;
    import org.springframework.boot.context.properties.ConfigurationProperties;
    import org.springframework.boot.context.properties.bind.DefaultValue;
    import org.springframework.boot.convert.DurationUnit;
    @ConfigurationProperties("my")
    public class MyProperties {
        // fields...
        private final Duration sessionTimeout;
        private final Duration readTimeout;
        public MyProperties(@DurationUnit(ChronoUnit.SECONDS) @DefaultValue("30s") Duration sessionTimeout,
                @DefaultValue("1000ms") Duration readTimeout) {
            this.sessionTimeout = sessionTimeout;
            this.readTimeout = readTimeout;
        // getters...
        public Duration getSessionTimeout() {
            return this.sessionTimeout;
        public Duration getReadTimeout() {
            return this.readTimeout;
    
    import org.springframework.boot.context.properties.ConfigurationProperties
    import org.springframework.boot.context.properties.bind.DefaultValue
    import org.springframework.boot.convert.DurationUnit
    import java.time.Duration
    import java.time.temporal.ChronoUnit
    @ConfigurationProperties("my")
    class MyProperties(@param:DurationUnit(ChronoUnit.SECONDS) @param:DefaultValue("30s") val sessionTimeout: Duration,
            @param:DefaultValue("1000ms") val readTimeout: Duration)
    If you are upgrading a Long property, make sure to define the unit (using @DurationUnit) if it is not milliseconds.
    Doing so gives a transparent upgrade path while supporting a much richer format.
    
    Converting Periods

    In addition to durations, Spring Boot can also work with java.time.Period type. The following formats can be used in application properties:

    An regular int representation (using days as the default unit unless a @PeriodUnit has been specified)

    The standard ISO-8601 format used by java.time.Period

    A simpler format where the value and the unit pairs are coupled (1y3d means 1 year and 3 days)

    Converting Data Sizes

    Spring Framework has a DataSize value type that expresses a size in bytes. If you expose a DataSize property, the following formats in application properties are available:

    A regular long representation (using bytes as the default unit unless a @DataSizeUnit has been specified)

    A more readable format where the value and the unit are coupled (10MB means 10 megabytes)

    import org.springframework.boot.context.properties.ConfigurationProperties;
    import org.springframework.boot.convert.DataSizeUnit;
    import org.springframework.util.unit.DataSize;
    import org.springframework.util.unit.DataUnit;
    @ConfigurationProperties("my")
    public class MyProperties {
        @DataSizeUnit(DataUnit.MEGABYTES)
        private DataSize bufferSize = DataSize.ofMegabytes(2);
        private DataSize sizeThreshold = DataSize.ofBytes(512);
        // getters/setters...
        public DataSize getBufferSize() {
            return this.bufferSize;
        public void setBufferSize(DataSize bufferSize) {
            this.bufferSize = bufferSize;
        public DataSize getSizeThreshold() {
            return this.sizeThreshold;
        public void setSizeThreshold(DataSize sizeThreshold) {
            this.sizeThreshold = sizeThreshold;
    
    import org.springframework.boot.context.properties.ConfigurationProperties
    import org.springframework.boot.convert.DataSizeUnit
    import org.springframework.util.unit.DataSize
    import org.springframework.util.unit.DataUnit
    @ConfigurationProperties("my")
    class MyProperties {
        @DataSizeUnit(DataUnit.MEGABYTES)
        var bufferSize = DataSize.ofMegabytes(2)
        var sizeThreshold = DataSize.ofBytes(512)
    

    To specify a buffer size of 10 megabytes, 10 and 10MB are equivalent. A size threshold of 256 bytes can be specified as 256 or 256B.

    You can also use any of the supported units. These are:

    The default unit is bytes and can be overridden using @DataSizeUnit as illustrated in the sample above.

    If you prefer to use constructor binding, the same properties can be exposed, as shown in the following example:

    import org.springframework.boot.context.properties.ConfigurationProperties;
    import org.springframework.boot.context.properties.bind.DefaultValue;
    import org.springframework.boot.convert.DataSizeUnit;
    import org.springframework.util.unit.DataSize;
    import org.springframework.util.unit.DataUnit;
    @ConfigurationProperties("my")
    public class MyProperties {
        // fields...
        private final DataSize bufferSize;
        private final DataSize sizeThreshold;
        public MyProperties(@DataSizeUnit(DataUnit.MEGABYTES) @DefaultValue("2MB") DataSize bufferSize,
                @DefaultValue("512B") DataSize sizeThreshold) {
            this.bufferSize = bufferSize;
            this.sizeThreshold = sizeThreshold;
        // getters...
        public DataSize getBufferSize() {
            return this.bufferSize;
        public DataSize getSizeThreshold() {
            return this.sizeThreshold;
    
    import org.springframework.boot.context.properties.ConfigurationProperties
    import org.springframework.boot.context.properties.bind.DefaultValue
    import org.springframework.boot.convert.DataSizeUnit
    import org.springframework.util.unit.DataSize
    import org.springframework.util.unit.DataUnit
    @ConfigurationProperties("my")
    class MyProperties(@param:DataSizeUnit(DataUnit.MEGABYTES) @param:DefaultValue("2MB") val bufferSize: DataSize,
            @param:DefaultValue("512B") val sizeThreshold: DataSize)
    If you are upgrading a Long property, make sure to define the unit (using @DataSizeUnit) if it is not bytes.
    Doing so gives a transparent upgrade path while supporting a much richer format.
    

    2.8.9. @ConfigurationProperties Validation

    Spring Boot attempts to validate @ConfigurationProperties classes whenever they are annotated with Spring’s @Validated annotation. You can use JSR-303 jakarta.validation constraint annotations directly on your configuration class. To do so, ensure that a compliant JSR-303 implementation is on your classpath and then add constraint annotations to your fields, as shown in the following example:

    import java.net.InetAddress;
    import jakarta.validation.constraints.NotNull;
    import org.springframework.boot.context.properties.ConfigurationProperties;
    import org.springframework.validation.annotation.Validated;
    @ConfigurationProperties("my.service")
    @Validated
    public class MyProperties {
        @NotNull
        private InetAddress remoteAddress;
        // getters/setters...
        public InetAddress getRemoteAddress() {
            return this.remoteAddress;
        public void setRemoteAddress(InetAddress remoteAddress) {
            this.remoteAddress = remoteAddress;
    
    import jakarta.validation.constraints.NotNull
    import org.springframework.boot.context.properties.ConfigurationProperties
    import org.springframework.validation.annotation.Validated
    import java.net.InetAddress
    @ConfigurationProperties("my.service")
    @Validated
    class MyProperties {
        var remoteAddress: @NotNull InetAddress? = null
    

    To ensure that validation is always triggered for nested properties, even when no properties are found, the associated field must be annotated with @Valid. The following example builds on the preceding MyProperties example:

    import java.net.InetAddress;
    import jakarta.validation.Valid;
    import jakarta.validation.constraints.NotEmpty;
    import jakarta.validation.constraints.NotNull;
    import org.springframework.boot.context.properties.ConfigurationProperties;
    import org.springframework.validation.annotation.Validated;
    @ConfigurationProperties("my.service")
    @Validated
    public class MyProperties {
        @NotNull
        private InetAddress remoteAddress;
        @Valid
        private final Security security = new Security();
        // getters/setters...
        public InetAddress getRemoteAddress() {
            return this.remoteAddress;
        public void setRemoteAddress(InetAddress remoteAddress) {
            this.remoteAddress = remoteAddress;
        public Security getSecurity() {
            return this.security;
        public static class Security {
            @NotEmpty
            private String username;
            // getters/setters...
            public String getUsername() {
                return this.username;
            public void setUsername(String username) {
                this.username = username;
    
    import jakarta.validation.Valid
    import jakarta.validation.constraints.NotEmpty
    import jakarta.validation.constraints.NotNull
    import org.springframework.boot.context.properties.ConfigurationProperties
    import org.springframework.validation.annotation.Validated
    import java.net.InetAddress
    @ConfigurationProperties("my.service")
    @Validated
    class MyProperties {
        var remoteAddress: @NotNull InetAddress? = null
        @Valid
        val security = Security()
        class Security {
            @NotEmpty
            var username: String? = null
    

    You can also add a custom Spring Validator by creating a bean definition called configurationPropertiesValidator. The @Bean method should be declared static. The configuration properties validator is created very early in the application’s lifecycle, and declaring the @Bean method as static lets the bean be created without having to instantiate the @Configuration class. Doing so avoids any problems that may be caused by early instantiation.

    The spring-boot-actuator module includes an endpoint that exposes all @ConfigurationProperties beans. Point your web browser to /actuator/configprops or use the equivalent JMX endpoint. See the "
    Production ready features" section for details.

    2.8.10. @ConfigurationProperties vs. @Value

    The @Value annotation is a core container feature, and it does not provide the same features as type-safe configuration properties. The following table summarizes the features that are supported by @ConfigurationProperties and @Value:

    If you do want to use @Value, we recommend that you refer to property names using their canonical form (kebab-case using only lowercase letters). This will allow Spring Boot to use the same logic as it does when relaxed binding @ConfigurationProperties.

    For example, @Value("${demo.item-price}") will pick up demo.item-price and demo.itemPrice forms from the application.properties file, as well as DEMO_ITEMPRICE from the system environment. If you used @Value("${demo.itemPrice}") instead, demo.item-price and DEMO_ITEMPRICE would not be considered.

    If you define a set of configuration keys for your own components, we recommend you group them in a POJO annotated with @ConfigurationProperties. Doing so will provide you with structured, type-safe object that you can inject into your own beans.

    SpEL expressions from application property files are not processed at time of parsing these files and populating the environment. However, it is possible to write a SpEL expression in @Value. If the value of a property from an application property file is a SpEL expression, it will be evaluated when consumed through @Value.

    Spring Profiles provide a way to segregate parts of your application configuration and make it be available only in certain environments. Any @Component, @Configuration or @ConfigurationProperties can be marked with @Profile to limit when it is loaded, as shown in the following example:

    import org.springframework.context.annotation.Configuration;
    import org.springframework.context.annotation.Profile;
    @Configuration(proxyBeanMethods = false)
    @Profile("production")
    public class ProductionConfiguration {
        // ...
    
    import org.springframework.context.annotation.Configuration
    import org.springframework.context.annotation.Profile
    @Configuration(proxyBeanMethods = false)
    @Profile("production")
    class ProductionConfiguration {
        // ...
    If @ConfigurationProperties beans are registered through @EnableConfigurationProperties instead of automatic scanning, the @Profile annotation needs to be specified on the @Configuration class that has the @EnableConfigurationProperties annotation.
    In the case where @ConfigurationProperties are scanned, @Profile can be specified on the @ConfigurationProperties class itself.
    

    You can use a spring.profiles.active Environment property to specify which profiles are active. You can specify the property in any of the ways described earlier in this chapter. For example, you could include it in your application.properties, as shown in the following example:

    Properties
    spring.profiles.active=dev,hsqldb
    spring:
      profiles:
        active: "dev,hsqldb"

    You could also specify it on the command line by using the following switch: --spring.profiles.active=dev,hsqldb.

    If no profile is active, a default profile is enabled. The name of the default profile is default and it can be tuned using the spring.profiles.default Environment property, as shown in the following example:

    Properties
    spring.profiles.default=none
    spring:
      profiles:
        default: "none"

    spring.profiles.active and spring.profiles.default can only be used in non-profile specific documents. This means they cannot be included in profile specific files or documents activated by spring.config.activate.on-profile.

    For example, the second document configuration is invalid:

    Properties
    # this document is valid
    spring.profiles.active=prod
    # this document is invalid
    spring.config.activate.on-profile=prod
    spring.profiles.active=metrics
    # this document is valid
    spring:
      profiles:
        active: "prod"
    # this document is invalid
    spring:
      config:
        activate:
          on-profile: "prod"
      profiles:
        active: "metrics"

    3.1. Adding Active Profiles

    The spring.profiles.active property follows the same ordering rules as other properties: The highest PropertySource wins. This means that you can specify active profiles in application.properties and then replace them by using the command line switch.

    Sometimes, it is useful to have properties that add to the active profiles rather than replace them. The spring.profiles.include property can be used to add active profiles on top of those activated by the spring.profiles.active property. The SpringApplication entry point also has a Java API for setting additional profiles. See the setAdditionalProfiles() method in SpringApplication.

    For example, when an application with the following properties is run, the common and local profiles will be activated even when it runs using the --spring.profiles.active switch:

    Properties
    spring.profiles.include[0]=common
    spring.profiles.include[1]=local
    spring:
      profiles:
        include:
          - "common"
          - "local"
    Similar to spring.profiles.active, spring.profiles.include can only be used in non-profile specific documents. This means it cannot be included in profile specific files or documents activated by spring.config.activate.on-profile.

    3.2. Profile Groups

    Occasionally the profiles that you define and use in your application are too fine-grained and become cumbersome to use. For example, you might have proddb and prodmq profiles that you use to enable database and messaging features independently.

    To help with this, Spring Boot lets you define profile groups. A profile group allows you to define a logical name for a related group of profiles.

    For example, we can create a production group that consists of our proddb and prodmq profiles.

    Properties
    spring.profiles.group.production[0]=proddb
    spring.profiles.group.production[1]=prodmq
    spring:
      profiles:
        group:
          production:
          - "proddb"
          - "prodmq"

    Our application can now be started using --spring.profiles.active=production to activate the production, proddb and prodmq profiles in one hit.

    3.3. Programmatically Setting Profiles

    You can programmatically set active profiles by calling SpringApplication.setAdditionalProfiles(…​) before your application runs. It is also possible to activate profiles by using Spring’s ConfigurableEnvironment interface.

    3.4. Profile-specific Configuration Files

    Profile-specific variants of both application.properties (or application.yml) and files referenced through @ConfigurationProperties are considered as files and loaded. See "Profile Specific Files" for details.

    Spring Boot uses Commons Logging for all internal logging but leaves the underlying log implementation open. Default configurations are provided for Java Util Logging, Log4j2, and Logback. In each case, loggers are pre-configured to use console output with optional file output also available.

    By default, if you use the “Starters”, Logback is used for logging. Appropriate Logback routing is also included to ensure that dependent libraries that use Java Util Logging, Commons Logging, Log4J, or SLF4J all work correctly.

    There are a lot of logging frameworks available for Java. Do not worry if the above list seems confusing. Generally, you do not need to change your logging dependencies and the Spring Boot defaults work just fine. When you deploy your application to a servlet container or application server, logging performed with the Java Util Logging API is not routed into your application’s logs. This prevents logging performed by the container or other applications that have been deployed to it from appearing in your application’s logs.
    2023-04-20T10:07:47.363Z  INFO 18339 --- [           main] o.s.b.d.f.s.MyApplication                : Starting MyApplication using Java 17.0.6 with PID 18339 (/opt/apps/myapp.jar started by myuser in /opt/apps/)
    2023-04-20T10:07:47.377Z  INFO 18339 --- [           main] o.s.b.d.f.s.MyApplication                : No active profile set, falling back to 1 default profile: "default"
    2023-04-20T10:07:52.007Z  INFO 18339 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat initialized with port(s): 8080 (http)
    2023-04-20T10:07:52.064Z  INFO 18339 --- [           main] o.apache.catalina.core.StandardService   : Starting service [Tomcat]
    2023-04-20T10:07:52.064Z  INFO 18339 --- [           main] o.apache.catalina.core.StandardEngine    : Starting Servlet engine: [Apache Tomcat/10.1.8]
    2023-04-20T10:07:52.577Z  INFO 18339 --- [           main] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring embedded WebApplicationContext
    2023-04-20T10:07:52.590Z  INFO 18339 --- [           main] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 5092 ms
    2023-04-20T10:07:54.152Z  INFO 18339 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat started on port(s): 8080 (http) with context path ''
    2023-04-20T10:07:54.164Z  INFO 18339 --- [           main] o.s.b.d.f.s.MyApplication                : Started MyApplication in 8.205 seconds (process running for 9.207)

    The following items are output:

    4.2. Console Output

    The default log configuration echoes messages to the console as they are written. By default, ERROR-level, WARN-level, and INFO-level messages are logged. You can also enable a “debug” mode by starting your application with a --debug flag.

    $ java -jar myapp.jar --debug

    When the debug mode is enabled, a selection of core loggers (embedded container, Hibernate, and Spring Boot) are configured to output more information. Enabling the debug mode does not configure your application to log all messages with DEBUG level.

    Alternatively, you can enable a “trace” mode by starting your application with a --trace flag (or trace=true in your application.properties). Doing so enables trace logging for a selection of core loggers (embedded container, Hibernate schema generation, and the whole Spring portfolio).

    4.2.1. Color-coded Output

    If your terminal supports ANSI, color output is used to aid readability. You can set spring.output.ansi.enabled to a supported value to override the auto-detection.

    Color coding is configured by using the %clr conversion word. In its simplest form, the converter colors the output according to the log level, as shown in the following example:

    %clr(%5p)

    The following table describes the mapping of log levels to colors:

    Alternatively, you can specify the color or style that should be used by providing it as an option to the conversion. For example, to make the text yellow, use the following setting:

    %clr(%d{yyyy-MM-dd'T'HH:mm:ss.SSSXXX}){yellow}

    The following colors and styles are supported:

    4.3. File Output

    By default, Spring Boot logs only to the console and does not write log files. If you want to write log files in addition to the console output, you need to set a logging.file.name or logging.file.path property (for example, in your application.properties).

    The following table shows how the logging.* properties can be used together:

    Table 5. Logging properties

    my.log

    Writes to the specified log file. Names can be an exact location or relative to the current directory.

    (none)

    Specific directory

    /var/log

    Writes spring.log to the specified directory. Names can be an exact location or relative to the current directory.

    4.4. File Rotation

    If you are using the Logback, it is possible to fine-tune log rotation settings using your application.properties or application.yaml file. For all other logging system, you will need to configure rotation settings directly yourself (for example, if you use Log4j2 then you could add a log4j2.xml or log4j2-spring.xml file).

    The following rotation policy properties are supported:

    logging.logback.rollingpolicy.file-name-pattern

    The filename pattern used to create log archives.

    logging.logback.rollingpolicy.clean-history-on-start

    If log archive cleanup should occur when the application starts.

    logging.logback.rollingpolicy.max-file-size

    The maximum size of log file before it is archived.

    logging.logback.rollingpolicy.total-size-cap

    The maximum amount of size log archives can take before being deleted.

    logging.logback.rollingpolicy.max-history

    The maximum number of archive log files to keep (defaults to 7).

    4.5. Log Levels

    All the supported logging systems can have the logger levels set in the Spring Environment (for example, in application.properties) by using logging.level.<logger-name>=<level> where level is one of TRACE, DEBUG, INFO, WARN, ERROR, FATAL, or OFF. The root logger can be configured by using logging.level.root.

    The following example shows potential logging settings in application.properties:

    Properties
    logging.level.root=warn
    logging.level.org.springframework.web=debug
    logging.level.org.hibernate=error
    logging:
      level:
        root: "warn"
        org.springframework.web: "debug"
        org.hibernate: "error"

    It is also possible to set logging levels using environment variables. For example, LOGGING_LEVEL_ORG_SPRINGFRAMEWORK_WEB=DEBUG will set org.springframework.web to DEBUG.

    The above approach will only work for package level logging. Since relaxed binding always converts environment variables to lowercase, it is not possible to configure logging for an individual class in this way. If you need to configure logging for a class, you can use
    the SPRING_APPLICATION_JSON variable.

    4.6. Log Groups

    It is often useful to be able to group related loggers together so that they can all be configured at the same time. For example, you might commonly change the logging levels for all Tomcat related loggers, but you can not easily remember top level packages.

    To help with this, Spring Boot allows you to define logging groups in your Spring Environment. For example, here is how you could define a “tomcat” group by adding it to your application.properties:

    Properties
    logging.group.tomcat=org.apache.catalina,org.apache.coyote,org.apache.tomcat
    logging:
      group:
        tomcat: "org.apache.catalina,org.apache.coyote,org.apache.tomcat"

    Once defined, you can change the level for all the loggers in the group with a single line:

    Properties
    logging.level.tomcat=trace
    logging:
      level:
        tomcat: "trace"

    Spring Boot includes the following pre-defined logging groups that can be used out-of-the-box:

    org.springframework.core.codec, org.springframework.http, org.springframework.web, org.springframework.boot.actuate.endpoint.web, org.springframework.boot.web.servlet.ServletContextInitializerBeans

    org.springframework.jdbc.core, org.hibernate.SQL, org.jooq.tools.LoggerListener

    4.7. Using a Log Shutdown Hook

    In order to release logging resources when your application terminates, a shutdown hook that will trigger log system cleanup when the JVM exits is provided. This shutdown hook is registered automatically unless your application is deployed as a war file. If your application has complex context hierarchies the shutdown hook may not meet your needs. If it does not, disable the shutdown hook and investigate the options provided directly by the underlying logging system. For example, Logback offers context selectors which allow each Logger to be created in its own context. You can use the logging.register-shutdown-hook property to disable the shutdown hook. Setting it to false will disable the registration. You can set the property in your application.properties or application.yaml file:

    Properties
    logging.register-shutdown-hook=false
    logging:
      register-shutdown-hook: false

    4.8. Custom Log Configuration

    The various logging systems can be activated by including the appropriate libraries on the classpath and can be further customized by providing a suitable configuration file in the root of the classpath or in a location specified by the following Spring Environment property: logging.config.

    You can force Spring Boot to use a particular logging system by using the org.springframework.boot.logging.LoggingSystem system property. The value should be the fully qualified class name of a LoggingSystem implementation. You can also disable Spring Boot’s logging configuration entirely by using a value of none.

    Since logging is initialized before the ApplicationContext is created, it is not possible to control logging from @PropertySources in Spring @Configuration files. The only way to change the logging system or disable it entirely is through System properties. When possible, we recommend that you use the -spring variants for your logging configuration (for example, logback-spring.xml rather than logback.xml). If you use standard configuration locations, Spring cannot completely control log initialization. There are known classloading issues with Java Util Logging that cause problems when running from an 'executable jar'. We recommend that you avoid it when running from an 'executable jar' if at all possible.

    logging.exception-conversion-word

    LOG_EXCEPTION_CONVERSION_WORD

    The conversion word used when logging exceptions.

    logging.file.name

    LOG_FILE

    If defined, it is used in the default log configuration.

    logging.file.path

    LOG_PATH

    If defined, it is used in the default log configuration.

    logging.pattern.console

    CONSOLE_LOG_PATTERN

    The log pattern to use on the console (stdout).

    logging.pattern.dateformat

    LOG_DATEFORMAT_PATTERN

    Appender pattern for log date format.

    logging.charset.console

    CONSOLE_LOG_CHARSET

    The charset to use for console logging.

    logging.pattern.file

    FILE_LOG_PATTERN

    The log pattern to use in a file (if LOG_FILE is enabled).

    logging.charset.file

    FILE_LOG_CHARSET

    The charset to use for file logging (if LOG_FILE is enabled).

    logging.pattern.level

    LOG_LEVEL_PATTERN

    The format to use when rendering the log level (default %5p).

    The current process ID (discovered if possible and when not already defined as an OS environment variable).

    logging.logback.rollingpolicy.file-name-pattern

    LOGBACK_ROLLINGPOLICY_FILE_NAME_PATTERN

    Pattern for rolled-over log file names (default ${LOG_FILE}.%d{yyyy-MM-dd}.%i.gz).

    logging.logback.rollingpolicy.clean-history-on-start

    LOGBACK_ROLLINGPOLICY_CLEAN_HISTORY_ON_START

    Whether to clean the archive log files on startup.

    logging.logback.rollingpolicy.max-file-size

    LOGBACK_ROLLINGPOLICY_MAX_FILE_SIZE

    Maximum log file size.

    logging.logback.rollingpolicy.total-size-cap

    LOGBACK_ROLLINGPOLICY_TOTAL_SIZE_CAP

    Total size of log backups to be kept.

    logging.logback.rollingpolicy.max-history

    LOGBACK_ROLLINGPOLICY_MAX_HISTORY

    Maximum number of archive log files to keep.

    All the supported logging systems can consult System properties when parsing their configuration files. See the default configurations in spring-boot.jar for examples:

    If you want to use a placeholder in a logging property, you should use Spring Boot’s syntax and not the syntax of the underlying framework. Notably, if you use Logback, you should use : as the delimiter between a property name and its default value and not use :-.

    You can add MDC and other ad-hoc content to log lines by overriding only the LOG_LEVEL_PATTERN (or logging.pattern.level with Logback). For example, if you use logging.pattern.level=user:%X{user} %5p, then the default log format contains an MDC entry for "user", if it exists, as shown in the following example.

    2019-08-30 12:30:04.031 user:someone INFO 22174 --- [  nio-8080-exec-0] demo.Controller
    Handling authenticated request

    4.9. Logback Extensions

    Spring Boot includes a number of extensions to Logback that can help with advanced configuration. You can use these extensions in your logback-spring.xml configuration file.

    Because the standard logback.xml configuration file is loaded too early, you cannot use extensions in it. You need to either use logback-spring.xml or define a logging.config property.
    ERROR in [email protected]:71 - no applicable action for [springProperty], current ElementPath is [[configuration][springProperty]]
    ERROR in [email protected]:71 - no applicable action for [springProfile], current ElementPath is [[configuration][springProfile]]

    4.9.1. Profile-specific Configuration

    The <springProfile> tag lets you optionally include or exclude sections of configuration based on the active Spring profiles. Profile sections are supported anywhere within the <configuration> element. Use the name attribute to specify which profile accepts the configuration. The <springProfile> tag can contain a profile name (for example staging) or a profile expression. A profile expression allows for more complicated profile logic to be expressed, for example production & (eu-central | eu-west). Check the Spring Framework reference guide for more details. The following listing shows three sample profiles:

    <springProfile name="staging">
        <!-- configuration to be enabled when the "staging" profile is active -->
    </springProfile>
    <springProfile name="dev | staging">
        <!-- configuration to be enabled when the "dev" or "staging" profiles are active -->
    </springProfile>
    <springProfile name="!production">
        <!-- configuration to be enabled when the "production" profile is not active -->
    </springProfile>

    4.9.2. Environment Properties

    The <springProperty> tag lets you expose properties from the Spring Environment for use within Logback. Doing so can be useful if you want to access values from your application.properties file in your Logback configuration. The tag works in a similar way to Logback’s standard <property> tag. However, rather than specifying a direct value, you specify the source of the property (from the Environment). If you need to store the property somewhere other than in local scope, you can use the scope attribute. If you need a fallback value (in case the property is not set in the Environment), you can use the defaultValue attribute. The following example shows how to expose properties for use within Logback:

    <springProperty scope="context" name="fluentHost" source="myapp.fluentd.host"
            defaultValue="localhost"/>
    <appender name="FLUENT" class="ch.qos.logback.more.appenders.DataFluentAppender">
        <remoteHost>${fluentHost}</remoteHost>
    </appender>

    4.10. Log4j2 Extensions

    Spring Boot includes a number of extensions to Log4j2 that can help with advanced configuration. You can use these extensions in any log4j2-spring.xml configuration file.

    Because the standard log4j2.xml configuration file is loaded too early, you cannot use extensions in it. You need to either use log4j2-spring.xml or define a logging.config property.

    4.10.1. Profile-specific Configuration

    The <SpringProfile> tag lets you optionally include or exclude sections of configuration based on the active Spring profiles. Profile sections are supported anywhere within the <Configuration> element. Use the name attribute to specify which profile accepts the configuration. The <SpringProfile> tag can contain a profile name (for example staging) or a profile expression. A profile expression allows for more complicated profile logic to be expressed, for example production & (eu-central | eu-west). Check the Spring Framework reference guide for more details. The following listing shows three sample profiles:

    <SpringProfile name="staging">
        <!-- configuration to be enabled when the "staging" profile is active -->
    </SpringProfile>
    <SpringProfile name="dev | staging">
        <!-- configuration to be enabled when the "dev" or "staging" profiles are active -->
    </SpringProfile>
    <SpringProfile name="!production">
        <!-- configuration to be enabled when the "production" profile is not active -->
    </SpringProfile>

    4.10.2. Environment Properties Lookup

    If you want to refer to properties from your Spring Environment within your Log4j2 configuration you can use spring: prefixed lookups. Doing so can be useful if you want to access values from your application.properties file in your Log4j2 configuration.

    The following example shows how to set a Log4j2 property named applicationName that reads spring.application.name from the Spring Environment:

    <Properties>
        <Property name="applicationName">${spring:spring.application.name}</Property>
    </Properties>

    4.10.3. Log4j2 System Properties

    Log4j2 supports a number of System Properties that can be used to configure various items. For example, the log4j2.skipJansi system property can be used to configure if the ConsoleAppender will try to use a Jansi output stream on Windows.

    All system properties that are loaded after the Log4j2 initialization can be obtained from the Spring Environment. For example, you could add log4j2.skipJansi=false to your application.properties file to have the ConsoleAppender use Jansi on Windows.

    System properties that are loaded during early Log4j2 initialization cannot reference the Spring Environment. For example, the property Log4j2 uses to allow the default Log4j2 implementation to be chosen is used before the Spring Environment is available.

    Spring Boot supports localized messages so that your application can cater to users of different language preferences. By default, Spring Boot looks for the presence of a messages resource bundle at the root of the classpath.

    The auto-configuration applies when the default properties file for the configured resource bundle is available (messages.properties by default). If your resource bundle contains only language-specific properties files, you are required to add the default. If no properties file is found that matches any of the configured base names, there will be no auto-configured MessageSource.

    The basename of the resource bundle as well as several other attributes can be configured using the spring.messages namespace, as shown in the following example:

    Properties
    spring.messages.basename=messages,config.i18n.messages
    spring.messages.fallback-to-system-locale=false
    spring:
      messages:
        basename: "messages,config.i18n.messages"
        fallback-to-system-locale: false

    6.1. Jackson

    Auto-configuration for Jackson is provided and Jackson is part of spring-boot-starter-json. When Jackson is on the classpath an ObjectMapper bean is automatically configured. Several configuration properties are provided for customizing the configuration of the ObjectMapper.

    6.1.1. Custom Serializers and Deserializers

    If you use Jackson to serialize and deserialize JSON data, you might want to write your own JsonSerializer and JsonDeserializer classes. Custom serializers are usually registered with Jackson through a module, but Spring Boot provides an alternative @JsonComponent annotation that makes it easier to directly register Spring Beans.

    You can use the @JsonComponent annotation directly on JsonSerializer, JsonDeserializer or KeyDeserializer implementations. You can also use it on classes that contain serializers/deserializers as inner classes, as shown in the following example:

    import java.io.IOException;
    import com.fasterxml.jackson.core.JsonGenerator;
    import com.fasterxml.jackson.core.JsonParser;
    import com.fasterxml.jackson.core.ObjectCodec;
    import com.fasterxml.jackson.databind.DeserializationContext;
    import com.fasterxml.jackson.databind.JsonDeserializer;
    import com.fasterxml.jackson.databind.JsonNode;
    import com.fasterxml.jackson.databind.JsonSerializer;
    import com.fasterxml.jackson.databind.SerializerProvider;
    import org.springframework.boot.jackson.JsonComponent;
    @JsonComponent
    public class MyJsonComponent {
        public static class Serializer extends JsonSerializer<MyObject> {
            @Override
            public void serialize(MyObject value, JsonGenerator jgen, SerializerProvider serializers) throws IOException {
                jgen.writeStartObject();
                jgen.writeStringField("name", value.getName());
                jgen.writeNumberField("age", value.getAge());
                jgen.writeEndObject();
        public static class Deserializer extends JsonDeserializer<MyObject> {
            @Override
            public MyObject deserialize(JsonParser jsonParser, DeserializationContext ctxt) throws IOException {
                ObjectCodec codec = jsonParser.getCodec();
                JsonNode tree = codec.readTree(jsonParser);
                String name = tree.get("name").textValue();
                int age = tree.get("age").intValue();
                return new MyObject(name, age);
    
    import com.fasterxml.jackson.core.JsonGenerator
    import com.fasterxml.jackson.core.JsonParser
    import com.fasterxml.jackson.core.JsonProcessingException
    import com.fasterxml.jackson.databind.DeserializationContext
    import com.fasterxml.jackson.databind.JsonDeserializer
    import com.fasterxml.jackson.databind.JsonNode
    import com.fasterxml.jackson.databind.JsonSerializer
    import com.fasterxml.jackson.databind.SerializerProvider
    import org.springframework.boot.jackson.JsonComponent
    import java.io.IOException
    @JsonComponent
    class MyJsonComponent {
        class Serializer : JsonSerializer<MyObject>() {
            @Throws(IOException::class)
            override fun serialize(value: MyObject, jgen: JsonGenerator, serializers: SerializerProvider) {
                jgen.writeStartObject()
                jgen.writeStringField("name", value.name)
                jgen.writeNumberField("age", value.age)
                jgen.writeEndObject()
        class Deserializer : JsonDeserializer<MyObject>() {
            @Throws(IOException::class, JsonProcessingException::class)
            override fun deserialize(jsonParser: JsonParser, ctxt: DeserializationContext): MyObject {
                val codec = jsonParser.codec
                val tree = codec.readTree<JsonNode>(jsonParser)
                val name = tree["name"].textValue()
                val age = tree["age"].intValue()
                return MyObject(name, age)
    

    All @JsonComponent beans in the ApplicationContext are automatically registered with Jackson. Because @JsonComponent is meta-annotated with @Component, the usual component-scanning rules apply.

    Spring Boot also provides JsonObjectSerializer and JsonObjectDeserializer base classes that provide useful alternatives to the standard Jackson versions when serializing objects. See JsonObjectSerializer and JsonObjectDeserializer in the Javadoc for details.

    The example above can be rewritten to use JsonObjectSerializer/JsonObjectDeserializer as follows:

    import java.io.IOException;
    import com.fasterxml.jackson.core.JsonGenerator;
    import com.fasterxml.jackson.core.JsonParser;
    import com.fasterxml.jackson.core.ObjectCodec;
    import com.fasterxml.jackson.databind.DeserializationContext;
    import com.fasterxml.jackson.databind.JsonNode;
    import com.fasterxml.jackson.databind.SerializerProvider;
    import org.springframework.boot.jackson.JsonComponent;
    import org.springframework.boot.jackson.JsonObjectDeserializer;
    import org.springframework.boot.jackson.JsonObjectSerializer;
    @JsonComponent
    public class MyJsonComponent {
        public static class Serializer extends JsonObjectSerializer<MyObject> {
            @Override
            protected void serializeObject(MyObject value, JsonGenerator jgen, SerializerProvider provider)
                    throws IOException {
                jgen.writeStringField("name", value.getName());
                jgen.writeNumberField("age", value.getAge());
        public static class Deserializer extends JsonObjectDeserializer<MyObject> {
            @Override
            protected MyObject deserializeObject(JsonParser jsonParser, DeserializationContext context, ObjectCodec codec,
                    JsonNode tree) throws IOException {
                String name = nullSafeValue(tree.get("name"), String.class);
                int age = nullSafeValue(tree.get("age"), Integer.class);
                return new MyObject(name, age);
    import com.fasterxml.jackson.core.JsonGenerator
    import com.fasterxml.jackson.core.JsonParser
    import com.fasterxml.jackson.core.ObjectCodec
    import com.fasterxml.jackson.databind.DeserializationContext
    import com.fasterxml.jackson.databind.JsonNode
    import com.fasterxml.jackson.databind.SerializerProvider
    import org.springframework.boot.jackson.JsonComponent
    import org.springframework.boot.jackson.JsonObjectDeserializer
    import org.springframework.boot.jackson.JsonObjectSerializer
    import java.io.IOException
    @JsonComponent
    class MyJsonComponent {
        class Serializer : JsonObjectSerializer<MyObject>() {
            @Throws(IOException::class)
            override fun serializeObject(value: MyObject, jgen: JsonGenerator, provider: SerializerProvider) {
                jgen.writeStringField("name", value.name)
                jgen.writeNumberField("age", value.age)
        class Deserializer : JsonObjectDeserializer<MyObject>() {
            @Throws(IOException::class)
            override fun deserializeObject(jsonParser: JsonParser, context: DeserializationContext,
                    codec: ObjectCodec, tree: JsonNode): MyObject {
                val name = nullSafeValue(tree["name"], String::class.java)
                val age = nullSafeValue(tree["age"], Int::class.java)
                return MyObject(name, age)
    

    6.1.2. Mixins

    Jackson has support for mixins that can be used to mix additional annotations into those already declared on a target class. Spring Boot’s Jackson auto-configuration will scan your application’s packages for classes annotated with @JsonMixin and register them with the auto-configured ObjectMapper. The registration is performed by Spring Boot’s JsonMixinModule.

    Auto-configuration for Gson is provided. When Gson is on the classpath a Gson bean is automatically configured. Several spring.gson.* configuration properties are provided for customizing the configuration. To take more control, one or more GsonBuilderCustomizer beans can be used.

    6.3. JSON-B

    Auto-configuration for JSON-B is provided. When the JSON-B API and an implementation are on the classpath a Jsonb bean will be automatically configured. The preferred JSON-B implementation is Eclipse Yasson for which dependency management is provided.

    If you have defined a custom Executor in the context, regular task execution (that is @EnableAsync) will use it transparently but the Spring MVC support will not be configured as it requires an AsyncTaskExecutor implementation (named applicationTaskExecutor). Depending on your target arrangement, you could change your Executor into a ThreadPoolTaskExecutor or define both a ThreadPoolTaskExecutor and an AsyncConfigurer wrapping your custom Executor.

    The auto-configured TaskExecutorBuilder allows you to easily create instances that reproduce what the auto-configuration does by default.

    The thread pool uses 8 core threads that can grow and shrink according to the load. Those default settings can be fine-tuned using the spring.task.execution namespace, as shown in the following example:

    Properties
    spring.task.execution.pool.max-size=16
    spring.task.execution.pool.queue-capacity=100
    spring.task.execution.pool.keep-alive=10s
    spring:
      task:
        execution:
          pool:
            max-size: 16
            queue-capacity: 100
            keep-alive: "10s"

    This changes the thread pool to use a bounded queue so that when the queue is full (100 tasks), the thread pool increases to maximum 16 threads. Shrinking of the pool is more aggressive as threads are reclaimed when they are idle for 10 seconds (rather than 60 seconds by default).

    A ThreadPoolTaskScheduler can also be auto-configured if need to be associated to scheduled task execution (using @EnableScheduling for instance). The thread pool uses one thread by default and its settings can be fine-tuned using the spring.task.scheduling namespace, as shown in the following example:

    Properties
    spring.task.scheduling.thread-name-prefix=scheduling-
    spring.task.scheduling.pool.size=2
    spring:
      task:
        scheduling:
          thread-name-prefix: "scheduling-"
          pool:
            size: 2

    Both a TaskExecutorBuilder bean and a TaskSchedulerBuilder bean are made available in the context if a custom executor or scheduler needs to be created.

    Spring Boot provides a number of utilities and annotations to help when testing your application. Test support is provided by two modules: spring-boot-test contains core items, and spring-boot-test-autoconfigure supports auto-configuration for tests.

    Most developers use the spring-boot-starter-test “Starter”, which imports both Spring Boot test modules as well as JUnit Jupiter, AssertJ, Hamcrest, and a number of other useful libraries.

    <groupId>org.junit.vintage</groupId> <artifactId>junit-vintage-engine</artifactId> <scope>test</scope> <exclusions> <exclusion> <groupId>org.hamcrest</groupId> <artifactId>hamcrest-core</artifactId> </exclusion> </exclusions> </dependency>

    hamcrest-core is excluded in favor of org.hamcrest:hamcrest that is part of spring-boot-starter-test.

    8.1. Test Scope Dependencies

    The spring-boot-starter-test “Starter” (in the test scope) contains the following provided libraries:

    Spring Test & Spring Boot Test: Utilities and integration test support for Spring Boot applications.

    AssertJ: A fluent assertion library.

    Hamcrest: A library of matcher objects (also known as constraints or predicates).

    Mockito: A Java mocking framework.

    JSONassert: An assertion library for JSON.

    JsonPath: XPath for JSON.

    8.2. Testing Spring Applications

    One of the major advantages of dependency injection is that it should make your code easier to unit test. You can instantiate objects by using the new operator without even involving Spring. You can also use mock objects instead of real dependencies.

    Often, you need to move beyond unit testing and start integration testing (with a Spring ApplicationContext). It is useful to be able to perform integration testing without requiring deployment of your application or needing to connect to other infrastructure.

    The Spring Framework includes a dedicated test module for such integration testing. You can declare a dependency directly to org.springframework:spring-test or use the spring-boot-starter-test “Starter” to pull it in transitively.

    If you have not used the spring-test module before, you should start by reading the relevant section of the Spring Framework reference documentation.

    8.3. Testing Spring Boot Applications

    A Spring Boot application is a Spring ApplicationContext, so nothing very special has to be done to test it beyond what you would normally do with a vanilla Spring context.

    Spring Boot provides a @SpringBootTest annotation, which can be used as an alternative to the standard spring-test @ContextConfiguration annotation when you need Spring Boot features. The annotation works by creating the ApplicationContext used in your tests through SpringApplication. In addition to @SpringBootTest a number of other annotations are also provided for testing more specific slices of an application.

    If you are using JUnit 4, do not forget to also add @RunWith(SpringRunner.class) to your test, otherwise the annotations will be ignored. If you are using JUnit 5, there is no need to add the equivalent @ExtendWith(SpringExtension.class) as @SpringBootTest and the other @…​Test annotations are already annotated with it.

    MOCK(Default) : Loads a web ApplicationContext and provides a mock web environment. Embedded servers are not started when using this annotation. If a web environment is not available on your classpath, this mode transparently falls back to creating a regular non-web ApplicationContext. It can be used in conjunction with @AutoConfigureMockMvc or @AutoConfigureWebTestClient for mock-based testing of your web application.

    RANDOM_PORT: Loads a WebServerApplicationContext and provides a real web environment. Embedded servers are started and listen on a random port.

    DEFINED_PORT: Loads a WebServerApplicationContext and provides a real web environment. Embedded servers are started and listen on a defined port (from your application.properties) or on the default port of 8080.

    NONE: Loads an ApplicationContext by using SpringApplication but does not provide any web environment (mock or otherwise).

    If your test is @Transactional, it rolls back the transaction at the end of each test method by default. However, as using this arrangement with either RANDOM_PORT or DEFINED_PORT implicitly provides a real servlet environment, the HTTP client and server run in separate threads and, thus, in separate transactions. Any transaction initiated on the server does not roll back in this case.

    8.3.1. Detecting Web Application Type

    If Spring MVC is available, a regular MVC-based application context is configured. If you have only Spring WebFlux, we will detect that and configure a WebFlux-based application context instead.

    If both are present, Spring MVC takes precedence. If you want to test a reactive web application in this scenario, you must set the spring.main.web-application-type property:

    import org.springframework.boot.test.context.SpringBootTest;
    @SpringBootTest(properties = "spring.main.web-application-type=reactive")
    class MyWebFluxTests {
        // ...
    
    import org.springframework.boot.test.context.SpringBootTest
    @SpringBootTest(properties = ["spring.main.web-application-type=reactive"])
    class MyWebFluxTests {
        // ...
    

    8.3.2. Detecting Test Configuration

    If you are familiar with the Spring Test Framework, you may be used to using @ContextConfiguration(classes=…​) in order to specify which Spring @Configuration to load. Alternatively, you might have often used nested @Configuration classes within your test.

    When testing Spring Boot applications, this is often not required. Spring Boot’s @*Test annotations search for your primary configuration automatically whenever you do not explicitly define one.

    The search algorithm works up from the package that contains the test until it finds a class annotated with @SpringBootApplication or @SpringBootConfiguration. As long as you structured your code in a sensible way, your main configuration is usually found.

    If you use a test annotation to test a more specific slice of your application, you should avoid adding configuration settings that are specific to a particular area on the main method’s application class.

    The underlying component scan configuration of @SpringBootApplication defines exclude filters that are used to make sure slicing works as expected. If you are using an explicit @ComponentScan directive on your @SpringBootApplication-annotated class, be aware that those filters will be disabled. If you are using slicing, you should define them again.

    If you want to customize the primary configuration, you can use a nested @TestConfiguration class. Unlike a nested @Configuration class, which would be used instead of your application’s primary configuration, a nested @TestConfiguration class is used in addition to your application’s primary configuration.

    8.3.3. Using the Test Configuration Main Method

    Typically the test configuration discovered by @SpringBootTest will be your main @SpringBootApplication. In most well structured applications, this configuration class will also include the main method used to launch the application.

    For example, the following is a very common code pattern for a typical Spring Boot application:

    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);
    
    import org.springframework.boot.autoconfigure.SpringBootApplication
    import org.springframework.boot.docs.using.structuringyourcode.locatingthemainclass.MyApplication
    import org.springframework.boot.runApplication
    @SpringBootApplication
    class MyApplication
    fun main(args: Array<String>) {
        runApplication<MyApplication>(*args)
    

    In the example above, the main method doesn’t do anything other than delegate to SpringApplication.run. It is, however, possible to have a more complex main method that applies customizations before calling SpringApplication.run.

    For example, here is an application that changes the banner mode and sets additional profiles:

    import org.springframework.boot.Banner;
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    @SpringBootApplication
    public class MyApplication {
        public static void main(String[] args) {
            SpringApplication application = new SpringApplication(MyApplication.class);
            application.setBannerMode(Banner.Mode.OFF);
            application.setAdditionalProfiles("myprofile");
            application.run(args);
    
    import org.springframework.boot.Banner
    import org.springframework.boot.runApplication
    import org.springframework.boot.autoconfigure.SpringBootApplication
    @SpringBootApplication
    class MyApplication
    fun main(args: Array<String>) {
        runApplication<MyApplication>(*args) {
            setBannerMode(Banner.Mode.OFF)
            setAdditionalProfiles("myprofile");
    

    Since customizations in the main method can affect the resulting ApplicationContext, it’s possible that you might also want to use the main method to create the ApplicationContext used in your tests. By default, @SpringBootTest will not call your main method, and instead the class itself is used directly to create the ApplicationContext

    If you want to change this behavior, you can change the useMainMethod attribute of @SpringBootTest to UseMainMethod.ALWAYS or UseMainMethod.WHEN_AVAILABLE. When set to ALWAYS, the test will fail if no main method can be found. When set to WHEN_AVAILABLE the main method will be used if it is available, otherwise the standard loading mechanism will be used.

    For example, the following test will invoke the main method of MyApplication in order to create the ApplicationContext. If the main method sets additional profiles then those will be active when the ApplicationContext starts.

    import org.junit.jupiter.api.Test;
    import org.springframework.boot.test.context.SpringBootTest;
    import org.springframework.boot.test.context.SpringBootTest.UseMainMethod;
    @SpringBootTest(useMainMethod = UseMainMethod.ALWAYS)
    class MyApplicationTests {
        @Test
        void exampleTest() {
            // ...
    
    import org.junit.jupiter.api.Test
    import org.springframework.boot.test.context.SpringBootTest
    import org.springframework.boot.test.context.SpringBootTest.UseMainMethod
    import org.springframework.context.annotation.Import
    @SpringBootTest(useMainMethod = UseMainMethod.ALWAYS)
    class MyApplicationTests {
        @Test
        fun exampleTest() {
            // ...
    

    8.3.4. Excluding Test Configuration

    If your application uses component scanning (for example, if you use @SpringBootApplication or @ComponentScan), you may find top-level configuration classes that you created only for specific tests accidentally get picked up everywhere.

    As we have seen earlier, @TestConfiguration can be used on an inner class of a test to customize the primary configuration. When placed on a top-level class, @TestConfiguration indicates that classes in src/test/java should not be picked up by scanning. You can then import that class explicitly where it is required, as shown in the following example:

    import org.junit.jupiter.api.Test;
    import org.springframework.boot.test.context.SpringBootTest;
    import org.springframework.context.annotation.Import;
    @SpringBootTest
    @Import(MyTestsConfiguration.class)
    class MyTests {
        @Test
        void exampleTest() {
            // ...
    
    import org.junit.jupiter.api.Test
    import org.springframework.boot.test.context.SpringBootTest
    import org.springframework.context.annotation.Import
    @SpringBootTest
    @Import(MyTestsConfiguration::class)
    class MyTests {
        @Test
        fun exampleTest() {
            // ...
    If you directly use @ComponentScan (that is, not through @SpringBootApplication) you need to register the TypeExcludeFilter with it.
    See the Javadoc for details.
    

    If your application expects arguments, you can have @SpringBootTest inject them using the args attribute.

    import org.junit.jupiter.api.Test;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.boot.ApplicationArguments;
    import org.springframework.boot.test.context.SpringBootTest;
    import static org.assertj.core.api.Assertions.assertThat;
    @SpringBootTest(args = "--app.test=one")
    class MyApplicationArgumentTests {
        @Test
        void applicationArgumentsPopulated(@Autowired ApplicationArguments args) {
            assertThat(args.getOptionNames()).containsOnly("app.test");
            assertThat(args.getOptionValues("app.test")).containsOnly("one");
    
    import org.assertj.core.api.Assertions.assertThat
    import org.junit.jupiter.api.Test
    import org.springframework.beans.factory.annotation.Autowired
    import org.springframework.boot.ApplicationArguments
    import org.springframework.boot.test.context.SpringBootTest
    @SpringBootTest(args = ["--app.test=one"])
    class MyApplicationArgumentTests {
        @Test
        fun applicationArgumentsPopulated(@Autowired args: ApplicationArguments) {
            assertThat(args.optionNames).containsOnly("app.test")
            assertThat(args.getOptionValues("app.test")).containsOnly("one")
    

    8.3.6. Testing With a Mock Environment

    By default, @SpringBootTest does not start the server but instead sets up a mock environment for testing web endpoints.

    With Spring MVC, we can query our web endpoints using MockMvc or WebTestClient, as shown in the following example:

    import org.junit.jupiter.api.Test;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
    import org.springframework.boot.test.context.SpringBootTest;
    import org.springframework.test.web.reactive.server.WebTestClient;
    import org.springframework.test.web.servlet.MockMvc;
    import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
    import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
    import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
    @SpringBootTest
    @AutoConfigureMockMvc
    class MyMockMvcTests {
        @Test
        void testWithMockMvc(@Autowired MockMvc mvc) throws Exception {
            mvc.perform(get("/")).andExpect(status().isOk()).andExpect(content().string("Hello World"));
        // If Spring WebFlux is on the classpath, you can drive MVC tests with a WebTestClient
        @Test
        void testWithWebTestClient(@Autowired WebTestClient webClient) {
            webClient
                    .get().uri("/")
                    .exchange()
                    .expectStatus().isOk()
                    .expectBody(String.class).isEqualTo("Hello World");
    
    import org.junit.jupiter.api.Test
    import org.springframework.beans.factory.annotation.Autowired
    import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc
    import org.springframework.boot.test.context.SpringBootTest
    import org.springframework.test.web.reactive.server.WebTestClient
    import org.springframework.test.web.reactive.server.expectBody
    import org.springframework.test.web.servlet.MockMvc
    import org.springframework.test.web.servlet.request.MockMvcRequestBuilders
    import org.springframework.test.web.servlet.result.MockMvcResultMatchers
    @SpringBootTest
    @AutoConfigureMockMvc
    class MyMockMvcTests {
        @Test
        fun testWithMockMvc(@Autowired mvc: MockMvc) {
            mvc.perform(MockMvcRequestBuilders.get("/")).andExpect(MockMvcResultMatchers.status().isOk)
                .andExpect(MockMvcResultMatchers.content().string("Hello World"))
        // If Spring WebFlux is on the classpath, you can drive MVC tests with a WebTestClient
        @Test
        fun testWithWebTestClient(@Autowired webClient: WebTestClient) {
            webClient
                .get().uri("/")
                .exchange()
                .expectStatus().isOk
                .expectBody<String>().isEqualTo("Hello World")
    

    With Spring WebFlux endpoints, you can use WebTestClient as shown in the following example:

    import org.junit.jupiter.api.Test;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.boot.test.autoconfigure.web.reactive.AutoConfigureWebTestClient;
    import org.springframework.boot.test.context.SpringBootTest;
    import org.springframework.test.web.reactive.server.WebTestClient;
    @SpringBootTest
    @AutoConfigureWebTestClient
    class MyMockWebTestClientTests {
        @Test
        void exampleTest(@Autowired WebTestClient webClient) {
            webClient
                .get().uri("/")
                .exchange()
                .expectStatus().isOk()
                .expectBody(String.class).isEqualTo("Hello World");
    
    import org.junit.jupiter.api.Test
    import org.springframework.beans.factory.annotation.Autowired
    import org.springframework.boot.test.autoconfigure.web.reactive.AutoConfigureWebTestClient
    import org.springframework.boot.test.context.SpringBootTest
    import org.springframework.test.web.reactive.server.WebTestClient
    import org.springframework.test.web.reactive.server.expectBody
    @SpringBootTest
    @AutoConfigureWebTestClient
    class MyMockWebTestClientTests {
        @Test
        fun exampleTest(@Autowired webClient: WebTestClient) {
            webClient
                .get().uri("/")
                .exchange()
                .expectStatus().isOk
                .expectBody<String>().isEqualTo("Hello World")
    

    Testing within a mocked environment is usually faster than running with a full servlet container. However, since mocking occurs at the Spring MVC layer, code that relies on lower-level servlet container behavior cannot be directly tested with MockMvc.

    For example, Spring Boot’s error handling is based on the “error page” support provided by the servlet container. This means that, whilst you can test your MVC layer throws and handles exceptions as expected, you cannot directly test that a specific custom error page is rendered. If you need to test these lower-level concerns, you can start a fully running server as described in the next section.

    8.3.7. Testing With a Running Server

    If you need to start a full running server, we recommend that you use random ports. If you use @SpringBootTest(webEnvironment=WebEnvironment.RANDOM_PORT), an available port is picked at random each time your test runs.

    The @LocalServerPort annotation can be used to inject the actual port used into your test. For convenience, tests that need to make REST calls to the started server can additionally @Autowire a WebTestClient, which resolves relative links to the running server and comes with a dedicated API for verifying responses, as shown in the following example:

    import org.junit.jupiter.api.Test;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.boot.test.context.SpringBootTest;
    import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
    import org.springframework.test.web.reactive.server.WebTestClient;
    @SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
    class MyRandomPortWebTestClientTests {
        @Test
        void exampleTest(@Autowired WebTestClient webClient) {
            webClient
                .get().uri("/")
                .exchange()
                .expectStatus().isOk()
                .expectBody(String.class).isEqualTo("Hello World");
    
    import org.junit.jupiter.api.Test
    import org.springframework.beans.factory.annotation.Autowired
    import org.springframework.boot.test.context.SpringBootTest
    import org.springframework.boot.test.context.SpringBootTest.WebEnvironment
    import org.springframework.test.web.reactive.server.WebTestClient
    import org.springframework.test.web.reactive.server.expectBody
    @SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
    class MyRandomPortWebTestClientTests {
        @Test
        fun exampleTest(@Autowired webClient: WebTestClient) {
            webClient
                .get().uri("/")
                .exchange()
                .expectStatus().isOk
                .expectBody<String>().isEqualTo("Hello World")
    

    This setup requires spring-webflux on the classpath. If you can not or will not add webflux, Spring Boot also provides a TestRestTemplate facility:

    import org.junit.jupiter.api.Test;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.boot.test.context.SpringBootTest;
    import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
    import org.springframework.boot.test.web.client.TestRestTemplate;
    import static org.assertj.core.api.Assertions.assertThat;
    @SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
    class MyRandomPortTestRestTemplateTests {
        @Test
        void exampleTest(@Autowired TestRestTemplate restTemplate) {
            String body = restTemplate.getForObject("/", String.class);
            assertThat(body).isEqualTo("Hello World");
    
    import org.assertj.core.api.Assertions.assertThat
    import org.junit.jupiter.api.Test
    import org.springframework.beans.factory.annotation.Autowired
    import org.springframework.boot.test.context.SpringBootTest
    import org.springframework.boot.test.context.SpringBootTest.WebEnvironment
    import org.springframework.boot.test.web.client.TestRestTemplate
    @SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
    class MyRandomPortTestRestTemplateTests {
        @Test
        fun exampleTest(@Autowired restTemplate: TestRestTemplate) {
            val body = restTemplate.getForObject("/", String::class.java)
            assertThat(body).isEqualTo("Hello World")
    

    8.3.8. Customizing WebTestClient

    To customize the WebTestClient bean, configure a WebTestClientBuilderCustomizer bean. Any such beans are called with the WebTestClient.Builder that is used to create the WebTestClient.

    8.3.9. Using JMX

    As the test context framework caches context, JMX is disabled by default to prevent identical components to register on the same domain. If such test needs access to an MBeanServer, consider marking it dirty as well:

    import javax.management.MBeanServer;
    import org.junit.jupiter.api.Test;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.boot.test.context.SpringBootTest;
    import org.springframework.test.annotation.DirtiesContext;
    import static org.assertj.core.api.Assertions.assertThat;
    @SpringBootTest(properties = "spring.jmx.enabled=true")
    @DirtiesContext
    class MyJmxTests {
        @Autowired
        private MBeanServer mBeanServer;
        @Test
        void exampleTest() {
            assertThat(this.mBeanServer.getDomains()).contains("java.lang");
            // ...
    import org.assertj.core.api.Assertions.assertThat
    import org.junit.jupiter.api.Test
    import org.springframework.beans.factory.annotation.Autowired
    import org.springframework.boot.test.context.SpringBootTest
    import org.springframework.test.annotation.DirtiesContext
    @SpringBootTest(properties = ["spring.jmx.enabled=true"])
    @DirtiesContext
    class MyJmxTests(@Autowired val mBeanServer: MBeanServer) {
        @Test
        fun exampleTest() {
            assertThat(mBeanServer.domains).contains("java.lang")
            // ...
    

    8.3.10. Using Metrics

    Regardless of your classpath, meter registries, except the in-memory backed, are not auto-configured when using @SpringBootTest.

    If you need to export metrics to a different backend as part of an integration test, annotate it with @AutoConfigureObservability.

    8.3.11. Using Tracing

    Regardless of your classpath, tracing is not auto-configured when using @SpringBootTest.

    If you need tracing as part of an integration test, annotate it with @AutoConfigureObservability.

    8.3.12. Mocking and Spying Beans

    When running tests, it is sometimes necessary to mock certain components within your application context. For example, you may have a facade over some remote service that is unavailable during development. Mocking can also be useful when you want to simulate failures that might be hard to trigger in a real environment.

    Spring Boot includes a @MockBean annotation that can be used to define a Mockito mock for a bean inside your ApplicationContext. You can use the annotation to add new beans or replace a single existing bean definition. The annotation can be used directly on test classes, on fields within your test, or on @Configuration classes and fields. When used on a field, the instance of the created mock is also injected. Mock beans are automatically reset after each test method.

    If your test uses one of Spring Boot’s test annotations (such as @SpringBootTest), this feature is automatically enabled. To use this feature with a different arrangement, listeners must be explicitly added, as shown in the following example:

    import org.springframework.boot.test.mock.mockito.MockitoTestExecutionListener;
    import org.springframework.boot.test.mock.mockito.ResetMocksTestExecutionListener;
    import org.springframework.test.context.ContextConfiguration;
    import org.springframework.test.context.TestExecutionListeners;
    @ContextConfiguration(classes = MyConfig.class)
    @TestExecutionListeners({ MockitoTestExecutionListener.class, ResetMocksTestExecutionListener.class })
    class MyTests {
        // ...
    
    import org.springframework.boot.test.mock.mockito.MockitoTestExecutionListener
    import org.springframework.boot.test.mock.mockito.ResetMocksTestExecutionListener
    import org.springframework.test.context.ContextConfiguration
    import org.springframework.test.context.TestExecutionListeners
    @ContextConfiguration(classes = [MyConfig::class])
    @TestExecutionListeners(
        MockitoTestExecutionListener::class,
        ResetMocksTestExecutionListener::class
    class MyTests {
        // ...
    

    The following example replaces an existing RemoteService bean with a mock implementation:

    import org.junit.jupiter.api.Test;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.boot.test.context.SpringBootTest;
    import org.springframework.boot.test.mock.mockito.MockBean;
    import static org.assertj.core.api.Assertions.assertThat;
    import static org.mockito.BDDMockito.given;
    @SpringBootTest
    class MyTests {
        @Autowired
        private Reverser reverser;
        @MockBean
        private RemoteService remoteService;
        @Test
        void exampleTest() {
            given(this.remoteService.getValue()).willReturn("spring");
            String reverse = this.reverser.getReverseValue(); // Calls injected RemoteService
            assertThat(reverse).isEqualTo("gnirps");
    
    import org.assertj.core.api.Assertions.assertThat
    import org.junit.jupiter.api.Test
    import org.mockito.BDDMockito.given
    import org.springframework.beans.factory.annotation.Autowired
    import org.springframework.boot.test.context.SpringBootTest
    import org.springframework.boot.test.mock.mockito.MockBean
    @SpringBootTest
    class MyTests(@Autowired val reverser: Reverser, @MockBean val remoteService: RemoteService) {
        @Test
        fun exampleTest() {
            given(remoteService.value).willReturn("spring")
            val reverse = reverser.reverseValue // Calls injected RemoteService
            assertThat(reverse).isEqualTo("gnirps")
    @MockBean cannot be used to mock the behavior of a bean that is exercised during application context refresh.
    By the time the test is executed, the application context refresh has completed and it is too late to configure the mocked behavior.
    We recommend using a @Bean method to create and configure the mock in this situation.
    CGLib proxies, such as those created for scoped beans, declare the proxied methods as final.
    This stops Mockito from functioning correctly as it cannot mock or spy on final methods in its default configuration.
    If you want to mock or spy on such a bean, configure Mockito to use its inline mock maker by adding org.mockito:mockito-inline to your application’s test dependencies.
    This allows Mockito to mock and spy on final methods.
    If you are using @SpyBean to spy on a bean with @Cacheable methods that refer to parameters by name, your application must be compiled with -parameters.
    This ensures that the parameter names are available to the caching infrastructure once the bean has been spied upon.
    When you are using @SpyBean to spy on a bean that is proxied by Spring, you may need to remove Spring’s proxy in some situations, for example when setting expectations using given or when.
    Use AopTestUtils.getTargetObject(yourProxiedSpy) to do so.
    

    8.3.13. Auto-configured Tests

    Spring Boot’s auto-configuration system works well for applications but can sometimes be a little too much for tests. It often helps to load only the parts of the configuration that are required to test a “slice” of your application. For example, you might want to test that Spring MVC controllers are mapping URLs correctly, and you do not want to involve database calls in those tests, or you might want to test JPA entities, and you are not interested in the web layer when those tests run.

    The spring-boot-test-autoconfigure module includes a number of annotations that can be used to automatically configure such “slices”. Each of them works in a similar way, providing a @…​Test annotation that loads the ApplicationContext and one or more @AutoConfigure…​ annotations that can be used to customize auto-configuration settings.

    Each slice restricts component scan to appropriate components and loads a very restricted set of auto-configuration classes. If you need to exclude one of them, most @…​Test annotations provide an excludeAutoConfiguration attribute. Alternatively, you can use @ImportAutoConfiguration#exclude. Including multiple “slices” by using several @…​Test annotations in one test is not supported. If you need multiple “slices”, pick one of the @…​Test annotations and include the @AutoConfigure…​ annotations of the other “slices” by hand. It is also possible to use the @AutoConfigure…​ annotations with the standard @SpringBootTest annotation. You can use this combination if you are not interested in “slicing” your application but you want some of the auto-configured test beans.

    8.3.14. Auto-configured JSON Tests

    To test that object JSON serialization and deserialization is working as expected, you can use the @JsonTest annotation. @JsonTest auto-configures the available supported JSON mapper, which can be one of the following libraries:

    If you need to configure elements of the auto-configuration, you can use the @AutoConfigureJsonTesters annotation.

    Spring Boot includes AssertJ-based helpers that work with the JSONAssert and JsonPath libraries to check that JSON appears as expected. The JacksonTester, GsonTester, JsonbTester, and BasicJsonTester classes can be used for Jackson, Gson, Jsonb, and Strings respectively. Any helper fields on the test class can be @Autowired when using @JsonTest. The following example shows a test class for Jackson:

    import org.junit.jupiter.api.Test;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.boot.test.autoconfigure.json.JsonTest;
    import org.springframework.boot.test.json.JacksonTester;
    import static org.assertj.core.api.Assertions.assertThat;
    @JsonTest
    class MyJsonTests {
        @Autowired
        private JacksonTester<VehicleDetails> json;
        @Test
        void serialize() throws Exception {
            VehicleDetails details = new VehicleDetails("Honda", "Civic");
            // Assert against a `.json` file in the same package as the test
            assertThat(this.json.write(details)).isEqualToJson("expected.json");
            // Or use JSON path based assertions
            assertThat(this.json.write(details)).hasJsonPathStringValue("@.make");
            assertThat(this.json.write(details)).extractingJsonPathStringValue("@.make").isEqualTo("Honda");
        @Test
        void deserialize() throws Exception {
            String content = "{\"make\":\"Ford\",\"model\":\"Focus\"}";
            assertThat(this.json.parse(content)).isEqualTo(new VehicleDetails("Ford", "Focus"));
            assertThat(this.json.parseObject(content).getMake()).isEqualTo("Ford");
    
    import org.assertj.core.api.Assertions.assertThat
    import org.junit.jupiter.api.Test
    import org.springframework.beans.factory.annotation.Autowired
    import org.springframework.boot.test.autoconfigure.json.JsonTest
    import org.springframework.boot.test.json.JacksonTester
    @JsonTest
    class MyJsonTests(@Autowired val json: JacksonTester<VehicleDetails>) {
        @Test
        fun serialize() {
            val details = VehicleDetails("Honda", "Civic")
            // Assert against a `.json` file in the same package as the test
            assertThat(json.write(details)).isEqualToJson("expected.json")
            // Or use JSON path based assertions
            assertThat(json.write(details)).hasJsonPathStringValue("@.make")
            assertThat(json.write(details)).extractingJsonPathStringValue("@.make").isEqualTo("Honda")
        @Test
        fun deserialize() {
            val content = "{\"make\":\"Ford\",\"model\":\"Focus\"}"
            assertThat(json.parse(content)).isEqualTo(VehicleDetails("Ford", "Focus"))
            assertThat(json.parseObject(content).make).isEqualTo("Ford")
    

    If you use Spring Boot’s AssertJ-based helpers to assert on a number value at a given JSON path, you might not be able to use isEqualTo depending on the type. Instead, you can use AssertJ’s satisfies to assert that the value matches the given condition. For instance, the following example asserts that the actual number is a float value close to 0.15 within an offset of 0.01.

    @Test
    void someTest() throws Exception {
        SomeObject value = new SomeObject(0.152f);
        assertThat(this.json.write(value)).extractingJsonPathNumberValue("@.test.numberValue")
            .satisfies((number) -> assertThat(number.floatValue()).isCloseTo(0.15f, within(0.01f)));
    fun someTest() {
        val value = SomeObject(0.152f)
        assertThat(json.write(value)).extractingJsonPathNumberValue("@.test.numberValue")
            .satisfies(ThrowingConsumer { number ->
                assertThat(number.toFloat()).isCloseTo(0.15f, within(0.01f))
    

    8.3.15. Auto-configured Spring MVC Tests

    To test whether Spring MVC controllers are working as expected, use the @WebMvcTest annotation. @WebMvcTest auto-configures the Spring MVC infrastructure and limits scanned beans to @Controller, @ControllerAdvice, @JsonComponent, Converter, GenericConverter, Filter, HandlerInterceptor, WebMvcConfigurer, WebMvcRegistrations, and HandlerMethodArgumentResolver. Regular @Component and @ConfigurationProperties beans are not scanned when the @WebMvcTest annotation is used. @EnableConfigurationProperties can be used to include @ConfigurationProperties beans.

    Often, @WebMvcTest is limited to a single controller and is used in combination with @MockBean to provide mock implementations for required collaborators.

    @WebMvcTest also auto-configures MockMvc. Mock MVC offers a powerful way to quickly test MVC controllers without needing to start a full HTTP server.

    You can also auto-configure MockMvc in a non-@WebMvcTest (such as @SpringBootTest) by annotating it with @AutoConfigureMockMvc. The following example uses MockMvc:
    import org.junit.jupiter.api.Test;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
    import org.springframework.boot.test.mock.mockito.MockBean;
    import org.springframework.http.MediaType;
    import org.springframework.test.web.servlet.MockMvc;
    import static org.mockito.BDDMockito.given;
    import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
    import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
    import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
    @WebMvcTest(UserVehicleController.class)
    class MyControllerTests {
        @Autowired
        private MockMvc mvc;
        @MockBean
        private UserVehicleService userVehicleService;
        @Test
        void testExample() throws Exception {
            given(this.userVehicleService.getVehicleDetails("sboot"))
                .willReturn(new VehicleDetails("Honda", "Civic"));
            this.mvc.perform(get("/sboot/vehicle").accept(MediaType.TEXT_PLAIN))
                .andExpect(status().isOk())
                .andExpect(content().string("Honda Civic"));
    
    import org.junit.jupiter.api.Test
    import org.mockito.BDDMockito.given
    import org.springframework.beans.factory.annotation.Autowired
    import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest
    import org.springframework.boot.test.mock.mockito.MockBean
    import org.springframework.http.MediaType
    import org.springframework.test.web.servlet.MockMvc
    import org.springframework.test.web.servlet.request.MockMvcRequestBuilders
    import org.springframework.test.web.servlet.result.MockMvcResultMatchers
    @WebMvcTest(UserVehicleController::class)
    class MyControllerTests(@Autowired val mvc: MockMvc) {
        @MockBean
        lateinit var userVehicleService: UserVehicleService
        @Test
        fun testExample() {
            given(userVehicleService.getVehicleDetails("sboot"))
                .willReturn(VehicleDetails("Honda", "Civic"))
            mvc.perform(MockMvcRequestBuilders.get("/sboot/vehicle").accept(MediaType.TEXT_PLAIN))
                .andExpect(MockMvcResultMatchers.status().isOk)
                .andExpect(MockMvcResultMatchers.content().string("Honda Civic"))
    

    If you use HtmlUnit and Selenium, auto-configuration also provides an HtmlUnit WebClient bean and/or a Selenium WebDriver bean. The following example uses HtmlUnit:

    import com.gargoylesoftware.htmlunit.WebClient;
    import com.gargoylesoftware.htmlunit.html.HtmlPage;
    import org.junit.jupiter.api.Test;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
    import org.springframework.boot.test.mock.mockito.MockBean;
    import static org.assertj.core.api.Assertions.assertThat;
    import static org.mockito.BDDMockito.given;
    @WebMvcTest(UserVehicleController.class)
    class MyHtmlUnitTests {
        @Autowired
        private WebClient webClient;
        @MockBean
        private UserVehicleService userVehicleService;
        @Test
        void testExample() throws Exception {
            given(this.userVehicleService.getVehicleDetails("sboot")).willReturn(new VehicleDetails("Honda", "Civic"));
            HtmlPage page = this.webClient.getPage("/sboot/vehicle.html");
            assertThat(page.getBody().getTextContent()).isEqualTo("Honda Civic");
    
    import com.gargoylesoftware.htmlunit.WebClient
    import com.gargoylesoftware.htmlunit.html.HtmlPage
    import org.assertj.core.api.Assertions.assertThat
    import org.junit.jupiter.api.Test
    import org.mockito.BDDMockito.given
    import org.springframework.beans.factory.annotation.Autowired
    import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest
    import org.springframework.boot.test.mock.mockito.MockBean
    @WebMvcTest(UserVehicleController::class)
    class MyHtmlUnitTests(@Autowired val webClient: WebClient) {
        @MockBean
        lateinit var userVehicleService: UserVehicleService
        @Test
        fun testExample() {
            given(userVehicleService.getVehicleDetails("sboot")).willReturn(VehicleDetails("Honda", "Civic"))
            val page = webClient.getPage<HtmlPage>("/sboot/vehicle.html")
            assertThat(page.body.textContent).isEqualTo("Honda Civic")
    By default, Spring Boot puts WebDriver beans in a special “scope” to ensure that the driver exits after each test and that a new instance is injected.
    If you do not want this behavior, you can add @Scope("singleton") to your WebDriver @Bean definition.
    The webDriver scope created by Spring Boot will replace any user defined scope of the same name.
    If you define your own webDriver scope you may find it stops working when you use @WebMvcTest.
    

    If you have Spring Security on the classpath, @WebMvcTest will also scan WebSecurityConfigurer beans. Instead of disabling security completely for such tests, you can use Spring Security’s test support. More details on how to use Spring Security’s MockMvc support can be found in this howto.html how-to section.

    8.3.16. Auto-configured Spring WebFlux Tests

    To test that Spring WebFlux controllers are working as expected, you can use the @WebFluxTest annotation. @WebFluxTest auto-configures the Spring WebFlux infrastructure and limits scanned beans to @Controller, @ControllerAdvice, @JsonComponent, Converter, GenericConverter, WebFilter, and WebFluxConfigurer. Regular @Component and @ConfigurationProperties beans are not scanned when the @WebFluxTest annotation is used. @EnableConfigurationProperties can be used to include @ConfigurationProperties beans.

    Often, @WebFluxTest is limited to a single controller and used in combination with the @MockBean annotation to provide mock implementations for required collaborators.

    @WebFluxTest also auto-configures WebTestClient, which offers a powerful way to quickly test WebFlux controllers without needing to start a full HTTP server.

    You can also auto-configure WebTestClient in a non-@WebFluxTest (such as @SpringBootTest) by annotating it with @AutoConfigureWebTestClient. The following example shows a class that uses both @WebFluxTest and a WebTestClient:
    import org.junit.jupiter.api.Test;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.boot.test.autoconfigure.web.reactive.WebFluxTest;
    import org.springframework.boot.test.mock.mockito.MockBean;
    import org.springframework.http.MediaType;
    import org.springframework.test.web.reactive.server.WebTestClient;
    import static org.mockito.BDDMockito.given;
    @WebFluxTest(UserVehicleController.class)
    class MyControllerTests {
        @Autowired
        private WebTestClient webClient;
        @MockBean
        private UserVehicleService userVehicleService;
        @Test
        void testExample() {
            given(this.userVehicleService.getVehicleDetails("sboot"))
                .willReturn(new VehicleDetails("Honda", "Civic"));
            this.webClient.get().uri("/sboot/vehicle").accept(MediaType.TEXT_PLAIN).exchange()
                .expectStatus().isOk()
                .expectBody(String.class).isEqualTo("Honda Civic");
    
    import org.junit.jupiter.api.Test
    import org.mockito.BDDMockito.given
    import org.springframework.beans.factory.annotation.Autowired
    import org.springframework.boot.test.autoconfigure.web.reactive.WebFluxTest
    import org.springframework.boot.test.mock.mockito.MockBean
    import org.springframework.http.MediaType
    import org.springframework.test.web.reactive.server.WebTestClient
    import org.springframework.test.web.reactive.server.expectBody
    @WebFluxTest(UserVehicleController::class)
    class MyControllerTests(@Autowired val webClient: WebTestClient) {
        @MockBean
        lateinit var userVehicleService: UserVehicleService
        @Test
        fun testExample() {
            given(userVehicleService.getVehicleDetails("sboot"))
                .willReturn(VehicleDetails("Honda", "Civic"))
            webClient.get().uri("/sboot/vehicle").accept(MediaType.TEXT_PLAIN).exchange()
                .expectStatus().isOk
                .expectBody<String>().isEqualTo("Honda Civic")
    @WebFluxTest cannot detect custom security configuration registered as a @Bean of type SecurityWebFilterChain.
    To include that in your test, you will need to import the configuration that registers the bean by using @Import or by using @SpringBootTest.
    

    8.3.17. Auto-configured Spring GraphQL Tests

    Spring GraphQL offers a dedicated testing support module; you’ll need to add it to your project:

    Maven
    <dependencies>
      <dependency>
        <groupId>org.springframework.graphql</groupId>
        <artifactId>spring-graphql-test</artifactId>
        <scope>test</scope>
      </dependency>
      <!-- Unless already present in the compile scope -->
      <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-webflux</artifactId>
        <scope>test</scope>
      </dependency>
    </dependencies>
    Gradle
    dependencies {
      testImplementation("org.springframework.graphql:spring-graphql-test")
      // Unless already present in the implementation configuration
      testImplementation("org.springframework.boot:spring-boot-starter-webflux")
    

    This testing module ships the GraphQlTester. The tester is heavily used in test, so be sure to become familiar with using it. There are GraphQlTester variants and Spring Boot will auto-configure them depending on the type of tests:

    the ExecutionGraphQlServiceTester performs tests on the server side, without a client nor a transport

    the HttpGraphQlTester performs tests with a client that connects to a server, with or without a live server

    Spring Boot helps you to test your Spring GraphQL Controllers with the @GraphQlTest annotation. @GraphQlTest auto-configures the Spring GraphQL infrastructure, without any transport nor server being involved. This limits scanned beans to @Controller, RuntimeWiringConfigurer, JsonComponent, Converter, GenericConverter, DataFetcherExceptionResolver, Instrumentation and GraphQlSourceBuilderCustomizer. Regular @Component and @ConfigurationProperties beans are not scanned when the @GraphQlTest annotation is used. @EnableConfigurationProperties can be used to include @ConfigurationProperties beans.

    Often, @GraphQlTest is limited to a set of controllers and used in combination with the @MockBean annotation to provide mock implementations for required collaborators.

    import org.junit.jupiter.api.Test;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.boot.docs.web.graphql.runtimewiring.GreetingController;
    import org.springframework.boot.test.autoconfigure.graphql.GraphQlTest;
    import org.springframework.graphql.test.tester.GraphQlTester;
    @GraphQlTest(GreetingController.class)
    class GreetingControllerTests {
        @Autowired
        private GraphQlTester graphQlTester;
        @Test
        void shouldGreetWithSpecificName() {
            this.graphQlTester.document("{ greeting(name: \"Alice\") } ")
                .execute()
                .path("greeting")
                .entity(String.class)
                .isEqualTo("Hello, Alice!");
        @Test
        void shouldGreetWithDefaultName() {
            this.graphQlTester.document("{ greeting } ")
                .execute()
                .path("greeting")
                .entity(String.class)
                .isEqualTo("Hello, Spring!");
    
    import org.junit.jupiter.api.Test
    import org.springframework.beans.factory.annotation.Autowired
    import org.springframework.boot.docs.web.graphql.runtimewiring.GreetingController
    import org.springframework.boot.test.autoconfigure.graphql.GraphQlTest
    import org.springframework.graphql.test.tester.GraphQlTester
    @GraphQlTest(GreetingController::class)
    internal class GreetingControllerTests {
        @Autowired
        lateinit var graphQlTester: GraphQlTester
        @Test
        fun shouldGreetWithSpecificName() {
            graphQlTester.document("{ greeting(name: \"Alice\") } ").execute().path("greeting").entity(String::class.java)
                    .isEqualTo("Hello, Alice!")
        @Test
        fun shouldGreetWithDefaultName() {
            graphQlTester.document("{ greeting } ").execute().path("greeting").entity(String::class.java)
                    .isEqualTo("Hello, Spring!")
    

    @SpringBootTest tests are full integration tests and involve the entire application. When using a random or defined port, a live server is configured and an HttpGraphQlTester bean is contributed automatically so you can use it to test your server. When a MOCK environment is configured, you can also request an HttpGraphQlTester bean by annotating your test class with @AutoConfigureHttpGraphQlTester:

    import org.junit.jupiter.api.Test;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.boot.test.autoconfigure.graphql.tester.AutoConfigureHttpGraphQlTester;
    import org.springframework.boot.test.context.SpringBootTest;
    import org.springframework.graphql.test.tester.HttpGraphQlTester;
    @AutoConfigureHttpGraphQlTester
    @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.MOCK)
    class GraphQlIntegrationTests {
        @Test
        void shouldGreetWithSpecificName(@Autowired HttpGraphQlTester graphQlTester) {
            HttpGraphQlTester authenticatedTester = graphQlTester.mutate()
                .webTestClient((client) -> client.defaultHeaders((headers) -> headers.setBasicAuth("admin", "ilovespring")))
                .build();
            authenticatedTester.document("{ greeting(name: \"Alice\") } ")
                .execute()
                .path("greeting")
                .entity(String.class)
                .isEqualTo("Hello, Alice!");
    
    import org.junit.jupiter.api.Test
    import org.springframework.beans.factory.annotation.Autowired
    import org.springframework.boot.test.autoconfigure.graphql.tester.AutoConfigureHttpGraphQlTester
    import org.springframework.boot.test.context.SpringBootTest
    import org.springframework.graphql.test.tester.HttpGraphQlTester
    import org.springframework.http.HttpHeaders
    import org.springframework.test.web.reactive.server.WebTestClient
    @AutoConfigureHttpGraphQlTester
    @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.MOCK)
    class GraphQlIntegrationTests {
        @Test
        fun shouldGreetWithSpecificName(@Autowired graphQlTester: HttpGraphQlTester) {
            val authenticatedTester = graphQlTester.mutate()
                .webTestClient { client: WebTestClient.Builder ->
                    client.defaultHeaders { headers: HttpHeaders ->
                        headers.setBasicAuth("admin", "ilovespring")
                }.build()
            authenticatedTester.document("{ greeting(name: \"Alice\") } ").execute()
                .path("greeting").entity(String::class.java).isEqualTo("Hello, Alice!")
    

    8.3.18. Auto-configured Data Cassandra Tests

    You can use @DataCassandraTest to test Cassandra applications. By default, it configures a CassandraTemplate, scans for @Table classes, and configures Spring Data Cassandra repositories. Regular @Component and @ConfigurationProperties beans are not scanned when the @DataCassandraTest annotation is used. @EnableConfigurationProperties can be used to include @ConfigurationProperties beans. (For more about using Cassandra with Spring Boot, see "data.html".)

    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.boot.test.autoconfigure.data.cassandra.DataCassandraTest;
    @DataCassandraTest
    class MyDataCassandraTests {
        @Autowired
        private SomeRepository repository;
    
    import org.springframework.beans.factory.annotation.Autowired
    import org.springframework.boot.test.autoconfigure.data.cassandra.DataCassandraTest
    @DataCassandraTest
    class MyDataCassandraTests(@Autowired val repository: SomeRepository)
    

    8.3.19. Auto-configured Data Couchbase Tests

    You can use @DataCouchbaseTest to test Couchbase applications. By default, it configures a CouchbaseTemplate or ReactiveCouchbaseTemplate, scans for @Document classes, and configures Spring Data Couchbase repositories. Regular @Component and @ConfigurationProperties beans are not scanned when the @DataCouchbaseTest annotation is used. @EnableConfigurationProperties can be used to include @ConfigurationProperties beans. (For more about using Couchbase with Spring Boot, see "data.html", earlier in this chapter.)

    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.boot.test.autoconfigure.data.couchbase.DataCouchbaseTest;
    @DataCouchbaseTest
    class MyDataCouchbaseTests {
        @Autowired
        private SomeRepository repository;
        // ...
    
    import org.springframework.beans.factory.annotation.Autowired
    import org.springframework.boot.test.autoconfigure.data.couchbase.DataCouchbaseTest
    @DataCouchbaseTest
    class MyDataCouchbaseTests(@Autowired val repository: SomeRepository) {
        // ...
    

    8.3.20. Auto-configured Data Elasticsearch Tests

    You can use @DataElasticsearchTest to test Elasticsearch applications. By default, it configures an ElasticsearchRestTemplate, scans for @Document classes, and configures Spring Data Elasticsearch repositories. Regular @Component and @ConfigurationProperties beans are not scanned when the @DataElasticsearchTest annotation is used. @EnableConfigurationProperties can be used to include @ConfigurationProperties beans. (For more about using Elasticsearch with Spring Boot, see "data.html", earlier in this chapter.)

    The following example shows a typical setup for using Elasticsearch tests in Spring Boot:

    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.boot.test.autoconfigure.data.elasticsearch.DataElasticsearchTest;
    @DataElasticsearchTest
    class MyDataElasticsearchTests {
        @Autowired
        private SomeRepository repository;
        // ...
    
    import org.springframework.beans.factory.annotation.Autowired
    import org.springframework.boot.test.autoconfigure.data.elasticsearch.DataElasticsearchTest
    @DataElasticsearchTest
    class MyDataElasticsearchTests(@Autowired val repository: SomeRepository) {
        // ...
    

    8.3.21. Auto-configured Data JPA Tests

    You can use the @DataJpaTest annotation to test JPA applications. By default, it scans for @Entity classes and configures Spring Data JPA repositories. If an embedded database is available on the classpath, it configures one as well. SQL queries are logged by default by setting the spring.jpa.show-sql property to true. This can be disabled using the showSql attribute of the annotation.

    Regular @Component and @ConfigurationProperties beans are not scanned when the @DataJpaTest annotation is used. @EnableConfigurationProperties can be used to include @ConfigurationProperties beans.

    By default, data JPA tests are transactional and roll back at the end of each test. See the relevant section in the Spring Framework Reference Documentation for more details. If that is not what you want, you can disable transaction management for a test or for the whole class as follows:

    import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;
    import org.springframework.transaction.annotation.Propagation;
    import org.springframework.transaction.annotation.Transactional;
    @DataJpaTest
    @Transactional(propagation = Propagation.NOT_SUPPORTED)
    class MyNonTransactionalTests {
        // ...
    
    import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest
    import org.springframework.transaction.annotation.Propagation
    import org.springframework.transaction.annotation.Transactional
    @DataJpaTest
    @Transactional(propagation = Propagation.NOT_SUPPORTED)
    class MyNonTransactionalTests {
        // ...
    TestEntityManager can also be auto-configured to any of your Spring-based test class by adding @AutoConfigureTestEntityManager.
    When doing so, make sure that your test is running in a transaction, for instance by adding  @Transactional on your test class or method.
    

    A JdbcTemplate is also available if you need that. The following example shows the @DataJpaTest annotation in use:

    import org.junit.jupiter.api.Test;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;
    import org.springframework.boot.test.autoconfigure.orm.jpa.TestEntityManager;
    import static org.assertj.core.api.Assertions.assertThat;
    @DataJpaTest
    class MyRepositoryTests {
        @Autowired
        private TestEntityManager entityManager;
        @Autowired
        private UserRepository repository;
        @Test
        void testExample() {
            this.entityManager.persist(new User("sboot", "1234"));
            User user = this.repository.findByUsername("sboot");
            assertThat(user.getUsername()).isEqualTo("sboot");
            assertThat(user.getEmployeeNumber()).isEqualTo("1234");
    
    import org.assertj.core.api.Assertions.assertThat
    import org.junit.jupiter.api.Test
    import org.springframework.beans.factory.annotation.Autowired
    import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest
    import org.springframework.boot.test.autoconfigure.orm.jpa.TestEntityManager
    @DataJpaTest
    class MyRepositoryTests(@Autowired val entityManager: TestEntityManager, @Autowired val repository: UserRepository) {
        @Test
        fun testExample() {
            entityManager.persist(User("sboot", "1234"))
            val user = repository.findByUsername("sboot")
            assertThat(user?.username).isEqualTo("sboot")
            assertThat(user?.employeeNumber).isEqualTo("1234")
    

    In-memory embedded databases generally work well for tests, since they are fast and do not require any installation. If, however, you prefer to run tests against a real database you can use the @AutoConfigureTestDatabase annotation, as shown in the following example:

    import org.springframework.boot.test.autoconfigure.jdbc.AutoConfigureTestDatabase;
    import org.springframework.boot.test.autoconfigure.jdbc.AutoConfigureTestDatabase.Replace;
    import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;
    @DataJpaTest
    @AutoConfigureTestDatabase(replace = Replace.NONE)
    class MyRepositoryTests {
        // ...
    
    import org.springframework.boot.test.autoconfigure.jdbc.AutoConfigureTestDatabase
    import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest
    @DataJpaTest
    @AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE)
    class MyRepositoryTests {
        // ...
    

    8.3.22. Auto-configured JDBC Tests

    @JdbcTest is similar to @DataJpaTest but is for tests that only require a DataSource and do not use Spring Data JDBC. By default, it configures an in-memory embedded database and a JdbcTemplate. Regular @Component and @ConfigurationProperties beans are not scanned when the @JdbcTest annotation is used. @EnableConfigurationProperties can be used to include @ConfigurationProperties beans.

    By default, JDBC tests are transactional and roll back at the end of each test. See the relevant section in the Spring Framework Reference Documentation for more details. If that is not what you want, you can disable transaction management for a test or for the whole class, as follows:

    import org.springframework.boot.test.autoconfigure.jdbc.JdbcTest;
    import org.springframework.transaction.annotation.Propagation;
    import org.springframework.transaction.annotation.Transactional;
    @JdbcTest
    @Transactional(propagation = Propagation.NOT_SUPPORTED)
    class MyTransactionalTests {
    
    import org.springframework.boot.test.autoconfigure.jdbc.JdbcTest
    import org.springframework.transaction.annotation.Propagation
    import org.springframework.transaction.annotation.Transactional
    @JdbcTest
    @Transactional(propagation = Propagation.NOT_SUPPORTED)
    class MyTransactionalTests
    

    If you prefer your test to run against a real database, you can use the @AutoConfigureTestDatabase annotation in the same way as for DataJpaTest. (See "Auto-configured Data JPA Tests".)

    8.3.23. Auto-configured Data JDBC Tests

    @DataJdbcTest is similar to @JdbcTest but is for tests that use Spring Data JDBC repositories. By default, it configures an in-memory embedded database, a JdbcTemplate, and Spring Data JDBC repositories. Only AbstractJdbcConfiguration subclasses are scanned when the @DataJdbcTest annotation is used, regular @Component and @ConfigurationProperties beans are not scanned. @EnableConfigurationProperties can be used to include @ConfigurationProperties beans.

    By default, Data JDBC tests are transactional and roll back at the end of each test. See the relevant section in the Spring Framework Reference Documentation for more details. If that is not what you want, you can disable transaction management for a test or for the whole test class as shown in the JDBC example.

    If you prefer your test to run against a real database, you can use the @AutoConfigureTestDatabase annotation in the same way as for DataJpaTest. (See "Auto-configured Data JPA Tests".)

    8.3.24. Auto-configured jOOQ Tests

    You can use @JooqTest in a similar fashion as @JdbcTest but for jOOQ-related tests. As jOOQ relies heavily on a Java-based schema that corresponds with the database schema, the existing DataSource is used. If you want to replace it with an in-memory database, you can use @AutoConfigureTestDatabase to override those settings. (For more about using jOOQ with Spring Boot, see "data.html".) Regular @Component and @ConfigurationProperties beans are not scanned when the @JooqTest annotation is used. @EnableConfigurationProperties can be used to include @ConfigurationProperties beans.

    @JooqTest configures a DSLContext. The following example shows the @JooqTest annotation in use:

    import org.jooq.DSLContext;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.boot.test.autoconfigure.jooq.JooqTest;
    @JooqTest
    class MyJooqTests {
        @Autowired
        private DSLContext dslContext;
        // ...
    
    import org.jooq.DSLContext
    import org.springframework.beans.factory.annotation.Autowired
    import org.springframework.boot.test.autoconfigure.jooq.JooqTest
    @JooqTest
    class MyJooqTests(@Autowired val dslContext: DSLContext) {
        // ...
    

    8.3.25. Auto-configured Data MongoDB Tests

    You can use @DataMongoTest to test MongoDB applications. By default, it configures a MongoTemplate, scans for @Document classes, and configures Spring Data MongoDB repositories. Regular @Component and @ConfigurationProperties beans are not scanned when the @DataMongoTest annotation is used. @EnableConfigurationProperties can be used to include @ConfigurationProperties beans. (For more about using MongoDB with Spring Boot, see "data.html".)

    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.boot.test.autoconfigure.data.mongo.DataMongoTest;
    import org.springframework.data.mongodb.core.MongoTemplate;
    @DataMongoTest
    class MyDataMongoDbTests {
        @Autowired
        private MongoTemplate mongoTemplate;
        // ...
    
    import org.springframework.beans.factory.annotation.Autowired
    import org.springframework.boot.test.autoconfigure.data.mongo.DataMongoTest
    import org.springframework.data.mongodb.core.MongoTemplate
    @DataMongoTest
    class MyDataMongoDbTests(@Autowired val mongoTemplate: MongoTemplate) {
        // ...
    

    8.3.26. Auto-configured Data Neo4j Tests

    You can use @DataNeo4jTest to test Neo4j applications. By default, it scans for @Node classes, and configures Spring Data Neo4j repositories. Regular @Component and @ConfigurationProperties beans are not scanned when the @DataNeo4jTest annotation is used. @EnableConfigurationProperties can be used to include @ConfigurationProperties beans. (For more about using Neo4J with Spring Boot, see "data.html".)

    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.boot.test.autoconfigure.data.neo4j.DataNeo4jTest;
    @DataNeo4jTest
    class MyDataNeo4jTests {
        @Autowired
        private SomeRepository repository;
        // ...
    
    import org.springframework.beans.factory.annotation.Autowired
    import org.springframework.boot.test.autoconfigure.data.neo4j.DataNeo4jTest
    @DataNeo4jTest
    class MyDataNeo4jTests(@Autowired val repository: SomeRepository) {
        // ...