On this page
Spring Boot Features
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.html" and "using-spring-boot.html" sections, so that you have a good grounding of the basics.
1. SpringApplication
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:
public static void main(String[] args) {
SpringApplication.run(MySpringConfiguration.class, args);
}
When your application starts, you should see something similar to the following output:
. ____ _ __ _ _
/\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
\\/ ___)| |_)| | | | | || (_| | ) ) ) )
' |____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/
:: Spring Boot :: v2.4.6
2019-04-31 13:09:54.117 INFO 56603 --- [ main] o.s.b.s.app.SampleApplication : Starting SampleApplication v0.1.0 on mycomputer with PID 56603 (/apps/myapp.jar started by pwebb)
2019-04-31 13:09:54.166 INFO 56603 --- [ main] ationConfigServletWebServerApplicationContext : Refreshing org.springframework.boot.web.ser[email protected] 6e5a8246: startup date [Wed Jul 31 00:08:16 PDT 2013]; root of context hierarchy
2019-04-01 13:09:56.912 INFO 41370 --- [ main] .t.TomcatServletWebServerFactory : Server initialized with port: 8080
2019-04-01 13:09:57.501 INFO 41370 --- [ main] o.s.b.s.app.SampleApplication : Started SampleApplication in 2.992 seconds (JVM running for 3.658)
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.
To add additional logging during startup, you can override logStartupInfo(boolean) in a subclass of SpringApplication . |
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's listening on port 8080 or configure this application to listen on another port.
Spring Boot provides numerous FailureAnalyzer implementations, and you can add your own. |
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:
spring.main.lazy-initialization=true
spring:
main:
lazy-initialization: true
If you want to disable lazy initialization for certain beans while using lazy initialization for the rest of the application, you can explicitly set their lazy attribute to false using the @Lazy(false) annotation. |
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
. In addition to a text file, you can also add a banner.gif
, banner.jpg
, or banner.png
image file to your classpath or set the spring.banner.image.location
property. Images are converted into an ASCII art representation and printed above any text banner.
Inside your banner.txt
file, you can use any of the following placeholders:
Variable | Description |
---|---|
|
The version number of your application, as declared in |
|
The version number of your application, as declared in |
|
The Spring Boot version that you are using. For example |
|
The Spring Boot version that you are using, formatted for display (surrounded with brackets and prefixed with |
|
Where |
|
The title of your application, as declared in |
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 This is why we recommend that you always launch unpacked jars using |
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:
public static void main(String[] args) {
SpringApplication app = new SpringApplication(MySpringConfiguration.class);
app.setBannerMode(Banner.Mode.OFF);
app.run(args);
}
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 references to XML configuration or to packages that should be scanned. |
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’s 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’s 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.
Tasks expected to run during startup should be executed by CommandLineRunner and ApplicationRunner components instead of using Spring component lifecycle callbacks such as @PostConstruct . |
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:
@Component
public class ReadinessStateExporter {
@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;
}
}
}
We can also update the state of the application, when the application breaks and cannot recover:
@Component
public class LocalCacheVerifier {
private final ApplicationEventPublisher eventPublisher;
public LocalCacheVerifier(ApplicationEventPublisher eventPublisher) {
this.eventPublisher = eventPublisher;
}
public void checkLocalCache() {
try {
//...
}
catch (CacheCompletelyBrokenException ex) {
AvailabilityChangeEvent.publish(this.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.
1.7. Application Events and Listeners
In addition to the usual Spring Framework events, such as ContextRefreshedEvent
, a SpringApplication
sends some additional application events.
Some events are actually triggered before the If you want those listeners to be registered automatically, regardless of the way the application is created, you can add a
|
Application events are sent in the following order, as your application runs:
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 theEnvironment
to be used in the context is known but before the context is created.An
ApplicationContextInitializedEvent
is sent when theApplicationContext
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 withLivenessState.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 withReadinessState.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 SpringApplicationEvent
s 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 theWebServer
is ready.ServletWebServerInitializedEvent
andReactiveWebServerInitializedEvent
are the servlet and reactive variants respectively.A
ContextRefreshedEvent
is sent when anApplicationContext
is refreshed.
You often need not use application events, but it can be handy to know that they exist. Internally, Spring Boot uses events to handle a variety of tasks. |
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 present, an
AnnotationConfigServletWebServerApplicationContext
is usedIf Spring MVC is not present and Spring WebFlux is present, an
AnnotationConfigReactiveWebServerApplicationContext
is usedOtherwise,
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 setApplicationContextClass(…)
.
It is often desirable to call setWebApplicationType(WebApplicationType.NONE) when using SpringApplication within a JUnit test. |
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 org.springframework.boot.*;
import org.springframework.beans.factory.annotation.*;
import org.springframework.stereotype.*;
@Component
public class MyBean {
@Autowired
public MyBean(ApplicationArguments args) {
boolean debug = args.containsOption("debug");
List<String> files = args.getNonOptionArgs();
// if run with "--debug logfile.txt" debug=true, files=["logfile.txt"]
}
}
Spring Boot also registers a CommandLinePropertySource with the Spring Environment . This lets you also inject single application arguments by using the @Value annotation. |
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.
This contract is well suited for tasks that should run after application startup but before it starts accepting traffic. |
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.*;
import org.springframework.stereotype.*;
@Component
public class MyBean implements CommandLineRunner {
public void run(String... args) {
// Do something...
}
}
If several CommandLineRunner
or ApplicationRunner
beans are defined that must be called in a specific order, you can additionally implement the org.springframework.core.Ordered
interface or use the org.springframework.core.annotation.Order
annotation.
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:
@SpringBootApplication
public class ExitCodeApplication {
@Bean
public ExitCodeGenerator exitCodeGenerator() {
return () -> 42;
}
public static void main(String[] args) {
System.exit(SpringApplication.exit(SpringApplication.run(ExitCodeApplication.class, 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.
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.
If you want to know on which HTTP port the application is running, get the property with a key of local.server.port . |
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
s . 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:
public static void main(String[] args) {
SpringApplication app = new SpringApplication(MySpringConfiguration.class);
app.setApplicationStartup(new BufferingApplicationStartup(2048));
app.run(args);
}
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. Additionally, Spring Boot Actuator will expose a startup
endpoint to expose this information as a JSON document .
2. Externalized Configuration
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, include 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. Properties are considered in the following order (with values from lower items overriding earlier ones):
Default properties (specified by setting
SpringApplication.setDefaultProperties
).@PropertySource
annotations on your@Configuration
classes. Please note that such property sources are not added to theEnvironment
until the application context is being refreshed. This is too late to configure certain properties such aslogging.*
andspring.main.*
which are read before refresh begins.Config data (such as
application.properties
files)A
RandomValuePropertySource
that has properties only inrandom.*
.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.
Config data files are considered in the following order:
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).
It is recommended to stick with one format for your entire application. If you have configuration files with both .properties and .yml format in the same location, .properties takes precedence. |
To provide a concrete example, suppose you develop a @Component
that uses a name
property, as shown in the following example:
import org.springframework.stereotype.*;
import org.springframework.beans.factory.annotation.*;
@Component
public class MyBean {
@Value("${name}")
private String name;
// ...
}
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='{"acme":{"name":"test"}}' java -jar myapp.jar
In the preceding example, you end up with acme.name=test
in the Spring Environment
.
The same JSON can also be provided as a system property:
$ java -Dspring.application.json='{"acme":{"name":"test"}}' -jar myapp.jar
Or you could supply the JSON by using a command line argument:
$ java -jar myapp.jar --spring.application.json='{"acme":{"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. |
2.3. External Application Properties
Spring Boot will automatically find and load application.properties
and application.yaml
files from the following locations when your application starts:
The classpath root
The classpath
/config
packageThe current directory
The
/config
subdirectory in the current directoryImmediate child directories of the
/config
subdirectory
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. You can also refer to an explicit location by using the spring.config.location
environment property (which is a comma-separated list of directory locations or file paths). The following example shows how to specify a different file name:
$ java -jar myproject.jar --spring.config.name=myproject
The following example shows how to specify two locations:
$ java -jar myproject.jar --spring.config.location=optional:classpath:/default.properties,optional:classpath:/override.properties
Use the prefix optional: if the locations are optional and you don’t mind if they don’t exist. |
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 used as-is. Whether specified directly or contained in a directory, configuration files must include a file extension in their name. Typical extensions that are supported out-of-the-box are .properties
, .yaml
, and .yml
.
When multiple locations are specified, the later ones can override the values of earlier ones.
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:
optional:classpath:custom-config/
optional:file:./custom-config/
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:
optional:classpath:/
optional:classpath:/config/
optional:file:./
optional:file:./config/
optional:file:./config/*/
optional:classpath:custom-config/
optional:file:./custom-config/
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. |
If your application runs in a servlet container or application server, then JNDI properties (in java:comp/env ) or servlet context initialization parameters can be used instead of, or as well as, environment variables or system properties. |
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 don’t mind if it doesn’t 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. |
Wildcard locations only work with external directories. You cannot use a wildcard in a classpath: location. |
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 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.
Properties files are only ever loaded once. If you’ve already directly imported a profile specific property files then it won’t be imported a second time. |
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:
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 doesn’t matter. For instance, the two examples below produce the same result:
spring.config.import=my.properties
my.property=value
spring:
config:
import: my.properties
my:
property: value
my.property=value
spring.config.import=my.properties
my:
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’s 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 |
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:
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’s 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 use:
A single file contains a complete set of properties (usually written as YAML).
Multiple files are written to a directory tree, with the filename becoming the ‘key’ and the contents becoming the ‘value’.
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:
etc/
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:
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.
Configuration tree values can be bound to both string String and byte[] types depending on the contents expected. |
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:
etc/
config/
dbconfig/
db/
username
password
mqconfig/
mq/
username
password
You can use configtree:/etc/config/*/
as the import location:
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.
Directories loaded using a wildcard are sorted alphabetically. If you need a different order, then you should list each location as a separate import |
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:
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). The standard ${name}
property-placeholder syntax can be used anywhere within a value.
For example, the following file will set app.description
to “MyApp is a Spring Boot application”:
app.name=MyApp
app.description=${app.name} is a Spring Boot application
app:
name: "MyApp"
description: "${app.name} is a Spring Boot application"
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.config.activate.on-cloud-platform: kubernetes
spring.application.name: MyCloudApp
For application.properties
files a special #---
comment is used to mark the document splits:
spring.application.name=MyApp
#---
spring.config.activate.on-cloud-platform=kubernetes
spring.application.name=MyCloudApp
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 comments. |
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. |
Multi-document property files cannot be loaded by using the @PropertySource or @TestPropertySource annotations. |
2.3.9. Activation Properties
It’s sometimes useful to only activate a given get 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:
Property | Note |
---|---|
|
A profile expression that must match for the document to be active. |
|
The |
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:
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’re looking for 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.
If you use “Starters”, SnakeYAML is automatically provided by spring-boot-starter . |
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:
dev:
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:
my:
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:
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]}
my:
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. 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.7.1. JavaBean properties binding
It is possible to bind a bean declaring standard JavaBean properties as shown in the following example:
package com.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("acme")
public class AcmeProperties {
private boolean enabled;
private InetAddress remoteAddress;
private final Security security = new Security();
public boolean isEnabled() { ... }
public void setEnabled(boolean enabled) { ... }
public InetAddress getRemoteAddress() { ... }
public void setRemoteAddress(InetAddress remoteAddress) { ... }
public Security getSecurity() { ... }
public static class Security {
private String username;
private String password;
private List<String> roles = new ArrayList<>(Collections.singleton("USER"));
public String getUsername() { ... }
public void setUsername(String username) { ... }
public String getPassword() { ... }
public void setPassword(String password) { ... }
public List<String> getRoles() { ... }
public void setRoles(List<String> roles) { ... }
}
}
The preceding POJO defines the following properties:
acme.enabled
, with a value offalse
by default.acme.remote-address
, with a type that can be coerced fromString
.acme.security.username
, with a nested "security" object whose name is determined by the name of the property. In particular, the return type is not used at all there and could have beenSecurityProperties
.acme.security.password
.acme.security.roles
, with a collection ofString
that defaults toUSER
.
The properties that map to @ConfigurationProperties classes available in Spring Boot, which are configured via properties files, YAML files, environment variables etc., are public API but the accessors (getters/setters) of the class itself are not meant to be used directly. |
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:
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.7.2. Constructor binding
The example in the previous section can be rewritten in an immutable fashion as shown in the following example:
package com.example;
import java.net.InetAddress;
import java.util.List;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.context.properties.ConstructorBinding;
import org.springframework.boot.context.properties.bind.DefaultValue;
@ConstructorBinding
@ConfigurationProperties("acme")
public class AcmeProperties {
private final boolean enabled;
private final InetAddress remoteAddress;
private final Security security;
public AcmeProperties(boolean enabled, InetAddress remoteAddress, Security security) {
this.enabled = enabled;
this.remoteAddress = remoteAddress;
this.security = security;
}
public boolean isEnabled() { ... }
public InetAddress getRemoteAddress() { ... }
public Security getSecurity() { ... }
public static class Security {
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;
}
public String getUsername() { ... }
public String getPassword() { ... }
public List<String> getRoles() { ... }
}
}
In this setup, the @ConstructorBinding
annotation is used to indicate that constructor binding should be used. This means that the binder will expect to find a constructor with the parameters that you wish to have bound.
Nested members of a @ConstructorBinding
class (such as Security
in the example above) will also be bound via their constructor.
Default values can be specified using @DefaultValue
and the same conversion service will be applied to coerce the String
value to the target type of a missing property. By default, if no properties are bound to Security
, the AcmeProperties
instance will contain a null
value for security
. If you wish you return a non-null instance of Security
even when no properties are bound to it, you can use an empty @DefaultValue
annotation to do so:
package com.example;
import java.net.InetAddress;
import java.util.List;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.context.properties.ConstructorBinding;
import org.springframework.boot.context.properties.bind.DefaultValue;
@ConstructorBinding
@ConfigurationProperties("acme")
public class AcmeProperties {
private final boolean enabled;
private final InetAddress remoteAddress;
private final Security security;
public AcmeProperties(boolean enabled, InetAddress remoteAddress, @DefaultValue Security security) {
this.enabled = enabled;
this.remoteAddress = remoteAddress;
this.security = security;
}
}
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 (e.g. @Component beans, beans created via @Bean methods or beans loaded using @Import ) |
If you have more than one constructor for your class you can also use @ConstructorBinding directly on the constructor that should be bound. |
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.7.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:
@Configuration(proxyBeanMethods = false)
@EnableConfigurationProperties(AcmeProperties.class)
public class MyConfiguration {
}
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:
@SpringBootApplication
@ConfigurationPropertiesScan({ "com.example.app", "org.acme.another" })
public class MyApplication {
}
When the The bean name in the example above is |
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.7.4. Using @ConfigurationProperties-annotated types
This style of configuration works particularly well with the SpringApplication
external YAML configuration, as shown in the following example:
acme:
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:
@Service
public class MyService {
private final AcmeProperties properties;
@Autowired
public MyService(AcmeProperties properties) {
this.properties = properties;
}
//...
@PostConstruct
public void openConnection() {
Server server = new Server(this.properties.getRemoteAddress());
// ...
}
}
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.7.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:
@ConfigurationProperties(prefix = "another")
@Bean
public AnotherComponent anotherComponent() {
...
}
Any JavaBean property defined with the another
prefix is mapped onto that AnotherComponent
bean in manner similar to the preceding AcmeProperties
example.
2.7.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:
@ConfigurationProperties(prefix="acme.my-project.person")
public class OwnerProperties {
private String firstName;
public String getFirstName() {
return this.firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
}
With the preceding code, the following properties names can all be used:
Property | Note |
---|---|
|
Kebab case, which is recommended for use in |
|
Standard camel case syntax. |
|
Underscore notation, which is an alternative format for use in |
|
Upper case format, which is recommended when using system environment variables. |
The prefix value for the annotation must be in kebab case (lowercase and separated by - , such as acme.my-project.person ). |
Property Source | Simple | List |
---|---|---|
Properties Files |
Camel case, kebab case, or underscore notation |
Standard list syntax using |
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 |
We recommend that, when possible, properties are stored in lower-case kebab format, such as my.property-name=acme . |
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>
:
acme.map.[/key1]=value1
acme.map.[/key2]=value2
acme.map./key3=value3
acme:
map:
"[/key1]": "value1"
"[/key2]": "value2"
"/key3": "value3"
For YAML files, the brackets need to be surrounded by quotes for the keys to be parsed properly. |
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 wasn’t surrounded by square brackets.
You may also occasionally need to use the bracket notation if your key
contains a .
and you are binding to non-scalar value. 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:
Replace dots (
.
) with underscores (_
).Remove any dashes (
-
).Convert to uppercase.
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.acme[0].other
would use an environment variable named MY_ACME_0_OTHER
.
2.7.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 AcmeProperties
:
@ConfigurationProperties("acme")
public class AcmeProperties {
private final List<MyPojo> list = new ArrayList<>();
public List<MyPojo> getList() {
return this.list;
}
}
Consider the following configuration:
acme.list[0].name=my name
acme.list[0].description=my description
#---
spring.config.activate.on-profile=dev
acme.list[0].name=my another name
acme:
list:
- name: "my name"
description: "my description"
---
spring:
config:
activate:
on-profile: "dev"
acme:
list:
- name: "my another name"
If the dev
profile is not active, AcmeProperties.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:
acme.list[0].name=my name
acme.list[0].description=my description
acme.list[1].name=another name
acme.list[1].description=another description
#---
spring.config.activate.on-profile=dev
acme.list[0].name=my another name
acme:
list:
- name: "my name"
description: "my description"
- name: "another name"
description: "another description"
---
spring:
config:
activate:
on-profile: "dev"
acme:
list:
- name: "my another name"
In the preceding example, if the dev
profile is active, AcmeProperties.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 AcmeProperties
:
@ConfigurationProperties("acme")
public class AcmeProperties {
private final Map<String, MyPojo> map = new HashMap<>();
public Map<String, MyPojo> getMap() {
return this.map;
}
}
Consider the following configuration:
acme.map.key1.name=my name 1
acme.map.key1.description=my description 1
#---
spring.config.activate.on-profile=dev
acme.map.key1.name=dev name 1
acme.map.key2.name=dev name 2
acme.map.key2.description=dev description 2
acme:
map:
key1:
name: "my name 1"
description: "my description 1"
---
spring:
config:
activate:
on-profile: "dev"
acme:
map:
key1:
name: "dev name 1"
key2:
name: "dev name 2"
description: "dev description 2"
If the dev
profile is not active, AcmeProperties.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
).
The preceding merging rules apply to properties from all property sources, and not just files. |
2.7.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 . |
Converting durations
Spring Boot has dedicated support for expressing durations. If you expose a java.time.Duration
property, the following formats in application properties are available:
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 (e.g.
10s
means 10 seconds)
Consider the following example:
@ConfigurationProperties("app.system")
public class AppSystemProperties {
@DurationUnit(ChronoUnit.SECONDS)
private Duration sessionTimeout = Duration.ofSeconds(30);
private Duration readTimeout = Duration.ofMillis(1000);
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;
}
}
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:
ns
for nanosecondsus
for microsecondsms
for millisecondss
for secondsm
for minutesh
for hoursd
for days
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:
@ConfigurationProperties("app.system")
@ConstructorBinding
public class AppSystemProperties {
private final Duration sessionTimeout;
private final Duration readTimeout;
public AppSystemProperties(@DurationUnit(ChronoUnit.SECONDS) @DefaultValue("30s") Duration sessionTimeout,
@DefaultValue("1000ms") Duration readTimeout) {
this.sessionTimeout = sessionTimeout;
this.readTimeout = readTimeout;
}
public Duration getSessionTimeout() {
return this.sessionTimeout;
}
public Duration getReadTimeout() {
return this.readTimeout;
}
}
If you are upgrading a Long property, make sure to define the unit (using @DurationUnit ) if it isn’t 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 (e.g.
1y3d
means 1 year and 3 days)
The following units are supported with the simple format:
y
for yearsm
for monthsw
for weeksd
for days
The java.time.Period type never actually stores the number of weeks, it is a shortcut that means “7 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 (e.g.
10MB
means 10 megabytes)
Consider the following example:
@ConfigurationProperties("app.io")
public class AppIoProperties {
@DataSizeUnit(DataUnit.MEGABYTES)
private DataSize bufferSize = DataSize.ofMegabytes(2);
private DataSize sizeThreshold = DataSize.ofBytes(512);
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;
}
}
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:
B
for bytesKB
for kilobytesMB
for megabytesGB
for gigabytesTB
for terabytes
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:
@ConfigurationProperties("app.io")
@ConstructorBinding
public class AppIoProperties {
private final DataSize bufferSize;
private final DataSize sizeThreshold;
public AppIoProperties(@DataSizeUnit(DataUnit.MEGABYTES) @DefaultValue("2MB") DataSize bufferSize,
@DefaultValue("512B") DataSize sizeThreshold) {
this.bufferSize = bufferSize;
this.sizeThreshold = sizeThreshold;
}
public DataSize getBufferSize() {
return this.bufferSize;
}
public DataSize getSizeThreshold() {
return this.sizeThreshold;
}
}
If you are upgrading a Long property, make sure to define the unit (using @DataSizeUnit ) if it isn’t bytes. Doing so gives a transparent upgrade path while supporting a much richer format. |
2.7.9. @ConfigurationProperties Validation
Spring Boot attempts to validate @ConfigurationProperties
classes whenever they are annotated with Spring’s @Validated
annotation. You can use JSR-303 javax.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:
@ConfigurationProperties(prefix="acme")
@Validated
public class AcmeProperties {
@NotNull
private InetAddress remoteAddress;
// ... getters and setters
}
You can also trigger validation by annotating the @Bean method that creates the configuration properties with @Validated . |
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 AcmeProperties
example:
@ConfigurationProperties(prefix="acme")
@Validated
public class AcmeProperties {
@NotNull
private InetAddress remoteAddress;
@Valid
private final Security security = new Security();
// ... getters and setters
public static class Security {
@NotEmpty
public String username;
// ... getters and setters
}
}
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.7.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
:
Feature | @ConfigurationProperties |
@Value |
---|---|---|
Yes |
Limited (see note below) |
|
Yes |
No |
|
|
No |
Yes |
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 via @Value
.
3. Profiles
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:
@Configuration(proxyBeanMethods = false)
@Profile("production")
public class ProductionConfiguration {
// ...
}
If @ConfigurationProperties beans are registered via @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:
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
.
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 SpringApplication
entry point has a Java API for setting additional profiles (that is, on top of those activated by the spring.profiles.active
property). See the setAdditionalProfiles()
method in SpringApplication . Profile groups, which are described in the next section can also be used to add active profiles if a given profile is active.
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.
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 active 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.
4. Logging
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 via 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. |
4.1. Log Format
The default log output from Spring Boot resembles the following example:
2019-03-05 10:57:51.112 INFO 45469 --- [ main] org.apache.catalina.core.StandardEngine : Starting Servlet Engine: Apache Tomcat/7.0.52
2019-03-05 10:57:51.253 INFO 45469 --- [ost-startStop-1] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring embedded WebApplicationContext
2019-03-05 10:57:51.253 INFO 45469 --- [ost-startStop-1] o.s.web.context.ContextLoader : Root WebApplicationContext: initialization completed in 1358 ms
2019-03-05 10:57:51.698 INFO 45469 --- [ost-startStop-1] o.s.b.c.e.ServletRegistrationBean : Mapping servlet: 'dispatcherServlet' to [/]
2019-03-05 10:57:51.702 INFO 45469 --- [ost-startStop-1] o.s.b.c.embedded.FilterRegistrationBean : Mapping filter: 'hiddenHttpMethodFilter' to: [/*]
The following items are output:
Date and Time: Millisecond precision and easily sortable.
Log Level:
ERROR
,WARN
,INFO
,DEBUG
, orTRACE
.Process ID.
A
---
separator to distinguish the start of actual log messages.Thread name: Enclosed in square brackets (may be truncated for console output).
Logger name: This is usually the source class name (often abbreviated).
The log message.
Logback does not have a FATAL level. It is mapped to ERROR . |
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
You can also specify debug=true in your application.properties . |
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:
Level | Color |
---|---|
|
Red |
|
Red |
|
Yellow |
|
Green |
|
Green |
|
Green |
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 HH:mm:ss.SSS}){yellow}
The following colors and styles are supported:
blue
cyan
faint
green
magenta
red
yellow
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:
logging.file.name |
logging.file.path |
Example | Description |
---|---|---|---|
(none) |
(none) |
Console only logging. |
|
Specific file |
(none) |
|
Writes to the specified log file. Names can be an exact location or relative to the current directory. |
(none) |
Specific directory |
|
Writes |
Log files rotate when they reach 10 MB and, as with console output, ERROR
-level, WARN
-level, and INFO
-level messages are logged by default.
Logging properties are independent of the actual logging infrastructure. As a result, specific configuration keys (such as logback.configurationFile for Logback) are not managed by spring Boot. |
4.4. File Rotation
If you are using the Logback, it’s possible to fine-tune log rotation settings using your application.properties
or application.yaml
file. For all other logging system, you’ll need to configure rotation settings directly yourself (for example, if you use Log4J2 then you could add a log4j.xml
file).
The following rotation policy properties are supported:
Name | Description |
---|---|
|
The filename pattern used to create log archives. |
|
If log archive cleanup should occur when the application starts. |
|
The maximum size of log file before it’s archived. |
|
The maximum amount of size log archives can take before being deleted. |
|
The number of days to keep log archives (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
:
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’s 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’s 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’s 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’t easily remember top level packages.
To help with this, Spring Boot allows you to define logging groups in your Spring Environment
. For example, here’s how you could define a “tomcat” group by adding it to your application.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:
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:
Name | Loggers |
---|---|
web |
|
sql |
|
4.7. Using a Log Shutdown Hook
In order to release logging resources it is usually a good idea to stop the logging system when your application terminates. Unfortunately, there’s no single way to do this that will work with all application types. If your application has complex context hierarchies or is deployed as a war file, you’ll need to 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.
For simple "single jar" applications deployed in their own JVM, you can use the logging.register-shutdown-hook
property. Setting logging.register-shutdown-hook
to true
will register a shutdown hook that will trigger log system cleanup when the JVM exits.
You can set the property in your application.properties
or application.yaml
file:
logging.register-shutdown-hook=true
logging:
register-shutdown-hook: true
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 via System properties. |
Depending on your logging system, the following files are loaded:
Logging System | Customization |
---|---|
Logback |
|
Log4j2 |
|
JDK (Java Util Logging) |
|
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. |
To help with the customization, some other properties are transferred from the Spring Environment
to System properties, as described in the following tab