âšď¸ Skipped - page is already crawled
| Filter | Status | Condition | Details |
|---|---|---|---|
| HTTP status | PASS | download_http_code = 200 | HTTP 200 |
| Age cutoff | PASS | download_stamp > now() - 6 MONTH | 0 months ago |
| History drop | PASS | isNull(history_drop_reason) | No drop reason |
| Spam/ban | PASS | fh_dont_index != 1 AND ml_spam_score = 0 | ml_spam_score=0 |
| Canonical | PASS | meta_canonical IS NULL OR = '' OR = src_unparsed | Not set |
| Property | Value |
|---|---|
| URL | https://docs.spring.io/spring-boot/reference/features/external-config.html |
| Last Crawled | 2026-04-07 04:11:34 (3 hours ago) |
| First Indexed | 2024-03-23 13:36:49 (2 years ago) |
| HTTP Status Code | 200 |
| Meta Title | Externalized Configuration :: Spring Boot |
| Meta Description | null |
| Meta Canonical | null |
| Boilerpipe Text | 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:
Default properties (specified by setting
SpringApplication.setDefaultProperties(Map)
).
@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
.
@DynamicPropertySource
annotations in your tests.
@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 YAML format in the same location,
.properties
takes precedence.
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.
To provide a concrete example, suppose you develop a
@Component
that uses a
name
property, as shown in the following example:
Java
Kotlin
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.
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)
.
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.
External Application Properties
Spring Boot will automatically find and load
application.properties
and
application.yaml
files from the following locations when your application starts:
From the classpath
The classpath root
The classpath
/config
package
From the current directory
The current directory
The
config/
subdirectory in the current directory
Immediate 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
PropertySource
instances 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
Use the prefix
optional:
if the
locations are optional
and you do not mind if they do not 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 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:
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.
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
ConfigDataLocationNotFoundException
errors 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.
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.
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.yaml
and
application-prod.yaml
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:
/cfg
application-live.properties
/ext
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:
/cfg/application-live.properties
/ext/application-prod.properties
/ext/application-live.properties
When we have
classpath:/cfg/;classpath:/ext/
instead (with a
;
delimiter) we process
/cfg
and
/ext
at the same level:
/ext/application-prod.properties
/cfg/application-live.properties
/ext/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 have already directly
imported
a profile specific property files then it will not be imported a second time.
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
YAML
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.
Using âFixedâ and âImport Relativeâ Locations
Imports may be specified as
fixed
or
import relative
locations.
A fixed location always resolves to the same underlying resource, regardless of where the
spring.config.import
property is declared.
An import relative location resolves relative to the file that declares the
spring.config.import
property.
A location starting with a forward slash (
/
) or a URL style prefix (
file:
,
classpath:
, etc.) is considered fixed.
All other locations are considered import relative.
optional:
prefixes are not considered when determining if a location is fixed or import relative.
As an example, say we have a
/demo
directory containing our
application.jar
file.
We might add a
/demo/application.properties
file with the following content:
spring.config.import=optional:core/core.properties
This is an import relative location and so will attempt to load the file
/demo/core/core.properties
if it exists.
If
/demo/core/core.properties
has the following content:
spring.config.import=optional:extra/extra.properties
It will attempt to load
/demo/core/extra/extra.properties
.
The
optional:extra/extra.properties
is relative to
/demo/core/core.properties
so the full directory is
/demo/core/
+
extra/extra.properties
.
Property Ordering
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
YAML
spring.config.import=my.properties
my.property=value
spring:
config:
import: "my.properties"
my:
property: "value"
Properties
YAML
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.
When appropriate,
Profile-specific variants
are also considered for import.
The example above would import both
my.properties
as well as any
my-<profile>.properties
variants.
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.
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
YAML
spring.config.import=file:/etc/config/myconfig[.yaml]
spring:
config:
import: "file:/etc/config/myconfig[.yaml]"
Using Environment Variables
When running applications on a cloud platform (such as Kubernetes) you often need to read config values that the platform supplies.
You can either use environment variables for such purpose, or you can use
configuration trees
.
You can even store whole configurations in properties or yaml format in (multiline) environment variables and load them using the
env:
prefix.
Assume thereâs an environment variable called
MY_CONFIGURATION
with this content:
my.name=Service1
my.cluster=Cluster1
Using the
env:
prefix it is possible to import all properties from this variable:
Properties
YAML
spring.config.import=env:MY_CONFIGURATION
spring:
config:
import: "env:MY_CONFIGURATION"
This feature also supports
specifying the extension
.
The default extension is
.properties
.
Using Configuration Trees
Storing config values in environment variables has 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:
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:
Properties
YAML
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.
The names of the folders and files under the config tree form the property name.
In the above example, to access the properties as
username
and
password
, you can set
spring.config.import
to
optional:configtree:/etc/config/myapp
.
Filenames with dot notation are also correctly mapped.
For example, in the above example, a file named
myapp.username
in
/etc/config
would result in a
myapp.username
property in the
Environment
.
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.
As with a non-wildcard import, the names of the folders and files under each config tree form the property name.
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:
Properties
YAML
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:
Properties
YAML
spring.config.import=optional:configtree:/run/secrets/
spring:
config:
import: "optional:configtree:/run/secrets/"
Property Placeholders
The values in
application.properties
and
application.yaml
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
YAML
app.name=MyApp
app.description=${app.name} is a Spring Boot application written by ${username:Unknown}
app:
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 use
${demo.itemPrice}
instead, it will pick up the
demo.itemPrice
form from the
application.properties
file, as well as
DEMO_ITEMPRICE
from the system environment, but
demo.item-price
would not be considered.
You can also use this technique to create âshortâ variants of existing Spring Boot properties.
See the
Use âShortâ Command Line Arguments
section in âHow-to Guidesâ for details.
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.yaml
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.
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 1. activation properties
Property
Note
on-profile
A profile expression that must match for the document to be active, or a list of profile expressions of which at least one must match for the document to be active.
on-cloud-platform
The
CloudPlatform
that must be detected for the document to be active.
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
YAML
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"
Encrypting Properties
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
.
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
.
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.
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
YAML
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).
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
by calling the
setEnvironmentPrefix(âŚâ)
method before the application is run.
For example, if you set the prefix to
input
, a property such as
remote.timeout
will be resolved as
INPUT_REMOTE_TIMEOUT
in the system environment.
The prefix
only
applies to system environment properties.
The example above would continue to use
remote.timeout
when reading properties from other sources.
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.
See also the
differences between
@Value
and type-safe configuration properties.
JavaBean Properties Binding
It is possible to bind a bean declaring standard JavaBean properties as shown in the following example:
Java
Kotlin
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"))
}
}
The preceding POJO defines the following properties:
my.service.enabled
, with a value of
false
by default.
my.service.remote-address
, with a type that can be coerced from
String
.
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
.
To use a reserved keyword in the name of a property, such as
my.service.import
, use the
@Name
annotation on the propertyâs field.
The properties that map to
@ConfigurationProperties
classes available in Spring Boot, which are configured through properties files, YAML files, environment variables, and other mechanisms, 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:
Pre-initialized Maps and Collections, as long as they are initialized with a mutable implementation (like the
roles
field in the preceding example).
Pre-initialized nested POJOs (like the
Security
field in the preceding example).
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.
Constructor Binding
The example in the previous section can be rewritten in an immutable fashion as shown in the following example:
Java
Kotlin
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, the parameterized constructor must be annotated with
@Autowired
or made
private
.
Kotlin developers can use an empty primary constructor to opt-out of constructor binding.
For example:
Java
Kotlin
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.ConfigurationProperties;
@ConfigurationProperties("my")
public class MyProperties {
// fields...
final MyBean myBean;
private String name;
@Autowired
public MyProperties(MyBean myBean) {
this.myBean = myBean;
}
// getters / setters...
public String getName() {
return this.name;
}
public void setName(String name) {
this.name = name;
}
}
import org.springframework.boot.context.properties.ConfigurationProperties
@ConfigurationProperties("my")
class MyProperties() {
constructor(name: String) : this() {
this.name = name
}
// vars...
var name: String? = null
}
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:
Java
Kotlin
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 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
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.
To use a reserved keyword in the name of a property, such as
my.service.import
, use the
@Name
annotation on the constructor parameter.
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:
Java
Kotlin
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
Java
Kotlin
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:
Java
Kotlin
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.
Using @ConfigurationProperties-annotated Types
This style of configuration works particularly well with the
SpringApplication
external YAML configuration, as shown in the following example:
my:
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:
Java
Kotlin
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();
// ...
}
// ...
}
import org.springframework.stereotype.Service
@Service
class MyService(val properties: MyProperties) {
fun openConnection() {
val server = Server(properties.remoteAddress)
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.
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:
Java
Kotlin
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("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("another")
fun anotherComponent(): AnotherComponent = AnotherComponent()
}
Any JavaBean property defined with the
another
prefix is mapped onto that
AnotherComponent
bean in manner similar to the preceding
SomeProperties
example.
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
).
Java
Kotlin
import org.springframework.boot.context.properties.ConfigurationProperties;
@ConfigurationProperties("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("my.main-project.person")
class MyPersonProperties {
var firstName: String? = null
}
With the preceding code, the following properties names can all be used:
Table 2. relaxed binding
Property
Note
my.main-project.person.first-name
Kebab case, which is recommended for use in
.properties
and YAML 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 YAML files.
MY_MAINPROJECT_PERSON_FIRSTNAME
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
my.main-project.person
).
Table 3. relaxed binding rules per property source
Property Source
Simple
List
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
We recommend that, when possible, properties are stored in lower-case kebab format, such as
my.person.first-name=Rod
.
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
YAML
my.map[/key1]=value1
my.map[/key2]=value2
my.map./key3=value3
my:
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 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:
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.service[0].other
would use an environment variable named
MY_SERVICE_0_OTHER
.
Support for binding from environment variables is applied to the
systemEnvironment
property source and to any additional property source whose name ends with
-systemEnvironment
.
Binding Maps From Environment Variables
When Spring Boot binds an environment variable to a property class, it lowercases the environment variable name before binding.
Most of the time this detail isnât important, except when binding to
Map
properties.
The keys in the
Map
are always in lowercase, as seen in the following example:
Java
Kotlin
import java.util.HashMap;
import java.util.Map;
import org.springframework.boot.context.properties.ConfigurationProperties;
@ConfigurationProperties("my.props")
public class MyMapsProperties {
private final Map<String, String> values = new HashMap<>();
public Map<String, String> getValues() {
return this.values;
}
}
import org.springframework.boot.context.properties.ConfigurationProperties
@ConfigurationProperties("my.props")
class MyMapsProperties {
val values: Map<String, String> = HashMap()
}
When setting
MY_PROPS_VALUES_KEY=value
, the
values
Map
contains a
{"key"="value"}
entry.
Only the environment variable
name
is lower-cased, not the value.
When setting
MY_PROPS_VALUES_KEY=VALUE
, the
values
Map
contains a
{"key"="VALUE"}
entry.
Caching
Relaxed binding uses a cache to improve performance. By default, this caching is only applied to immutable property sources.
To customize this behavior, for example to enable caching for mutable property sources, use
ConfigurationPropertyCaching
.
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
:
Java
Kotlin
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()
}
Consider the following configuration:
Properties
YAML
my.list[0].name=my name
my.list[0].description=my description
#---
spring.config.activate.on-profile=dev
my.list[0].name=my another name
my:
list:
- name: "my name"
description: "my description"
---
spring:
config:
activate:
on-profile: "dev"
my:
list:
- name: "my another name"
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
YAML
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
my:
list:
- name: "my name"
description: "my description"
- name: "another name"
description: "another description"
---
spring:
config:
activate:
on-profile: "dev"
my:
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
:
Java
Kotlin
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()
}
Consider the following configuration:
Properties
YAML
my.map.key1.name=my name 1
my.map.key1.description=my description 1
#---
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
my:
map:
key1:
name: "my name 1"
description: "my description 1"
---
spring:
config:
activate:
on-profile: "dev"
my:
map:
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
).
The preceding merging rules apply to properties from all property sources, and not just files.
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
).
Beans used for property conversion are requested very early during the application lifecycle so 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
.
When qualifying a
@Bean
method with
@ConfigurationPropertiesBinding
, the method should be
static
to avoid âbean is not eligible for getting processed by all BeanPostProcessorsâ warnings.
Converting Durations
Spring Boot has dedicated support for expressing durations.
If you expose a
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
Duration
A more readable format where the value and the unit are coupled (
10s
means 10 seconds)
Consider the following example:
Java
Kotlin
import java.time.Duration;
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:
ns
for nanoseconds
us
for microseconds
ms
for milliseconds
s
for seconds
m
for minutes
h
for hours
d
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:
Java
Kotlin
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
Period
type.
The following formats can be used in application properties:
A regular
int
representation (using days as the default unit unless a
@PeriodUnit
has been specified)
The standard ISO-8601 format
used by
Period
A simpler format where the value and the unit pairs are coupled (
1y3d
means 1 year and 3 days)
The following units are supported with the simple format:
y
for years
m
for months
w
for weeks
d
for days
The
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 (
10MB
means 10 megabytes)
Consider the following example:
Java
Kotlin
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:
B
for bytes
KB
for kilobytes
MB
for megabytes
GB
for gigabytes
TB
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:
Java
Kotlin
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.
Converting Base64 Data
Spring Boot supports resolving binary data that have been Base64 encoded.
If you expose a
Resource
property, the base64 encoded text can be provided as the value with a
base64:
prefix, as shown in the following example:
Properties
YAML
my.property=base64:SGVsbG8gV29ybGQ=
my:
property: base64:SGVsbG8gV29ybGQ=
The
Resource
property can also be used to provide the path to the resource, making it more versatile.
@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:
Java
Kotlin
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
}
You can also trigger validation by annotating the
@Bean
method that creates the configuration properties with
@Validated
.
To cascade validation to nested properties the associated field must be annotated with
@Valid
.
The following example builds on the preceding
MyProperties
example:
Java
Kotlin
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.
@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
Relaxed binding
Yes
Limited (see
note below
)
Meta-data support
Yes
No
SpEL
evaluation
No
Yes
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 use
@Value("${demo.itemPrice}")
instead, it will pickup the
demo.itemPrice
form from the
application.properties
file, as well as
DEMO_ITEMPRICE
from the system environment, but
demo.item-price
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
. |
| Markdown | [](https://spring.io/)
[Why Spring](https://docs.spring.io/spring-boot/reference/features/external-config.html)
[Overview](https://spring.io/why-spring)
Trending
[Generative AI](https://spring.io/ai) [Cloud](https://spring.io/cloud)
Architecture Patterns
[Microservices](https://spring.io/microservices) [Reactive](https://spring.io/reactive) [Event Driven](https://spring.io/event-driven)
Application Types
[Web Applications](https://spring.io/web-applications) [Serverless](https://spring.io/serverless) [Batch](https://spring.io/batch)
[Learn](https://docs.spring.io/spring-boot/reference/features/external-config.html)
Getting Started
[Quickstart](https://spring.io/quickstart) [Guides](https://spring.io/guides)
Academy
[Courses](https://spring.academy/courses)
[Get Certified](https://spring.academy/learning-path)
[Projects](https://docs.spring.io/spring-boot/reference/features/external-config.html)
[Overview](https://spring.io/projects)
Projects
[Spring Boot](https://spring.io/projects/spring-boot) [Spring Framework](https://spring.io/projects/spring-framework) [Spring Cloud](https://spring.io/projects/spring-cloud) [Spring AI](https://spring.io/projects/spring-ai) [Spring Data](https://spring.io/projects/spring-data) [Spring Integration](https://spring.io/projects/spring-integration) [Spring Batch](https://spring.io/projects/spring-batch) [Spring Security](https://spring.io/projects/spring-security)
Foundational Projects
[Micrometer](https://micrometer.io/)
[Reactor](https://projectreactor.io/)
Development Tools
[Spring Tools](https://spring.io/tools)
[Spring Initializr](https://start.spring.io/)
[Resources](https://docs.spring.io/spring-boot/reference/features/external-config.html)
[Blog](https://spring.io/blog) [Release Calendar](https://spring.io/projects#release-calendar) [Version Mappings](https://spring.io/projects/generations) [Release Highlights](https://spring.io/projects/release-highlights) [Security Advisories](https://spring.io/security)
GitHub Orgs
[Spring Projects](https://github.com/spring-projects)
[Spring Cloud](https://github.com/spring-cloud)
[Community](https://docs.spring.io/spring-boot/reference/features/external-config.html)
[Overview](https://spring.io/community) [Events](https://spring.io/events) [Authors](https://spring.io/authors)
[Enterprise](https://docs.spring.io/spring-boot/reference/features/external-config.html)
[Overview](https://enterprise.spring.io/) [Long-term Support](https://enterprise.spring.io/lts-releases) [Automated Upgrades](https://enterprise.spring.io/spring-application-advisor) [Governance and Compliance](https://enterprise.spring.io/enterprise-extensions) [Modern App Development](https://enterprise.spring.io/enterprise-components)
light
Spring Boot 4\.0.5
Search
- - [Overview](https://docs.spring.io/spring-boot/index.html)
- [Documentation](https://docs.spring.io/spring-boot/documentation.html)
- [Community](https://docs.spring.io/spring-boot/community.html)
- [System Requirements](https://docs.spring.io/spring-boot/system-requirements.html)
- [Installing Spring Boot](https://docs.spring.io/spring-boot/installing.html)
- [Upgrading Spring Boot](https://docs.spring.io/spring-boot/upgrading.html)
- [Tutorials](https://docs.spring.io/spring-boot/tutorial/index.html)
- [Developing Your First Spring Boot Application](https://docs.spring.io/spring-boot/tutorial/first-application/index.html)
- [Reference](https://docs.spring.io/spring-boot/reference/index.html)
- [Developing with Spring Boot](https://docs.spring.io/spring-boot/reference/using/index.html)
- [Build Systems](https://docs.spring.io/spring-boot/reference/using/build-systems.html)
- [Structuring Your Code](https://docs.spring.io/spring-boot/reference/using/structuring-your-code.html)
- [Configuration Classes](https://docs.spring.io/spring-boot/reference/using/configuration-classes.html)
- [Auto-configuration](https://docs.spring.io/spring-boot/reference/using/auto-configuration.html)
- [Spring Beans and Dependency Injection](https://docs.spring.io/spring-boot/reference/using/spring-beans-and-dependency-injection.html)
- [Using the @SpringBootApplication Annotation](https://docs.spring.io/spring-boot/reference/using/using-the-springbootapplication-annotation.html)
- [Running Your Application](https://docs.spring.io/spring-boot/reference/using/running-your-application.html)
- [Developer Tools](https://docs.spring.io/spring-boot/reference/using/devtools.html)
- [Packaging Your Application for Production](https://docs.spring.io/spring-boot/reference/using/packaging-for-production.html)
- [Core Features](https://docs.spring.io/spring-boot/reference/features/index.html)
- [SpringApplication](https://docs.spring.io/spring-boot/reference/features/spring-application.html)
- [Externalized Configuration](https://docs.spring.io/spring-boot/reference/features/external-config.html)
- [Profiles](https://docs.spring.io/spring-boot/reference/features/profiles.html)
- [Logging](https://docs.spring.io/spring-boot/reference/features/logging.html)
- [Internationalization](https://docs.spring.io/spring-boot/reference/features/internationalization.html)
- [Aspect-Oriented Programming](https://docs.spring.io/spring-boot/reference/features/aop.html)
- [JSON](https://docs.spring.io/spring-boot/reference/features/json.html)
- [Task Execution and Scheduling](https://docs.spring.io/spring-boot/reference/features/task-execution-and-scheduling.html)
- [Development-time Services](https://docs.spring.io/spring-boot/reference/features/dev-services.html)
- [Creating Your Own Auto-configuration](https://docs.spring.io/spring-boot/reference/features/developing-auto-configuration.html)
- [Kotlin Support](https://docs.spring.io/spring-boot/reference/features/kotlin.html)
- [SSL](https://docs.spring.io/spring-boot/reference/features/ssl.html)
- [Web](https://docs.spring.io/spring-boot/reference/web/index.html)
- [Servlet Web Applications](https://docs.spring.io/spring-boot/reference/web/servlet.html)
- [Reactive Web Applications](https://docs.spring.io/spring-boot/reference/web/reactive.html)
- [Graceful Shutdown](https://docs.spring.io/spring-boot/reference/web/graceful-shutdown.html)
- [Spring Security](https://docs.spring.io/spring-boot/reference/web/spring-security.html)
- [Spring Session](https://docs.spring.io/spring-boot/reference/web/spring-session.html)
- [Spring for GraphQL](https://docs.spring.io/spring-boot/reference/web/spring-graphql.html)
- [Spring HATEOAS](https://docs.spring.io/spring-boot/reference/web/spring-hateoas.html)
- [Data](https://docs.spring.io/spring-boot/reference/data/index.html)
- [SQL Databases](https://docs.spring.io/spring-boot/reference/data/sql.html)
- [Working with NoSQL Technologies](https://docs.spring.io/spring-boot/reference/data/nosql.html)
- [IO](https://docs.spring.io/spring-boot/reference/io/index.html)
- [Caching](https://docs.spring.io/spring-boot/reference/io/caching.html)
- [Spring Batch](https://docs.spring.io/spring-boot/reference/io/spring-batch.html)
- [Hazelcast](https://docs.spring.io/spring-boot/reference/io/hazelcast.html)
- [Quartz Scheduler](https://docs.spring.io/spring-boot/reference/io/quartz.html)
- [Sending Email](https://docs.spring.io/spring-boot/reference/io/email.html)
- [Validation](https://docs.spring.io/spring-boot/reference/io/validation.html)
- [Calling REST Services](https://docs.spring.io/spring-boot/reference/io/rest-client.html)
- [Web Services](https://docs.spring.io/spring-boot/reference/io/webservices.html)
- [Distributed Transactions With JTA](https://docs.spring.io/spring-boot/reference/io/jta.html)
- [Messaging](https://docs.spring.io/spring-boot/reference/messaging/index.html)
- [JMS](https://docs.spring.io/spring-boot/reference/messaging/jms.html)
- [AMQP](https://docs.spring.io/spring-boot/reference/messaging/amqp.html)
- [Apache Kafka Support](https://docs.spring.io/spring-boot/reference/messaging/kafka.html)
- [Apache Pulsar Support](https://docs.spring.io/spring-boot/reference/messaging/pulsar.html)
- [RSocket](https://docs.spring.io/spring-boot/reference/messaging/rsocket.html)
- [Spring Integration](https://docs.spring.io/spring-boot/reference/messaging/spring-integration.html)
- [WebSockets](https://docs.spring.io/spring-boot/reference/messaging/websockets.html)
- [Testing](https://docs.spring.io/spring-boot/reference/testing/index.html)
- [Test Modules](https://docs.spring.io/spring-boot/reference/testing/test-modules.html)
- [Test Scope Dependencies](https://docs.spring.io/spring-boot/reference/testing/test-scope-dependencies.html)
- [Testing Spring Applications](https://docs.spring.io/spring-boot/reference/testing/spring-applications.html)
- [Testing Spring Boot Applications](https://docs.spring.io/spring-boot/reference/testing/spring-boot-applications.html)
- [Testcontainers](https://docs.spring.io/spring-boot/reference/testing/testcontainers.html)
- [Test Utilities](https://docs.spring.io/spring-boot/reference/testing/test-utilities.html)
- [Packaging Spring Boot Applications](https://docs.spring.io/spring-boot/reference/packaging/index.html)
- [Efficient Deployments](https://docs.spring.io/spring-boot/reference/packaging/efficient.html)
- [AOT Cache](https://docs.spring.io/spring-boot/reference/packaging/aot-cache.html)
- [Ahead-of-Time Processing With the JVM](https://docs.spring.io/spring-boot/reference/packaging/aot.html)
- [GraalVM Native Images](https://docs.spring.io/spring-boot/reference/packaging/native-image/index.html)
- [Introducing GraalVM Native Images](https://docs.spring.io/spring-boot/reference/packaging/native-image/introducing-graalvm-native-images.html)
- [Advanced Native Images Topics](https://docs.spring.io/spring-boot/reference/packaging/native-image/advanced-topics.html)
- [Checkpoint and Restore With the JVM](https://docs.spring.io/spring-boot/reference/packaging/checkpoint-restore.html)
- [Container Images](https://docs.spring.io/spring-boot/reference/packaging/container-images/index.html)
- [Efficient Container Images](https://docs.spring.io/spring-boot/reference/packaging/container-images/efficient-images.html)
- [Dockerfiles](https://docs.spring.io/spring-boot/reference/packaging/container-images/dockerfiles.html)
- [Cloud Native Buildpacks](https://docs.spring.io/spring-boot/reference/packaging/container-images/cloud-native-buildpacks.html)
- [Production-ready Features](https://docs.spring.io/spring-boot/reference/actuator/index.html)
- [Enabling Production-ready Features](https://docs.spring.io/spring-boot/reference/actuator/enabling.html)
- [Endpoints](https://docs.spring.io/spring-boot/reference/actuator/endpoints.html)
- [Monitoring and Management Over HTTP](https://docs.spring.io/spring-boot/reference/actuator/monitoring.html)
- [Monitoring and Management over JMX](https://docs.spring.io/spring-boot/reference/actuator/jmx.html)
- [Observability](https://docs.spring.io/spring-boot/reference/actuator/observability.html)
- [Loggers](https://docs.spring.io/spring-boot/reference/actuator/loggers.html)
- [Metrics](https://docs.spring.io/spring-boot/reference/actuator/metrics.html)
- [Tracing](https://docs.spring.io/spring-boot/reference/actuator/tracing.html)
- [Auditing](https://docs.spring.io/spring-boot/reference/actuator/auditing.html)
- [Recording HTTP Exchanges](https://docs.spring.io/spring-boot/reference/actuator/http-exchanges.html)
- [Process Monitoring](https://docs.spring.io/spring-boot/reference/actuator/process-monitoring.html)
- [Cloud Foundry Support](https://docs.spring.io/spring-boot/reference/actuator/cloud-foundry.html)
- [How-to Guides](https://docs.spring.io/spring-boot/how-to/index.html)
- [Spring Boot Application](https://docs.spring.io/spring-boot/how-to/application.html)
- [Properties and Configuration](https://docs.spring.io/spring-boot/how-to/properties-and-configuration.html)
- [Embedded Web Servers](https://docs.spring.io/spring-boot/how-to/webserver.html)
- [Spring MVC](https://docs.spring.io/spring-boot/how-to/spring-mvc.html)
- [Jersey](https://docs.spring.io/spring-boot/how-to/jersey.html)
- [HTTP Clients](https://docs.spring.io/spring-boot/how-to/http-clients.html)
- [Logging](https://docs.spring.io/spring-boot/how-to/logging.html)
- [Data Access](https://docs.spring.io/spring-boot/how-to/data-access.html)
- [Database Initialization](https://docs.spring.io/spring-boot/how-to/data-initialization.html)
- [NoSQL](https://docs.spring.io/spring-boot/how-to/nosql.html)
- [Messaging](https://docs.spring.io/spring-boot/how-to/messaging.html)
- [Batch Applications](https://docs.spring.io/spring-boot/how-to/batch.html)
- [Actuator](https://docs.spring.io/spring-boot/how-to/actuator.html)
- [Security](https://docs.spring.io/spring-boot/how-to/security.html)
- [Hot Swapping](https://docs.spring.io/spring-boot/how-to/hotswapping.html)
- [Testing](https://docs.spring.io/spring-boot/how-to/testing.html)
- [Build](https://docs.spring.io/spring-boot/how-to/build.html)
- [Ahead-of-Time Processing](https://docs.spring.io/spring-boot/how-to/aot.html)
- [GraalVM Native Applications](https://docs.spring.io/spring-boot/how-to/native-image/index.html)
- [Developing Your First GraalVM Native Application](https://docs.spring.io/spring-boot/how-to/native-image/developing-your-first-application.html)
- [Testing GraalVM Native Images](https://docs.spring.io/spring-boot/how-to/native-image/testing-native-applications.html)
- [AOT Cache](https://docs.spring.io/spring-boot/how-to/aot-cache.html)
- [Deploying Spring Boot Applications](https://docs.spring.io/spring-boot/how-to/deployment/index.html)
- [Traditional Deployment](https://docs.spring.io/spring-boot/how-to/deployment/traditional-deployment.html)
- [Deploying to the Cloud](https://docs.spring.io/spring-boot/how-to/deployment/cloud.html)
- [Installing Spring Boot Applications](https://docs.spring.io/spring-boot/how-to/deployment/installing.html)
- [Docker Compose](https://docs.spring.io/spring-boot/how-to/docker-compose.html)
- [Build Tool Plugins](https://docs.spring.io/spring-boot/build-tool-plugin/index.html)
- [Maven Plugin](https://docs.spring.io/spring-boot/maven-plugin/index.html)
- [Getting Started](https://docs.spring.io/spring-boot/maven-plugin/getting-started.html)
- [Using the Plugin](https://docs.spring.io/spring-boot/maven-plugin/using.html)
- [Goals](https://docs.spring.io/spring-boot/maven-plugin/goals.html)
- [Packaging Executable Archives](https://docs.spring.io/spring-boot/maven-plugin/packaging.html)
- [Packaging OCI Images](https://docs.spring.io/spring-boot/maven-plugin/build-image.html)
- [Running your Application with Maven](https://docs.spring.io/spring-boot/maven-plugin/run.html)
- [Ahead-of-Time Processing](https://docs.spring.io/spring-boot/maven-plugin/aot.html)
- [Running Integration Tests](https://docs.spring.io/spring-boot/maven-plugin/integration-tests.html)
- [Integrating with Actuator](https://docs.spring.io/spring-boot/maven-plugin/build-info.html)
- [Help Information](https://docs.spring.io/spring-boot/maven-plugin/help.html)
- [Gradle Plugin](https://docs.spring.io/spring-boot/gradle-plugin/index.html)
- [Getting Started](https://docs.spring.io/spring-boot/gradle-plugin/getting-started.html)
- [Managing Dependencies](https://docs.spring.io/spring-boot/gradle-plugin/managing-dependencies.html)
- [Packaging Executable Archives](https://docs.spring.io/spring-boot/gradle-plugin/packaging.html)
- [Packaging OCI Images](https://docs.spring.io/spring-boot/gradle-plugin/packaging-oci-image.html)
- [Publishing your Application](https://docs.spring.io/spring-boot/gradle-plugin/publishing.html)
- [Running your Application with Gradle](https://docs.spring.io/spring-boot/gradle-plugin/running.html)
- [Ahead-of-Time Processing](https://docs.spring.io/spring-boot/gradle-plugin/aot.html)
- [Integrating with Actuator](https://docs.spring.io/spring-boot/gradle-plugin/integrating-with-actuator.html)
- [Reacting to Other Plugins](https://docs.spring.io/spring-boot/gradle-plugin/reacting.html)
- [Spring Boot AntLib Module](https://docs.spring.io/spring-boot/build-tool-plugin/antlib.html)
- [Supporting Other Build Systems](https://docs.spring.io/spring-boot/build-tool-plugin/other-build-systems.html)
- [Spring Boot CLI](https://docs.spring.io/spring-boot/cli/index.html)
- [Installing the CLI](https://docs.spring.io/spring-boot/cli/installation.html)
- [Using the CLI](https://docs.spring.io/spring-boot/cli/using-the-cli.html)
- Rest APIs
- [Actuator](https://docs.spring.io/spring-boot/api/rest/actuator/index.html)
- [Audit Events (`auditevents`)](https://docs.spring.io/spring-boot/api/rest/actuator/auditevents.html)
- [Beans (`beans`)](https://docs.spring.io/spring-boot/api/rest/actuator/beans.html)
- [Caches (`caches`)](https://docs.spring.io/spring-boot/api/rest/actuator/caches.html)
- [Conditions Evaluation Report (`conditions`)](https://docs.spring.io/spring-boot/api/rest/actuator/conditions.html)
- [Configuration Properties (`configprops`)](https://docs.spring.io/spring-boot/api/rest/actuator/configprops.html)
- [Environment (`env`)](https://docs.spring.io/spring-boot/api/rest/actuator/env.html)
- [Flyway (`flyway`)](https://docs.spring.io/spring-boot/api/rest/actuator/flyway.html)
- [Health (`health`)](https://docs.spring.io/spring-boot/api/rest/actuator/health.html)
- [Heap Dump (`heapdump`)](https://docs.spring.io/spring-boot/api/rest/actuator/heapdump.html)
- [HTTP Exchanges (`httpexchanges`)](https://docs.spring.io/spring-boot/api/rest/actuator/httpexchanges.html)
- [Info (`info`)](https://docs.spring.io/spring-boot/api/rest/actuator/info.html)
- [Spring Integration Graph (`integrationgraph`)](https://docs.spring.io/spring-boot/api/rest/actuator/integrationgraph.html)
- [Liquibase (`liquibase`)](https://docs.spring.io/spring-boot/api/rest/actuator/liquibase.html)
- [Log File (`logfile`)](https://docs.spring.io/spring-boot/api/rest/actuator/logfile.html)
- [Loggers (`loggers`)](https://docs.spring.io/spring-boot/api/rest/actuator/loggers.html)
- [Mappings (`mappings`)](https://docs.spring.io/spring-boot/api/rest/actuator/mappings.html)
- [Metrics (`metrics`)](https://docs.spring.io/spring-boot/api/rest/actuator/metrics.html)
- [Prometheus (`prometheus`)](https://docs.spring.io/spring-boot/api/rest/actuator/prometheus.html)
- [Quartz (`quartz`)](https://docs.spring.io/spring-boot/api/rest/actuator/quartz.html)
- [Software Bill of Materials (`sbom`)](https://docs.spring.io/spring-boot/api/rest/actuator/sbom.html)
- [Scheduled Tasks (`scheduledtasks`)](https://docs.spring.io/spring-boot/api/rest/actuator/scheduledtasks.html)
- [Sessions (`sessions`)](https://docs.spring.io/spring-boot/api/rest/actuator/sessions.html)
- [Shutdown (`shutdown`)](https://docs.spring.io/spring-boot/api/rest/actuator/shutdown.html)
- [Application Startup (`startup`)](https://docs.spring.io/spring-boot/api/rest/actuator/startup.html)
- [Thread Dump (`threaddump`)](https://docs.spring.io/spring-boot/api/rest/actuator/threaddump.html)
- Java APIs
- [Spring Boot](https://docs.spring.io/spring-boot/api/java/index.html)
- [Gradle Plugin](https://docs.spring.io/spring-boot/gradle-plugin/api/java/index.html)
- [Maven Plugin](https://docs.spring.io/spring-boot/maven-plugin/api/java/index.html)
- Kotlin APIs
- [Spring Boot](https://docs.spring.io/spring-boot/api/kotlin/index.html)
- Specifications
- [Configuration Metadata](https://docs.spring.io/spring-boot/specification/configuration-metadata/index.html)
- [Metadata Format](https://docs.spring.io/spring-boot/specification/configuration-metadata/format.html)
- [Providing Manual Hints](https://docs.spring.io/spring-boot/specification/configuration-metadata/manual-hints.html)
- [Generating Your Own Metadata by Using the Annotation Processor](https://docs.spring.io/spring-boot/specification/configuration-metadata/annotation-processor.html)
- [The Executable Jar Format](https://docs.spring.io/spring-boot/specification/executable-jar/index.html)
- [Nested JARs](https://docs.spring.io/spring-boot/specification/executable-jar/nested-jars.html)
- [Spring Bootâs âNestedJarFileâ Class](https://docs.spring.io/spring-boot/specification/executable-jar/jarfile-class.html)
- [Launching Executable Jars](https://docs.spring.io/spring-boot/specification/executable-jar/launching.html)
- [PropertiesLauncher Features](https://docs.spring.io/spring-boot/specification/executable-jar/property-launcher.html)
- [Executable Jar Restrictions](https://docs.spring.io/spring-boot/specification/executable-jar/restrictions.html)
- [Alternative Single Jar Solutions](https://docs.spring.io/spring-boot/specification/executable-jar/alternatives.html)
- Appendix
- [Common Application Properties](https://docs.spring.io/spring-boot/appendix/application-properties/index.html)
- [Deprecated Application Properties](https://docs.spring.io/spring-boot/appendix/deprecated-application-properties/index.html)
- [Auto-configuration Classes](https://docs.spring.io/spring-boot/appendix/auto-configuration-classes/index.html)
- [spring-boot-activemq](https://docs.spring.io/spring-boot/appendix/auto-configuration-classes/spring-boot-activemq.html)
- [spring-boot-actuator-autoconfigure](https://docs.spring.io/spring-boot/appendix/auto-configuration-classes/spring-boot-actuator-autoconfigure.html)
- [spring-boot-amqp](https://docs.spring.io/spring-boot/appendix/auto-configuration-classes/spring-boot-amqp.html)
- [spring-boot-artemis](https://docs.spring.io/spring-boot/appendix/auto-configuration-classes/spring-boot-artemis.html)
- [spring-boot-autoconfigure](https://docs.spring.io/spring-boot/appendix/auto-configuration-classes/spring-boot-autoconfigure.html)
- [spring-boot-batch](https://docs.spring.io/spring-boot/appendix/auto-configuration-classes/spring-boot-batch.html)
- [spring-boot-batch-jdbc](https://docs.spring.io/spring-boot/appendix/auto-configuration-classes/spring-boot-batch-jdbc.html)
- [spring-boot-cache](https://docs.spring.io/spring-boot/appendix/auto-configuration-classes/spring-boot-cache.html)
- [spring-boot-cassandra](https://docs.spring.io/spring-boot/appendix/auto-configuration-classes/spring-boot-cassandra.html)
- [spring-boot-cloudfoundry](https://docs.spring.io/spring-boot/appendix/auto-configuration-classes/spring-boot-cloudfoundry.html)
- [spring-boot-couchbase](https://docs.spring.io/spring-boot/appendix/auto-configuration-classes/spring-boot-couchbase.html)
- [spring-boot-data-cassandra](https://docs.spring.io/spring-boot/appendix/auto-configuration-classes/spring-boot-data-cassandra.html)
- [spring-boot-data-commons](https://docs.spring.io/spring-boot/appendix/auto-configuration-classes/spring-boot-data-commons.html)
- [spring-boot-data-couchbase](https://docs.spring.io/spring-boot/appendix/auto-configuration-classes/spring-boot-data-couchbase.html)
- [spring-boot-data-elasticsearch](https://docs.spring.io/spring-boot/appendix/auto-configuration-classes/spring-boot-data-elasticsearch.html)
- [spring-boot-data-jdbc](https://docs.spring.io/spring-boot/appendix/auto-configuration-classes/spring-boot-data-jdbc.html)
- [spring-boot-data-jpa](https://docs.spring.io/spring-boot/appendix/auto-configuration-classes/spring-boot-data-jpa.html)
- [spring-boot-data-ldap](https://docs.spring.io/spring-boot/appendix/auto-configuration-classes/spring-boot-data-ldap.html)
- [spring-boot-data-mongodb](https://docs.spring.io/spring-boot/appendix/auto-configuration-classes/spring-boot-data-mongodb.html)
- [spring-boot-data-neo4j](https://docs.spring.io/spring-boot/appendix/auto-configuration-classes/spring-boot-data-neo4j.html)
- [spring-boot-data-r2dbc](https://docs.spring.io/spring-boot/appendix/auto-configuration-classes/spring-boot-data-r2dbc.html)
- [spring-boot-data-redis](https://docs.spring.io/spring-boot/appendix/auto-configuration-classes/spring-boot-data-redis.html)
- [spring-boot-data-rest](https://docs.spring.io/spring-boot/appendix/auto-configuration-classes/spring-boot-data-rest.html)
- [spring-boot-devtools](https://docs.spring.io/spring-boot/appendix/auto-configuration-classes/spring-boot-devtools.html)
- [spring-boot-elasticsearch](https://docs.spring.io/spring-boot/appendix/auto-configuration-classes/spring-boot-elasticsearch.html)
- [spring-boot-flyway](https://docs.spring.io/spring-boot/appendix/auto-configuration-classes/spring-boot-flyway.html)
- [spring-boot-freemarker](https://docs.spring.io/spring-boot/appendix/auto-configuration-classes/spring-boot-freemarker.html)
- [spring-boot-graphql](https://docs.spring.io/spring-boot/appendix/auto-configuration-classes/spring-boot-graphql.html)
- [spring-boot-groovy-templates](https://docs.spring.io/spring-boot/appendix/auto-configuration-classes/spring-boot-groovy-templates.html)
- [spring-boot-gson](https://docs.spring.io/spring-boot/appendix/auto-configuration-classes/spring-boot-gson.html)
- [spring-boot-h2console](https://docs.spring.io/spring-boot/appendix/auto-configuration-classes/spring-boot-h2console.html)
- [spring-boot-hateoas](https://docs.spring.io/spring-boot/appendix/auto-configuration-classes/spring-boot-hateoas.html)
- [spring-boot-hazelcast](https://docs.spring.io/spring-boot/appendix/auto-configuration-classes/spring-boot-hazelcast.html)
- [spring-boot-health](https://docs.spring.io/spring-boot/appendix/auto-configuration-classes/spring-boot-health.html)
- [spring-boot-hibernate](https://docs.spring.io/spring-boot/appendix/auto-configuration-classes/spring-boot-hibernate.html)
- [spring-boot-http-client](https://docs.spring.io/spring-boot/appendix/auto-configuration-classes/spring-boot-http-client.html)
- [spring-boot-http-codec](https://docs.spring.io/spring-boot/appendix/auto-configuration-classes/spring-boot-http-codec.html)
- [spring-boot-http-converter](https://docs.spring.io/spring-boot/appendix/auto-configuration-classes/spring-boot-http-converter.html)
- [spring-boot-integration](https://docs.spring.io/spring-boot/appendix/auto-configuration-classes/spring-boot-integration.html)
- [spring-boot-jackson](https://docs.spring.io/spring-boot/appendix/auto-configuration-classes/spring-boot-jackson.html)
- [spring-boot-jackson2](https://docs.spring.io/spring-boot/appendix/auto-configuration-classes/spring-boot-jackson2.html)
- [spring-boot-jdbc](https://docs.spring.io/spring-boot/appendix/auto-configuration-classes/spring-boot-jdbc.html)
- [spring-boot-jersey](https://docs.spring.io/spring-boot/appendix/auto-configuration-classes/spring-boot-jersey.html)
- [spring-boot-jetty](https://docs.spring.io/spring-boot/appendix/auto-configuration-classes/spring-boot-jetty.html)
- [spring-boot-jms](https://docs.spring.io/spring-boot/appendix/auto-configuration-classes/spring-boot-jms.html)
- [spring-boot-jooq](https://docs.spring.io/spring-boot/appendix/auto-configuration-classes/spring-boot-jooq.html)
- [spring-boot-jsonb](https://docs.spring.io/spring-boot/appendix/auto-configuration-classes/spring-boot-jsonb.html)
- [spring-boot-kafka](https://docs.spring.io/spring-boot/appendix/auto-configuration-classes/spring-boot-kafka.html)
- [spring-boot-kotlinx-serialization-json](https://docs.spring.io/spring-boot/appendix/auto-configuration-classes/spring-boot-kotlinx-serialization-json.html)
- [spring-boot-ldap](https://docs.spring.io/spring-boot/appendix/auto-configuration-classes/spring-boot-ldap.html)
- [spring-boot-liquibase](https://docs.spring.io/spring-boot/appendix/auto-configuration-classes/spring-boot-liquibase.html)
- [spring-boot-mail](https://docs.spring.io/spring-boot/appendix/auto-configuration-classes/spring-boot-mail.html)
- [spring-boot-micrometer-metrics](https://docs.spring.io/spring-boot/appendix/auto-configuration-classes/spring-boot-micrometer-metrics.html)
- [spring-boot-micrometer-observation](https://docs.spring.io/spring-boot/appendix/auto-configuration-classes/spring-boot-micrometer-observation.html)
- [spring-boot-micrometer-tracing](https://docs.spring.io/spring-boot/appendix/auto-configuration-classes/spring-boot-micrometer-tracing.html)
- [spring-boot-micrometer-tracing-brave](https://docs.spring.io/spring-boot/appendix/auto-configuration-classes/spring-boot-micrometer-tracing-brave.html)
- [spring-boot-micrometer-tracing-opentelemetry](https://docs.spring.io/spring-boot/appendix/auto-configuration-classes/spring-boot-micrometer-tracing-opentelemetry.html)
- [spring-boot-mongodb](https://docs.spring.io/spring-boot/appendix/auto-configuration-classes/spring-boot-mongodb.html)
- [spring-boot-mustache](https://docs.spring.io/spring-boot/appendix/auto-configuration-classes/spring-boot-mustache.html)
- [spring-boot-neo4j](https://docs.spring.io/spring-boot/appendix/auto-configuration-classes/spring-boot-neo4j.html)
- [spring-boot-netty](https://docs.spring.io/spring-boot/appendix/auto-configuration-classes/spring-boot-netty.html)
- [spring-boot-opentelemetry](https://docs.spring.io/spring-boot/appendix/auto-configuration-classes/spring-boot-opentelemetry.html)
- [spring-boot-persistence](https://docs.spring.io/spring-boot/appendix/auto-configuration-classes/spring-boot-persistence.html)
- [spring-boot-pulsar](https://docs.spring.io/spring-boot/appendix/auto-configuration-classes/spring-boot-pulsar.html)
- [spring-boot-quartz](https://docs.spring.io/spring-boot/appendix/auto-configuration-classes/spring-boot-quartz.html)
- [spring-boot-r2dbc](https://docs.spring.io/spring-boot/appendix/auto-configuration-classes/spring-boot-r2dbc.html)
- [spring-boot-reactor](https://docs.spring.io/spring-boot/appendix/auto-configuration-classes/spring-boot-reactor.html)
- [spring-boot-reactor-netty](https://docs.spring.io/spring-boot/appendix/auto-configuration-classes/spring-boot-reactor-netty.html)
- [spring-boot-restclient](https://docs.spring.io/spring-boot/appendix/auto-configuration-classes/spring-boot-restclient.html)
- [spring-boot-resttestclient](https://docs.spring.io/spring-boot/appendix/auto-configuration-classes/spring-boot-resttestclient.html)
- [spring-boot-rsocket](https://docs.spring.io/spring-boot/appendix/auto-configuration-classes/spring-boot-rsocket.html)
- [spring-boot-security](https://docs.spring.io/spring-boot/appendix/auto-configuration-classes/spring-boot-security.html)
- [spring-boot-security-oauth2-authorization-server](https://docs.spring.io/spring-boot/appendix/auto-configuration-classes/spring-boot-security-oauth2-authorization-server.html)
- [spring-boot-security-oauth2-client](https://docs.spring.io/spring-boot/appendix/auto-configuration-classes/spring-boot-security-oauth2-client.html)
- [spring-boot-security-oauth2-resource-server](https://docs.spring.io/spring-boot/appendix/auto-configuration-classes/spring-boot-security-oauth2-resource-server.html)
- [spring-boot-security-saml2](https://docs.spring.io/spring-boot/appendix/auto-configuration-classes/spring-boot-security-saml2.html)
- [spring-boot-sendgrid](https://docs.spring.io/spring-boot/appendix/auto-configuration-classes/spring-boot-sendgrid.html)
- [spring-boot-servlet](https://docs.spring.io/spring-boot/appendix/auto-configuration-classes/spring-boot-servlet.html)
- [spring-boot-session](https://docs.spring.io/spring-boot/appendix/auto-configuration-classes/spring-boot-session.html)
- [spring-boot-session-data-redis](https://docs.spring.io/spring-boot/appendix/auto-configuration-classes/spring-boot-session-data-redis.html)
- [spring-boot-session-jdbc](https://docs.spring.io/spring-boot/appendix/auto-configuration-classes/spring-boot-session-jdbc.html)
- [spring-boot-testcontainers](https://docs.spring.io/spring-boot/appendix/auto-configuration-classes/spring-boot-testcontainers.html)
- [spring-boot-thymeleaf](https://docs.spring.io/spring-boot/appendix/auto-configuration-classes/spring-boot-thymeleaf.html)
- [spring-boot-tomcat](https://docs.spring.io/spring-boot/appendix/auto-configuration-classes/spring-boot-tomcat.html)
- [spring-boot-transaction](https://docs.spring.io/spring-boot/appendix/auto-configuration-classes/spring-boot-transaction.html)
- [spring-boot-validation](https://docs.spring.io/spring-boot/appendix/auto-configuration-classes/spring-boot-validation.html)
- [spring-boot-webclient](https://docs.spring.io/spring-boot/appendix/auto-configuration-classes/spring-boot-webclient.html)
- [spring-boot-webflux](https://docs.spring.io/spring-boot/appendix/auto-configuration-classes/spring-boot-webflux.html)
- [spring-boot-webmvc](https://docs.spring.io/spring-boot/appendix/auto-configuration-classes/spring-boot-webmvc.html)
- [spring-boot-webservices](https://docs.spring.io/spring-boot/appendix/auto-configuration-classes/spring-boot-webservices.html)
- [spring-boot-websocket](https://docs.spring.io/spring-boot/appendix/auto-configuration-classes/spring-boot-websocket.html)
- [spring-boot-zipkin](https://docs.spring.io/spring-boot/appendix/auto-configuration-classes/spring-boot-zipkin.html)
- [Test Auto-configuration Annotations](https://docs.spring.io/spring-boot/appendix/test-auto-configuration/index.html)
- [Test Slices](https://docs.spring.io/spring-boot/appendix/test-auto-configuration/slices.html)
- [Dependency Versions](https://docs.spring.io/spring-boot/appendix/dependency-versions/index.html)
- [Managed Dependency Coordinates](https://docs.spring.io/spring-boot/appendix/dependency-versions/coordinates.html)
- [Version Properties](https://docs.spring.io/spring-boot/appendix/dependency-versions/properties.html)
Search
[Edit this Page](https://github.com/spring-projects/spring-boot/blob/v4.0.5/documentation/spring-boot-docs/src/docs/antora/modules/reference/pages/features/external-config.adoc)
[GitHub Project](https://github.com/spring-projects/spring-boot "GitHub")
[Stack Overflow](https://stackoverflow.com/tags/spring-boot)
- [Spring Boot](https://docs.spring.io/spring-boot/index.html)
- [Reference](https://docs.spring.io/spring-boot/reference/index.html)
- [Core Features](https://docs.spring.io/spring-boot/reference/features/index.html)
- [Externalized Configuration](https://docs.spring.io/spring-boot/reference/features/external-config.html)
# 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 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`](https://docs.spring.io/spring-framework/docs/7.0.x/javadoc-api/org/springframework/beans/factory/annotation/Value.html) annotation, accessed through Springâs [`Environment`](https://docs.spring.io/spring-framework/docs/7.0.x/javadoc-api/org/springframework/core/env/Environment.html) abstraction, or be [bound to structured objects](https://docs.spring.io/spring-boot/reference/features/external-config.html#features.external-config.typesafe-configuration-properties) through [`@ConfigurationProperties`](https://docs.spring.io/spring-boot/4.0.5/api/java/org/springframework/boot/context/properties/ConfigurationProperties.html).
Spring Boot uses a very particular [`PropertySource`](https://docs.spring.io/spring-framework/docs/7.0.x/javadoc-api/org/springframework/core/env/PropertySource.html) 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:
1. Default properties (specified by setting [`SpringApplication.setDefaultProperties(Map)`](https://docs.spring.io/spring-boot/4.0.5/api/java/org/springframework/boot/SpringApplication.html#setDefaultProperties\(java.util.Map\))).
2. [`@PropertySource`](https://docs.spring.io/spring-framework/docs/7.0.x/javadoc-api/org/springframework/context/annotation/PropertySource.html) annotations on your [`@Configuration`](https://docs.spring.io/spring-framework/docs/7.0.x/javadoc-api/org/springframework/context/annotation/Configuration.html) classes. Please note that such property sources are not added to the [`Environment`](https://docs.spring.io/spring-framework/docs/7.0.x/javadoc-api/org/springframework/core/env/Environment.html) 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.
3. Config data (such as `application.properties` files).
4. A [`RandomValuePropertySource`](https://docs.spring.io/spring-boot/4.0.5/api/java/org/springframework/boot/env/RandomValuePropertySource.html) that has properties only in `random.*`.
5. OS environment variables.
6. Java System properties (`System.getProperties()`).
7. JNDI attributes from `java:comp/env`.
8. [`ServletContext`](https://jakarta.ee/specifications/servlet/6.1/apidocs/jakarta.servlet/jakarta/servlet/ServletContext.html) init parameters.
9. [`ServletConfig`](https://jakarta.ee/specifications/servlet/6.1/apidocs/jakarta.servlet/jakarta/servlet/ServletConfig.html) init parameters.
10. Properties from `SPRING_APPLICATION_JSON` (inline JSON embedded in an environment variable or system property).
11. Command line arguments.
12. `properties` attribute on your tests. Available on [`@SpringBootTest`](https://docs.spring.io/spring-boot/4.0.5/api/java/org/springframework/boot/test/context/SpringBootTest.html) and the [test annotations for testing a particular slice of your application](https://docs.spring.io/spring-boot/reference/testing/spring-boot-applications.html#testing.spring-boot-applications.autoconfigured-tests).
13. [`@DynamicPropertySource`](https://docs.spring.io/spring-framework/docs/7.0.x/javadoc-api/org/springframework/test/context/DynamicPropertySource.html) annotations in your tests.
14. [`@TestPropertySource`](https://docs.spring.io/spring-framework/docs/7.0.x/javadoc-api/org/springframework/test/context/TestPropertySource.html) annotations on your tests.
15. [Devtools global settings properties](https://docs.spring.io/spring-boot/reference/using/devtools.html#using.devtools.globalsettings) in the `$HOME/.config/spring-boot` directory when devtools is active.
Config data files are considered in the following order:
1. [Application properties](https://docs.spring.io/spring-boot/reference/features/external-config.html#features.external-config.files) packaged inside your jar (`application.properties` and YAML variants).
2. [Profile-specific application properties](https://docs.spring.io/spring-boot/reference/features/external-config.html#features.external-config.files.profile-specific) packaged inside your jar (`application-{profile}.properties` and YAML variants).
3. [Application properties](https://docs.spring.io/spring-boot/reference/features/external-config.html#features.external-config.files) outside of your packaged jar (`application.properties` and YAML variants).
4. [Profile-specific application properties](https://docs.spring.io/spring-boot/reference/features/external-config.html#features.external-config.files.profile-specific) 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 YAML format in the same location, `.properties` takes precedence. |
| | |
|---|---|
| | 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](https://docs.spring.io/spring-boot/reference/features/external-config.html#features.external-config.typesafe-configuration-properties.relaxed-binding.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. |
To provide a concrete example, suppose you develop a [`@Component`](https://docs.spring.io/spring-framework/docs/7.0.x/javadoc-api/org/springframework/stereotype/Component.html) that uses a `name` property, as shown in the following example:
- Java
- Kotlin
```
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](https://docs.spring.io/spring-boot/reference/actuator/endpoints.html) section for details. |
## Accessing Command Line Properties
By default, [`SpringApplication`](https://docs.spring.io/spring-boot/4.0.5/api/java/org/springframework/boot/SpringApplication.html) 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`](https://docs.spring.io/spring-framework/docs/7.0.x/javadoc-api/org/springframework/core/env/Environment.html). 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`](https://docs.spring.io/spring-framework/docs/7.0.x/javadoc-api/org/springframework/core/env/Environment.html), you can disable them by using `SpringApplication.setAddCommandLineProperties(false)`.
## 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`](https://docs.spring.io/spring-framework/docs/7.0.x/javadoc-api/org/springframework/core/env/Environment.html).
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`](https://docs.spring.io/spring-framework/docs/7.0.x/javadoc-api/org/springframework/core/env/Environment.html).
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`](https://docs.spring.io/spring-framework/docs/7.0.x/javadoc-api/org/springframework/core/env/PropertySourcesPropertyResolver.html) treats `null` properties as missing values. This means that the JSON cannot override properties from lower order property sources with a `null` value. |
## External Application Properties
Spring Boot will automatically find and load `application.properties` and `application.yaml` files from the following locations when your application starts:
1. From the classpath
1. The classpath root
2. The classpath `/config` package
2. From the current directory
1. The current directory
2. The `config/` subdirectory in the current directory
3. Immediate 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 [`PropertySource`](https://docs.spring.io/spring-framework/docs/7.0.x/javadoc-api/org/springframework/core/env/PropertySource.html) instances to the Spring [`Environment`](https://docs.spring.io/spring-framework/docs/7.0.x/javadoc-api/org/springframework/core/env/Environment.html).
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
```
| | |
|---|---|
| | Use the prefix `optional:` if the [locations are optional](https://docs.spring.io/spring-boot/reference/features/external-config.html#features.external-config.files.optional-prefix) and you do not mind if they do not 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 imported directly.
| | |
|---|---|
| | Both directory and file location values are also expanded to check for [profile-specific files](https://docs.spring.io/spring-boot/reference/features/external-config.html#features.external-config.files.profile-specific). 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](https://docs.spring.io/spring-boot/reference/features/external-config.html#features.external-config.files.profile-specific) 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:
1. `optional:classpath:custom-config/`
2. `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:
1. `optional:classpath:/;optional:classpath:/config/`
2. `optional:file:./;optional:file:./config/;optional:file:./config/*/`
3. `optional:classpath:custom-config/`
4. `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.
### Optional Locations
By default, when a specified config data location does not exist, Spring Boot will throw a [`ConfigDataLocationNotFoundException`](https://docs.spring.io/spring-boot/4.0.5/api/java/org/springframework/boot/context/config/ConfigDataLocationNotFoundException.html) 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`](https://docs.spring.io/spring-boot/reference/features/external-config.html#features.external-config.files.importing) 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 [`ConfigDataLocationNotFoundException`](https://docs.spring.io/spring-boot/4.0.5/api/java/org/springframework/boot/context/config/ConfigDataLocationNotFoundException.html) errors 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.
### 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. |
### 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.yaml` and `application-prod.yaml` 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](https://docs.spring.io/spring-boot/reference/features/external-config.html#features.external-config.files.location-groups) 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: When we have a `spring.config.location` of `classpath:/cfg/,classpath:/ext/` we process all `/cfg` files before all `/ext` files: `/cfg/application-live.properties` `/ext/application-prod.properties` `/ext/application-live.properties` When we have `classpath:/cfg/;classpath:/ext/` instead (with a `;` delimiter) we process `/cfg` and `/ext` at the same level: `/ext/application-prod.properties` `/cfg/application-live.properties` `/ext/application-live.properties` |
The [`Environment`](https://docs.spring.io/spring-framework/docs/7.0.x/javadoc-api/org/springframework/core/env/Environment.html) 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 have already directly [imported](https://docs.spring.io/spring-boot/reference/features/external-config.html#features.external-config.files.importing) a profile specific property files then it will not be imported a second time. |
### 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
- YAML
```
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.
#### Using âFixedâ and âImport Relativeâ Locations
Imports may be specified as *fixed* or *import relative* locations. A fixed location always resolves to the same underlying resource, regardless of where the `spring.config.import` property is declared. An import relative location resolves relative to the file that declares the `spring.config.import` property.
A location starting with a forward slash (`/`) or a URL style prefix (`file:`, `classpath:`, etc.) is considered fixed. All other locations are considered import relative.
| | |
|---|---|
| | `optional:` prefixes are not considered when determining if a location is fixed or import relative. |
As an example, say we have a `/demo` directory containing our `application.jar` file. We might add a `/demo/application.properties` file with the following content:
```
spring.config.import=optional:core/core.properties
```
This is an import relative location and so will attempt to load the file `/demo/core/core.properties` if it exists.
If `/demo/core/core.properties` has the following content:
```
spring.config.import=optional:extra/extra.properties
```
It will attempt to load `/demo/core/extra/extra.properties`. The `optional:extra/extra.properties` is relative to `/demo/core/core.properties` so the full directory is `/demo/core/` + `extra/extra.properties`.
#### Property Ordering
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
- YAML
```
spring.config.import=my.properties
my.property=value
```
```
spring:
config:
import: "my.properties"
my:
property: "value"
```
- Properties
- YAML
```
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.
| | |
|---|---|
| | When appropriate, [Profile-specific variants](https://docs.spring.io/spring-boot/reference/features/external-config.html#features.external-config.files.profile-specific) are also considered for import. The example above would import both `my.properties` as well as any `my-<profile>.properties` variants. |
| | |
|---|---|
| | 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](https://docs.spring.io/spring-boot/reference/features/external-config.html#features.external-config.files.configtree). 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`](https://docs.spring.io/spring-boot/4.0.5/api/java/org/springframework/boot/context/config/ConfigDataLocationResolver.html) and [`ConfigDataLoader`](https://docs.spring.io/spring-boot/4.0.5/api/java/org/springframework/boot/context/config/ConfigDataLoader.html) classes in the `org.springframework.boot.context.config` package. |
### 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
- YAML
```
spring.config.import=file:/etc/config/myconfig[.yaml]
```
```
spring:
config:
import: "file:/etc/config/myconfig[.yaml]"
```
### Using Environment Variables
When running applications on a cloud platform (such as Kubernetes) you often need to read config values that the platform supplies. You can either use environment variables for such purpose, or you can use [configuration trees](https://docs.spring.io/spring-boot/reference/features/external-config.html#features.external-config.files.configtree).
You can even store whole configurations in properties or yaml format in (multiline) environment variables and load them using the `env:` prefix. Assume thereâs an environment variable called `MY_CONFIGURATION` with this content:
```
my.name=Service1
my.cluster=Cluster1
```
Using the `env:` prefix it is possible to import all properties from this variable:
- Properties
- YAML
```
spring.config.import=env:MY_CONFIGURATION
```
```
spring:
config:
import: "env:MY_CONFIGURATION"
```
| | |
|---|---|
| | This feature also supports [specifying the extension](https://docs.spring.io/spring-boot/reference/features/external-config.html#features.external-config.files.importing-extensionless). The default extension is `.properties`. |
### Using Configuration Trees
Storing config values in environment variables has 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`](https://kubernetes.io/docs/tasks/configure-pod-container/configure-pod-configmap/#populate-a-volume-with-data-stored-in-a-configmap) and [`Secrets`](https://kubernetes.io/docs/concepts/configuration/secret/#using-secrets-as-files-from-a-pod).
There are two common volume mount patterns that can be used:
1. A single file contains a complete set of properties (usually written as YAML).
2. 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](https://docs.spring.io/spring-boot/reference/features/external-config.html#features.external-config.files.importing). 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:
- Properties
- YAML
```
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`](https://docs.spring.io/spring-framework/docs/7.0.x/javadoc-api/org/springframework/core/env/Environment.html) in the usual way.
| | |
|---|---|
| | The names of the folders and files under the config tree form the property name. In the above example, to access the properties as `username` and `password`, you can set `spring.config.import` to `optional:configtree:/etc/config/myapp`. |
| | |
|---|---|
| | Filenames with dot notation are also correctly mapped. For example, in the above example, a file named `myapp.username` in `/etc/config` would result in a `myapp.username` property in the [`Environment`](https://docs.spring.io/spring-framework/docs/7.0.x/javadoc-api/org/springframework/core/env/Environment.html). |
| | |
|---|---|
| | Configuration tree values can be bound to both string [`String`](https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/String.html) 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. As with a non-wildcard import, the names of the folders and files under each config tree form the property name.
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:
- Properties
- YAML
```
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:
- Properties
- YAML
```
spring.config.import=optional:configtree:/run/secrets/
```
```
spring:
config:
import: "optional:configtree:/run/secrets/"
```
### Property Placeholders
The values in `application.properties` and `application.yaml` are filtered through the existing [`Environment`](https://docs.spring.io/spring-framework/docs/7.0.x/javadoc-api/org/springframework/core/env/Environment.html) 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
- YAML
```
app.name=MyApp
app.description=${app.name} is a Spring Boot application written by ${username:Unknown}
```
```
app:
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](https://docs.spring.io/spring-boot/reference/features/external-config.html#features.external-config.typesafe-configuration-properties.relaxed-binding) [`@ConfigurationProperties`](https://docs.spring.io/spring-boot/4.0.5/api/java/org/springframework/boot/context/properties/ConfigurationProperties.html). 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 use `${demo.itemPrice}` instead, it will pick up the `demo.itemPrice` form from the `application.properties` file, as well as `DEMO_ITEMPRICE` from the system environment, but `demo.item-price` would not be considered. |
| | |
|---|---|
| | You can also use this technique to create âshortâ variants of existing Spring Boot properties. See the [Use âShortâ Command Line Arguments](https://docs.spring.io/spring-boot/how-to/properties-and-configuration.html#howto.properties-and-configuration.short-command-line-arguments) section in âHow-to Guidesâ for details. |
### 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.yaml` 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](https://docs.spring.io/spring-boot/reference/features/external-config.html#features.external-config.files.activation-properties) for details. |
| | |
|---|---|
| | Multi-document property files cannot be loaded by using the [`@PropertySource`](https://docs.spring.io/spring-framework/docs/7.0.x/javadoc-api/org/springframework/context/annotation/PropertySource.html) or [`@TestPropertySource`](https://docs.spring.io/spring-framework/docs/7.0.x/javadoc-api/org/springframework/test/context/TestPropertySource.html) annotations. |
### 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:
| Property | Note |
|---|---|
| `on-profile` | A profile expression that must match for the document to be active, or a list of profile expressions of which at least one must match for the document to be active. |
| `on-cloud-platform` | The [`CloudPlatform`](https://docs.spring.io/spring-boot/4.0.5/api/java/org/springframework/boot/cloud/CloudPlatform.html) that must be detected for the document to be active. |
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
- YAML
```
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"
```
## 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`](https://docs.spring.io/spring-framework/docs/7.0.x/javadoc-api/org/springframework/core/env/Environment.html). The [`EnvironmentPostProcessor`](https://docs.spring.io/spring-boot/4.0.5/api/java/org/springframework/boot/EnvironmentPostProcessor.html) interface allows you to manipulate the [`Environment`](https://docs.spring.io/spring-framework/docs/7.0.x/javadoc-api/org/springframework/core/env/Environment.html) before the application starts. See [Customize the Environment or ApplicationContext Before It Starts](https://docs.spring.io/spring-boot/how-to/application.html#howto.application.customize-the-environment-or-application-context) for details.
If you need a secure way to store credentials and passwords, the [Spring Cloud Vault](https://cloud.spring.io/spring-cloud-vault/) project provides support for storing externalized configuration in [HashiCorp Vault](https://www.vaultproject.io/).
## Working With YAML
[YAML](https://yaml.org/) is a superset of JSON and, as such, is a convenient format for specifying hierarchical configuration data. The [`SpringApplication`](https://docs.spring.io/spring-boot/4.0.5/api/java/org/springframework/boot/SpringApplication.html) class automatically supports YAML as an alternative to properties whenever you have the [SnakeYAML](https://github.com/snakeyaml/snakeyaml) library on your classpath.
| | |
|---|---|
| | If you use starters, SnakeYAML is automatically provided by `spring-boot-starter`. |
### 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`](https://docs.spring.io/spring-framework/docs/7.0.x/javadoc-api/org/springframework/core/env/Environment.html). 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`](https://docs.spring.io/spring-framework/docs/7.0.x/javadoc-api/org/springframework/core/env/Environment.html), 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`](https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/util/List.html) or [`Set`](https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/util/Set.html) objects using Spring Bootâs [`Binder`](https://docs.spring.io/spring-boot/4.0.5/api/java/org/springframework/boot/context/properties/bind/Binder.html) class. For more details see the [Type-safe Configuration Properties](https://docs.spring.io/spring-boot/reference/features/external-config.html#features.external-config.typesafe-configuration-properties) section below. |
| | |
|---|---|
| | YAML files cannot be loaded by using the [`@PropertySource`](https://docs.spring.io/spring-framework/docs/7.0.x/javadoc-api/org/springframework/context/annotation/PropertySource.html) or [`@TestPropertySource`](https://docs.spring.io/spring-framework/docs/7.0.x/javadoc-api/org/springframework/test/context/TestPropertySource.html) annotations. So, in the case that you need to load values that way, you need to use a properties file. |
### Directly Loading YAML
Spring Framework provides two convenient classes that can be used to load YAML documents. The [`YamlPropertiesFactoryBean`](https://docs.spring.io/spring-framework/docs/7.0.x/javadoc-api/org/springframework/beans/factory/config/YamlPropertiesFactoryBean.html) loads YAML as [`Properties`](https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/util/Properties.html) and the [`YamlMapFactoryBean`](https://docs.spring.io/spring-framework/docs/7.0.x/javadoc-api/org/springframework/beans/factory/config/YamlMapFactoryBean.html) loads YAML as a [`Map`](https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/util/Map.html).
You can also use the [`YamlPropertySourceLoader`](https://docs.spring.io/spring-boot/4.0.5/api/java/org/springframework/boot/env/YamlPropertySourceLoader.html) class if you want to load YAML as a Spring [`PropertySource`](https://docs.spring.io/spring-framework/docs/7.0.x/javadoc-api/org/springframework/core/env/PropertySource.html).
## Configuring Random Values
The [`RandomValuePropertySource`](https://docs.spring.io/spring-boot/4.0.5/api/java/org/springframework/boot/env/RandomValuePropertySource.html) 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
- YAML
```
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).
## 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`](https://docs.spring.io/spring-boot/4.0.5/api/java/org/springframework/boot/SpringApplication.html) by calling the `setEnvironmentPrefix(âŚâ)` method before the application is run.
For example, if you set the prefix to `input`, a property such as `remote.timeout` will be resolved as `INPUT_REMOTE_TIMEOUT` in the system environment.
| | |
|---|---|
| | The prefix *only* applies to system environment properties. The example above would continue to use `remote.timeout` when reading properties from other sources. |
## 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.
| | |
|---|---|
| | See also the [differences between](https://docs.spring.io/spring-boot/reference/features/external-config.html#features.external-config.typesafe-configuration-properties.vs-value-annotation) [`@Value`](https://docs.spring.io/spring-framework/docs/7.0.x/javadoc-api/org/springframework/beans/factory/annotation/Value.html) and type-safe configuration properties. |
### JavaBean Properties Binding
It is possible to bind a bean declaring standard JavaBean properties as shown in the following example:
- Java
- Kotlin
```
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"))
}
}
```
The preceding POJO defines the following properties:
- `my.service.enabled`, with a value of `false` by default.
- `my.service.remote-address`, with a type that can be coerced from [`String`](https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/String.html).
- `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`](https://docs.spring.io/spring-boot/4.0.5/api/java/org/springframework/boot/security/autoconfigure/SecurityProperties.html).
- `my.service.security.password`.
- `my.service.security.roles`, with a collection of [`String`](https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/String.html) that defaults to `USER`.
| | |
|---|---|
| | To use a reserved keyword in the name of a property, such as `my.service.import`, use the [`@Name`](https://docs.spring.io/spring-boot/4.0.5/api/java/org/springframework/boot/context/properties/bind/Name.html) annotation on the propertyâs field. |
| | |
|---|---|
| | The properties that map to [`@ConfigurationProperties`](https://docs.spring.io/spring-boot/4.0.5/api/java/org/springframework/boot/context/properties/ConfigurationProperties.html) classes available in Spring Boot, which are configured through properties files, YAML files, environment variables, and other mechanisms, 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: Pre-initialized Maps and Collections, as long as they are initialized with a mutable implementation (like the `roles` field in the preceding example). Pre-initialized nested POJOs (like the `Security` field in the preceding example). 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. |
### Constructor Binding
The example in the previous section can be rewritten in an immutable fashion as shown in the following example:
- Java
- Kotlin
```
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`](https://docs.spring.io/spring-boot/4.0.5/api/java/org/springframework/boot/context/properties/bind/ConstructorBinding.html) annotation can be used to specify which constructor to use for constructor binding.
To opt-out of constructor binding for a class, the parameterized constructor must be annotated with [`@Autowired`](https://docs.spring.io/spring-framework/docs/7.0.x/javadoc-api/org/springframework/beans/factory/annotation/Autowired.html) or made `private`. Kotlin developers can use an empty primary constructor to opt-out of constructor binding.
For example:
- Java
- Kotlin
```
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.ConfigurationProperties;
@ConfigurationProperties("my")
public class MyProperties {
// fields...
final MyBean myBean;
private String name;
@Autowired
public MyProperties(MyBean myBean) {
this.myBean = myBean;
}
// getters / setters...
public String getName() {
return this.name;
}
public void setName(String name) {
this.name = name;
}
}
```
```
import org.springframework.boot.context.properties.ConfigurationProperties
@ConfigurationProperties("my")
class MyProperties() {
constructor(name: String) : this() {
this.name = name
}
// vars...
var name: String? = null
}
```
Constructor binding can be used with records. Unless your record has multiple constructors, there is no need to use [`@ConstructorBinding`](https://docs.spring.io/spring-boot/4.0.5/api/java/org/springframework/boot/context/properties/bind/ConstructorBinding.html).
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`](https://docs.spring.io/spring-boot/4.0.5/api/java/org/springframework/boot/context/properties/bind/DefaultValue.html) on constructor parameters and record components. The conversion service will be applied to coerce the annotationâs [`String`](https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/String.html) 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`](https://docs.spring.io/spring-boot/4.0.5/api/java/org/springframework/boot/context/properties/bind/DefaultValue.html) annotation:
- Java
- Kotlin
```
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`](https://docs.spring.io/spring-boot/4.0.5/api/java/org/springframework/boot/context/properties/EnableConfigurationProperties.html) or configuration property scanning. You cannot use constructor binding with beans that are created by the regular Spring mechanisms (for example [`@Component`](https://docs.spring.io/spring-framework/docs/7.0.x/javadoc-api/org/springframework/stereotype/Component.html) beans, beans created by using [`@Bean`](https://docs.spring.io/spring-framework/docs/7.0.x/javadoc-api/org/springframework/context/annotation/Bean.html) methods or beans loaded by using [`@Import`](https://docs.spring.io/spring-framework/docs/7.0.x/javadoc-api/org/springframework/context/annotation/Import.html)) |
| | |
|---|---|
| | To use constructor binding 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 [`Optional`](https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/util/Optional.html) with [`@ConfigurationProperties`](https://docs.spring.io/spring-boot/4.0.5/api/java/org/springframework/boot/context/properties/ConfigurationProperties.html) 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`](https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/util/Optional.html) property and it has no value, `null` rather than an empty [`Optional`](https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/util/Optional.html) will be bound. |
| | |
|---|---|
| | To use a reserved keyword in the name of a property, such as `my.service.import`, use the [`@Name`](https://docs.spring.io/spring-boot/4.0.5/api/java/org/springframework/boot/context/properties/bind/Name.html) annotation on the constructor parameter. |
### Enabling @ConfigurationProperties-annotated Types
Spring Boot provides infrastructure to bind [`@ConfigurationProperties`](https://docs.spring.io/spring-boot/4.0.5/api/java/org/springframework/boot/context/properties/ConfigurationProperties.html) 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`](https://docs.spring.io/spring-boot/4.0.5/api/java/org/springframework/boot/context/properties/ConfigurationProperties.html) 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`](https://docs.spring.io/spring-boot/4.0.5/api/java/org/springframework/boot/context/properties/EnableConfigurationProperties.html) annotation. This can be done on any [`@Configuration`](https://docs.spring.io/spring-framework/docs/7.0.x/javadoc-api/org/springframework/context/annotation/Configuration.html) class, as shown in the following example:
- Java
- Kotlin
```
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
```
- Java
- Kotlin
```
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`](https://docs.spring.io/spring-boot/4.0.5/api/java/org/springframework/boot/context/properties/ConfigurationPropertiesScan.html) annotation to your application. Typically, it is added to the main application class that is annotated with [`@SpringBootApplication`](https://docs.spring.io/spring-boot/4.0.5/api/java/org/springframework/boot/autoconfigure/SpringBootApplication.html) but it can be added to any [`@Configuration`](https://docs.spring.io/spring-framework/docs/7.0.x/javadoc-api/org/springframework/context/annotation/Configuration.html) 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:
- Java
- Kotlin
```
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`](https://docs.spring.io/spring-boot/4.0.5/api/java/org/springframework/boot/context/properties/ConfigurationProperties.html) bean is registered using configuration property scanning or through [`@EnableConfigurationProperties`](https://docs.spring.io/spring-boot/4.0.5/api/java/org/springframework/boot/context/properties/EnableConfigurationProperties.html), the bean has a conventional name: `<prefix>-<fqn>`, where `<prefix>` is the environment key prefix specified in the [`@ConfigurationProperties`](https://docs.spring.io/spring-boot/4.0.5/api/java/org/springframework/boot/context/properties/ConfigurationProperties.html) 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`](https://docs.spring.io/spring-boot/4.0.5/api/java/org/springframework/boot/context/properties/ConfigurationProperties.html) 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`](https://docs.spring.io/spring-framework/docs/7.0.x/javadoc-api/org/springframework/context/EnvironmentAware.html) if you need access to the [`Environment`](https://docs.spring.io/spring-framework/docs/7.0.x/javadoc-api/org/springframework/core/env/Environment.html)). If you still want to inject other beans using the constructor, the configuration properties bean must be annotated with [`@Component`](https://docs.spring.io/spring-framework/docs/7.0.x/javadoc-api/org/springframework/stereotype/Component.html) and use JavaBean-based property binding.
### Using @ConfigurationProperties-annotated Types
This style of configuration works particularly well with the [`SpringApplication`](https://docs.spring.io/spring-boot/4.0.5/api/java/org/springframework/boot/SpringApplication.html) external YAML configuration, as shown in the following example:
```
my:
service:
remote-address: 192.168.1.1
security:
username: "admin"
roles:
- "USER"
- "ADMIN"
```
To work with [`@ConfigurationProperties`](https://docs.spring.io/spring-boot/4.0.5/api/java/org/springframework/boot/context/properties/ConfigurationProperties.html) beans, you can inject them in the same way as any other bean, as shown in the following example:
- Java
- Kotlin
```
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();
// ...
}
// ...
}
```
```
import org.springframework.stereotype.Service
@Service
class MyService(val properties: MyProperties) {
fun openConnection() {
val server = Server(properties.remoteAddress)
server.start()
// ...
}
// ...
}
```
| | |
|---|---|
| | Using [`@ConfigurationProperties`](https://docs.spring.io/spring-boot/4.0.5/api/java/org/springframework/boot/context/properties/ConfigurationProperties.html) also lets you generate metadata files that can be used by IDEs to offer auto-completion for your own keys. See the [appendix](https://docs.spring.io/spring-boot/specification/configuration-metadata/index.html) for details. |
### Third-party Configuration
As well as using [`@ConfigurationProperties`](https://docs.spring.io/spring-boot/4.0.5/api/java/org/springframework/boot/context/properties/ConfigurationProperties.html) to annotate a class, you can also use it on public [`@Bean`](https://docs.spring.io/spring-framework/docs/7.0.x/javadoc-api/org/springframework/context/annotation/Bean.html) 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`](https://docs.spring.io/spring-framework/docs/7.0.x/javadoc-api/org/springframework/core/env/Environment.html) properties, add [`@ConfigurationProperties`](https://docs.spring.io/spring-boot/4.0.5/api/java/org/springframework/boot/context/properties/ConfigurationProperties.html) to its bean registration, as shown in the following example:
- Java
- Kotlin
```
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("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("another")
fun anotherComponent(): AnotherComponent = AnotherComponent()
}
```
Any JavaBean property defined with the `another` prefix is mapped onto that `AnotherComponent` bean in manner similar to the preceding `SomeProperties` example.
### Relaxed Binding
Spring Boot uses some relaxed rules for binding [`Environment`](https://docs.spring.io/spring-framework/docs/7.0.x/javadoc-api/org/springframework/core/env/Environment.html) properties to [`@ConfigurationProperties`](https://docs.spring.io/spring-boot/4.0.5/api/java/org/springframework/boot/context/properties/ConfigurationProperties.html) beans, so there does not need to be an exact match between the [`Environment`](https://docs.spring.io/spring-framework/docs/7.0.x/javadoc-api/org/springframework/core/env/Environment.html) 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`](https://docs.spring.io/spring-boot/4.0.5/api/java/org/springframework/boot/context/properties/ConfigurationProperties.html) class:
- Java
- Kotlin
```
import org.springframework.boot.context.properties.ConfigurationProperties;
@ConfigurationProperties("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("my.main-project.person")
class MyPersonProperties {
var firstName: String? = null
}
```
With the preceding code, the following properties names can all be used:
| Property | Note |
|---|---|
| `my.main-project.person.first-name` | Kebab case, which is recommended for use in `.properties` and YAML 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 YAML files. |
| `MY_MAINPROJECT_PERSON_FIRSTNAME` | 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 `my.main-project.person`). |
| Property Source | Simple | List |
|---|---|---|
| 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](https://docs.spring.io/spring-boot/reference/features/external-config.html#features.external-config.typesafe-configuration-properties.relaxed-binding.environment-variables)). | Numeric values surrounded by underscores (see [Binding From Environment Variables](https://docs.spring.io/spring-boot/reference/features/external-config.html#features.external-config.typesafe-configuration-properties.relaxed-binding.environment-variables)) |
| System properties | Camel case, kebab case, or underscore notation | Standard list syntax using `[ ]` or comma-separated values |
| | |
|---|---|
| | We recommend that, when possible, properties are stored in lower-case kebab format, such as `my.person.first-name=Rod`. |
#### Binding Maps
When binding to [`Map`](https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/util/Map.html) 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
- YAML
```
my.map[/key1]=value1
my.map[/key2]=value2
my.map./key3=value3
```
```
my:
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`](https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/util/Map.html) 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`](https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/Object.html). 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:
- 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`](https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/util/List.html), 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`.
Support for binding from environment variables is applied to the `systemEnvironment` property source and to any additional property source whose name ends with `-systemEnvironment`.
#### Binding Maps From Environment Variables
When Spring Boot binds an environment variable to a property class, it lowercases the environment variable name before binding. Most of the time this detail isnât important, except when binding to [`Map`](https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/util/Map.html) properties.
The keys in the [`Map`](https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/util/Map.html) are always in lowercase, as seen in the following example:
- Java
- Kotlin
```
import java.util.HashMap;
import java.util.Map;
import org.springframework.boot.context.properties.ConfigurationProperties;
@ConfigurationProperties("my.props")
public class MyMapsProperties {
private final Map<String, String> values = new HashMap<>();
public Map<String, String> getValues() {
return this.values;
}
}
```
```
import org.springframework.boot.context.properties.ConfigurationProperties
@ConfigurationProperties("my.props")
class MyMapsProperties {
val values: Map<String, String> = HashMap()
}
```
When setting `MY_PROPS_VALUES_KEY=value`, the `values` [`Map`](https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/util/Map.html) contains a `{"key"="value"}` entry.
Only the environment variable **name** is lower-cased, not the value. When setting `MY_PROPS_VALUES_KEY=VALUE`, the `values` [`Map`](https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/util/Map.html) contains a `{"key"="VALUE"}` entry.
#### Caching
Relaxed binding uses a cache to improve performance. By default, this caching is only applied to immutable property sources. To customize this behavior, for example to enable caching for mutable property sources, use [`ConfigurationPropertyCaching`](https://docs.spring.io/spring-boot/4.0.5/api/java/org/springframework/boot/context/properties/source/ConfigurationPropertyCaching.html).
### 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`:
- Java
- Kotlin
```
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()
}
```
Consider the following configuration:
- Properties
- YAML
```
my.list[0].name=my name
my.list[0].description=my description
#---
spring.config.activate.on-profile=dev
my.list[0].name=my another name
```
```
my:
list:
- name: "my name"
description: "my description"
---
spring:
config:
activate:
on-profile: "dev"
my:
list:
- name: "my another name"
```
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`](https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/util/List.html) is specified in multiple profiles, the one with the highest priority (and only that one) is used. Consider the following example:
- Properties
- YAML
```
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
```
```
my:
list:
- name: "my name"
description: "my description"
- name: "another name"
description: "another description"
---
spring:
config:
activate:
on-profile: "dev"
my:
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`](https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/util/Map.html) 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`:
- Java
- Kotlin
```
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()
}
```
Consider the following configuration:
- Properties
- YAML
```
my.map.key1.name=my name 1
my.map.key1.description=my description 1
#---
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
```
```
my:
map:
key1:
name: "my name 1"
description: "my description 1"
---
spring:
config:
activate:
on-profile: "dev"
my:
map:
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`).
| | |
|---|---|
| | The preceding merging rules apply to properties from all property sources, and not just files. |
### Properties Conversion
Spring Boot attempts to coerce the external application properties to the right type when it binds to the [`@ConfigurationProperties`](https://docs.spring.io/spring-boot/4.0.5/api/java/org/springframework/boot/context/properties/ConfigurationProperties.html) beans. If you need custom type conversion, you can provide a [`ConversionService`](https://docs.spring.io/spring-framework/docs/7.0.x/javadoc-api/org/springframework/core/convert/ConversionService.html) bean (with a bean named `conversionService`) or custom property editors (through a [`CustomEditorConfigurer`](https://docs.spring.io/spring-framework/docs/7.0.x/javadoc-api/org/springframework/beans/factory/config/CustomEditorConfigurer.html) bean) or custom converters (with bean definitions annotated as [`@ConfigurationPropertiesBinding`](https://docs.spring.io/spring-boot/4.0.5/api/java/org/springframework/boot/context/properties/ConfigurationPropertiesBinding.html)).
| | |
|---|---|
| | Beans used for property conversion are requested very early during the application lifecycle so make sure to limit the dependencies that your [`ConversionService`](https://docs.spring.io/spring-framework/docs/7.0.x/javadoc-api/org/springframework/core/convert/ConversionService.html) is using. Typically, any dependency that you require may not be fully initialized at creation time. |
| | |
|---|---|
| | You may want to rename your custom [`ConversionService`](https://docs.spring.io/spring-framework/docs/7.0.x/javadoc-api/org/springframework/core/convert/ConversionService.html) if it is not required for configuration keys coercion and only rely on custom converters qualified with [`@ConfigurationPropertiesBinding`](https://docs.spring.io/spring-boot/4.0.5/api/java/org/springframework/boot/context/properties/ConfigurationPropertiesBinding.html). When qualifying a `@Bean` method with `@ConfigurationPropertiesBinding`, the method should be `static` to avoid âbean is not eligible for getting processed by all BeanPostProcessorsâ warnings. |
#### Converting Durations
Spring Boot has dedicated support for expressing durations. If you expose a [`Duration`](https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/time/Duration.html) property, the following formats in application properties are available:
- A regular `long` representation (using milliseconds as the default unit unless a [`@DurationUnit`](https://docs.spring.io/spring-boot/4.0.5/api/java/org/springframework/boot/convert/DurationUnit.html) has been specified)
- The standard ISO-8601 format [used by](https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/time/Duration.html#parse\(java.lang.CharSequence\)) [`Duration`](https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/time/Duration.html)
- A more readable format where the value and the unit are coupled (`10s` means 10 seconds)
Consider the following example:
- Java
- Kotlin
```
import java.time.Duration;
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:
- `ns` for nanoseconds
- `us` for microseconds
- `ms` for milliseconds
- `s` for seconds
- `m` for minutes
- `h` for hours
- `d` for days
The default unit is milliseconds and can be overridden using [`@DurationUnit`](https://docs.spring.io/spring-boot/4.0.5/api/java/org/springframework/boot/convert/DurationUnit.html) 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:
- Java
- Kotlin
```
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`](https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/Long.html) property, make sure to define the unit (using [`@DurationUnit`](https://docs.spring.io/spring-boot/4.0.5/api/java/org/springframework/boot/convert/DurationUnit.html)) 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 [`Period`](https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/time/Period.html) type. The following formats can be used in application properties:
- A regular `int` representation (using days as the default unit unless a [`@PeriodUnit`](https://docs.spring.io/spring-boot/4.0.5/api/java/org/springframework/boot/convert/PeriodUnit.html) has been specified)
- The standard ISO-8601 format [used by](https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/time/Period.html#parse\(java.lang.CharSequence\)) [`Period`](https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/time/Period.html)
- A simpler format where the value and the unit pairs are coupled (`1y3d` means 1 year and 3 days)
The following units are supported with the simple format:
- `y` for years
- `m` for months
- `w` for weeks
- `d` for days
| | |
|---|---|
| | The [`Period`](https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/time/Period.html) type never actually stores the number of weeks, it is a shortcut that means â7 daysâ. |
#### Converting Data Sizes
Spring Framework has a [`DataSize`](https://docs.spring.io/spring-framework/docs/7.0.x/javadoc-api/org/springframework/util/unit/DataSize.html) value type that expresses a size in bytes. If you expose a [`DataSize`](https://docs.spring.io/spring-framework/docs/7.0.x/javadoc-api/org/springframework/util/unit/DataSize.html) property, the following formats in application properties are available:
- A regular `long` representation (using bytes as the default unit unless a [`@DataSizeUnit`](https://docs.spring.io/spring-boot/4.0.5/api/java/org/springframework/boot/convert/DataSizeUnit.html) has been specified)
- A more readable format where the value and the unit are coupled (`10MB` means 10 megabytes)
Consider the following example:
- Java
- Kotlin
```
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:
- `B` for bytes
- `KB` for kilobytes
- `MB` for megabytes
- `GB` for gigabytes
- `TB` for terabytes
The default unit is bytes and can be overridden using [`@DataSizeUnit`](https://docs.spring.io/spring-boot/4.0.5/api/java/org/springframework/boot/convert/DataSizeUnit.html) 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:
- Java
- Kotlin
```
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`](https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/Long.html) property, make sure to define the unit (using [`@DataSizeUnit`](https://docs.spring.io/spring-boot/4.0.5/api/java/org/springframework/boot/convert/DataSizeUnit.html)) if it is not bytes. Doing so gives a transparent upgrade path while supporting a much richer format. |
#### Converting Base64 Data
Spring Boot supports resolving binary data that have been Base64 encoded. If you expose a `Resource` property, the base64 encoded text can be provided as the value with a `base64:` prefix, as shown in the following example:
- Properties
- YAML
```
my.property=base64:SGVsbG8gV29ybGQ=
```
```
my:
property: base64:SGVsbG8gV29ybGQ=
```
| | |
|---|---|
| | The `Resource` property can also be used to provide the path to the resource, making it more versatile. |
### @ConfigurationProperties Validation
Spring Boot attempts to validate [`@ConfigurationProperties`](https://docs.spring.io/spring-boot/4.0.5/api/java/org/springframework/boot/context/properties/ConfigurationProperties.html) classes whenever they are annotated with Springâs [`@Validated`](https://docs.spring.io/spring-framework/docs/7.0.x/javadoc-api/org/springframework/validation/annotation/Validated.html) 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:
- Java
- Kotlin
```
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
}
```
| | |
|---|---|
| | You can also trigger validation by annotating the [`@Bean`](https://docs.spring.io/spring-framework/docs/7.0.x/javadoc-api/org/springframework/context/annotation/Bean.html) method that creates the configuration properties with [`@Validated`](https://docs.spring.io/spring-framework/docs/7.0.x/javadoc-api/org/springframework/validation/annotation/Validated.html). |
To cascade validation to nested properties the associated field must be annotated with [`@Valid`](https://jakarta.ee/specifications/bean-validation/3.1/apidocs/jakarta/validation/Valid.html). The following example builds on the preceding `MyProperties` example:
- Java
- Kotlin
```
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`](https://docs.spring.io/spring-framework/docs/7.0.x/javadoc-api/org/springframework/validation/Validator.html) by creating a bean definition called `configurationPropertiesValidator`. The [`@Bean`](https://docs.spring.io/spring-framework/docs/7.0.x/javadoc-api/org/springframework/context/annotation/Bean.html) method should be declared `static`. The configuration properties validator is created very early in the applicationâs lifecycle, and declaring the [`@Bean`](https://docs.spring.io/spring-framework/docs/7.0.x/javadoc-api/org/springframework/context/annotation/Bean.html) method as static lets the bean be created without having to instantiate the [`@Configuration`](https://docs.spring.io/spring-framework/docs/7.0.x/javadoc-api/org/springframework/context/annotation/Configuration.html) 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`](https://docs.spring.io/spring-boot/4.0.5/api/java/org/springframework/boot/context/properties/ConfigurationProperties.html) beans. Point your web browser to `/actuator/configprops` or use the equivalent JMX endpoint. See the [Production ready features](https://docs.spring.io/spring-boot/reference/actuator/endpoints.html) section for details. |
### @ConfigurationProperties vs. @Value
The [`@Value`](https://docs.spring.io/spring-framework/docs/7.0.x/javadoc-api/org/springframework/beans/factory/annotation/Value.html) 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`](https://docs.spring.io/spring-boot/4.0.5/api/java/org/springframework/boot/context/properties/ConfigurationProperties.html) and [`@Value`](https://docs.spring.io/spring-framework/docs/7.0.x/javadoc-api/org/springframework/beans/factory/annotation/Value.html):
| Feature | `@ConfigurationProperties` | `@Value` |
|---|---|---|
| [Relaxed binding](https://docs.spring.io/spring-boot/reference/features/external-config.html#features.external-config.typesafe-configuration-properties.relaxed-binding) | Yes | Limited (see [note below](https://docs.spring.io/spring-boot/reference/features/external-config.html#features.external-config.typesafe-configuration-properties.vs-value-annotation.note)) |
| [Meta-data support](https://docs.spring.io/spring-boot/specification/configuration-metadata/index.html) | Yes | No |
| `SpEL` evaluation | No | Yes |
| | |
|---|---|
| | If you do want to use [`@Value`](https://docs.spring.io/spring-framework/docs/7.0.x/javadoc-api/org/springframework/beans/factory/annotation/Value.html), 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](https://docs.spring.io/spring-boot/reference/features/external-config.html#features.external-config.typesafe-configuration-properties.relaxed-binding) [`@ConfigurationProperties`](https://docs.spring.io/spring-boot/4.0.5/api/java/org/springframework/boot/context/properties/ConfigurationProperties.html). 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 use `@Value("${demo.itemPrice}")` instead, it will pickup the `demo.itemPrice` form from the `application.properties` file, as well as `DEMO_ITEMPRICE` from the system environment, but `demo.item-price` 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`](https://docs.spring.io/spring-boot/4.0.5/api/java/org/springframework/boot/context/properties/ConfigurationProperties.html). Doing so will provide you with structured, type-safe object that you can inject into your own beans.
`SpEL` expressions from [application property files](https://docs.spring.io/spring-boot/reference/features/external-config.html#features.external-config.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`](https://docs.spring.io/spring-framework/docs/7.0.x/javadoc-api/org/springframework/beans/factory/annotation/Value.html). If the value of a property from an application property file is a `SpEL` expression, it will be evaluated when consumed through [`@Value`](https://docs.spring.io/spring-framework/docs/7.0.x/javadoc-api/org/springframework/beans/factory/annotation/Value.html).
[SpringApplication](https://docs.spring.io/spring-boot/reference/features/spring-application.html) [Profiles](https://docs.spring.io/spring-boot/reference/features/profiles.html)
- [Spring Boot](https://docs.spring.io/spring-boot/index.html)
Stable
- [4\.0.5](https://docs.spring.io/spring-boot/reference/features/external-config.html)
- [3\.5.13](https://docs.spring.io/spring-boot/3.5/reference/features/external-config.html)
- [3\.4.13](https://docs.spring.io/spring-boot/3.4/reference/features/external-config.html)
- [3\.3.13](https://docs.spring.io/spring-boot/3.3/reference/features/external-config.html)
Preview
- [4\.1.0-M4](https://docs.spring.io/spring-boot/4.1/reference/features/external-config.html)
Snapshot
- [4\.1.0-SNAPSHOT](https://docs.spring.io/spring-boot/4.1-SNAPSHOT/reference/features/external-config.html)
- [4\.0.6-SNAPSHOT](https://docs.spring.io/spring-boot/4.0-SNAPSHOT/reference/features/external-config.html)
- [3\.5.14-SNAPSHOT](https://docs.spring.io/spring-boot/3.5-SNAPSHOT/reference/features/external-config.html)
- Related Spring Documentation
- [Spring Boot](https://docs.spring.io/spring-boot/)
- [Spring Framework](https://docs.spring.io/spring-framework/reference/)
- Spring Cloud
- [Spring Cloud Build](https://docs.spring.io/spring-cloud-build/reference/)
- [Spring Cloud Bus](https://docs.spring.io/spring-cloud-bus/reference/)
- [Spring Cloud Circuit Breaker](https://docs.spring.io/spring-cloud-circuitbreaker/reference/)
- [Spring Cloud Commons](https://docs.spring.io/spring-cloud-commons/reference/)
- [Spring Cloud Config](https://docs.spring.io/spring-cloud-config/reference/)
- [Spring Cloud Consul](https://docs.spring.io/spring-cloud-consul/reference/)
- [Spring Cloud Contract](https://docs.spring.io/spring-cloud-contract/reference/)
- [Spring Cloud Function](https://docs.spring.io/spring-cloud-function/reference/)
- [Spring Cloud Gateway](https://docs.spring.io/spring-cloud-gateway/reference/)
- [Spring Cloud Kubernetes](https://docs.spring.io/spring-cloud-kubernetes/reference/)
- [Spring Cloud Netflix](https://docs.spring.io/spring-cloud-netflix/reference/)
- [Spring Cloud OpenFeign](https://docs.spring.io/spring-cloud-openfeign/reference/)
- [Spring Cloud Stream](https://docs.spring.io/spring-cloud-stream/reference/)
- [Spring Cloud Task](https://docs.spring.io/spring-cloud-task/reference/)
- [Spring Cloud Vault](https://docs.spring.io/spring-cloud-vault/reference/)
- [Spring Cloud Zookeeper](https://docs.spring.io/spring-cloud-zookeeper/reference/)
- Spring Data
- [Spring Data Cassandra](https://docs.spring.io/spring-data/cassandra/reference/)
- [Spring Data Commons](https://docs.spring.io/spring-data/commons/reference/)
- [Spring Data Couchbase](https://docs.spring.io/spring-data/couchbase/reference/)
- [Spring Data Elasticsearch](https://docs.spring.io/spring-data/elasticsearch/reference/)
- [Spring Data JPA](https://docs.spring.io/spring-data/jpa/reference/)
- [Spring Data KeyValue](https://docs.spring.io/spring-data/keyvalue/reference/)
- [Spring Data LDAP](https://docs.spring.io/spring-data/ldap/reference/)
- [Spring Data MongoDB](https://docs.spring.io/spring-data/mongodb/reference/)
- [Spring Data Neo4j](https://docs.spring.io/spring-data/neo4j/reference/)
- [Spring Data Redis](https://docs.spring.io/spring-data/redis/reference/)
- [Spring Data JDBC & R2DBC](https://docs.spring.io/spring-data/relational/reference/)
- [Spring Data REST](https://docs.spring.io/spring-data/rest/reference/)
- [Spring Integration](https://docs.spring.io/spring-integration/reference/)
- [Spring Batch](https://docs.spring.io/spring-batch/reference/)
- [Spring Security](https://docs.spring.io/spring-security/reference/)
- [Spring Authorization Server](https://docs.spring.io/spring-authorization-server/reference/)
- [Spring LDAP](https://docs.spring.io/spring-ldap/reference/)
- [Spring Security Kerberos](https://docs.spring.io/spring-security-kerberos/reference/)
- [Spring Session](https://docs.spring.io/spring-session/reference/)
- [Spring Vault](https://docs.spring.io/spring-vault/reference/)
- [Spring AI](https://docs.spring.io/spring-ai/reference/)
- [Spring AMQP](https://docs.spring.io/spring-amqp/reference/)
- [Spring CLI](https://docs.spring.io/spring-cli/reference/)
- [Spring GraphQL](https://docs.spring.io/spring-graphql/reference/)
- [Spring for Apache Kafka](https://docs.spring.io/spring-kafka/reference/)
- [Spring Modulith](https://docs.spring.io/spring-modulith/reference/)
- [Spring for Apache Pulsar](https://docs.spring.io/spring-pulsar/reference/)
- [Spring Shell](https://docs.spring.io/spring-shell/reference/)

Copyright Š 2005 - Broadcom. All Rights Reserved. The term "Broadcom" refers to Broadcom Inc. and/or its subsidiaries.
[Terms of Use](https://www.vmware.com/help/legal.html) ⢠[Privacy](https://www.vmware.com/help/privacy.html) ⢠[Trademark Guidelines](https://spring.io/trademarks) ⢠[Thank you](https://spring.io/thank-you) ⢠[Your California Privacy Rights](https://www.vmware.com/help/privacy/california-privacy-rights.html) ⢠[Cookie Settings]()
ApacheÂŽ, Apache TomcatÂŽ, Apache KafkaÂŽ, Apache Cassandraâ˘, and Apache Geode⢠are trademarks or registered trademarks of the Apache Software Foundation in the United States and/or other countries. Javaâ˘, Java⢠SE, Java⢠EE, and OpenJDK⢠are trademarks of Oracle and/or its affiliates. KubernetesÂŽ is a registered trademark of the Linux Foundation in the United States and other countries. LinuxÂŽ is the registered trademark of Linus Torvalds in the United States and other countries. WindowsÂŽ and MicrosoftÂŽ Azure are registered trademarks of Microsoft Corporation. âAWSâ and âAmazon Web Servicesâ are trademarks or registered trademarks of Amazon.com Inc. or its affiliates. All other trademarks and copyrights are property of their respective owners and are only mentioned for informative purposes. Other names may be trademarks of their respective owners.
[Search in all Spring Docs](https://docs.spring.io/spring-boot/search.html)
[ ](https://www.algolia.com/) |
| Readable Markdown | 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`](https://docs.spring.io/spring-framework/docs/7.0.x/javadoc-api/org/springframework/beans/factory/annotation/Value.html) annotation, accessed through Springâs [`Environment`](https://docs.spring.io/spring-framework/docs/7.0.x/javadoc-api/org/springframework/core/env/Environment.html) abstraction, or be [bound to structured objects](https://docs.spring.io/spring-boot/reference/features/external-config.html#features.external-config.typesafe-configuration-properties) through [`@ConfigurationProperties`](https://docs.spring.io/spring-boot/4.0.5/api/java/org/springframework/boot/context/properties/ConfigurationProperties.html).
Spring Boot uses a very particular [`PropertySource`](https://docs.spring.io/spring-framework/docs/7.0.x/javadoc-api/org/springframework/core/env/PropertySource.html) 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:
1. Default properties (specified by setting [`SpringApplication.setDefaultProperties(Map)`](https://docs.spring.io/spring-boot/4.0.5/api/java/org/springframework/boot/SpringApplication.html#setDefaultProperties\(java.util.Map\))).
2. [`@PropertySource`](https://docs.spring.io/spring-framework/docs/7.0.x/javadoc-api/org/springframework/context/annotation/PropertySource.html) annotations on your [`@Configuration`](https://docs.spring.io/spring-framework/docs/7.0.x/javadoc-api/org/springframework/context/annotation/Configuration.html) classes. Please note that such property sources are not added to the [`Environment`](https://docs.spring.io/spring-framework/docs/7.0.x/javadoc-api/org/springframework/core/env/Environment.html) 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.
3. Config data (such as `application.properties` files).
4. A [`RandomValuePropertySource`](https://docs.spring.io/spring-boot/4.0.5/api/java/org/springframework/boot/env/RandomValuePropertySource.html) that has properties only in `random.*`.
5. OS environment variables.
6. Java System properties (`System.getProperties()`).
7. JNDI attributes from `java:comp/env`.
8. [`ServletContext`](https://jakarta.ee/specifications/servlet/6.1/apidocs/jakarta.servlet/jakarta/servlet/ServletContext.html) init parameters.
9. [`ServletConfig`](https://jakarta.ee/specifications/servlet/6.1/apidocs/jakarta.servlet/jakarta/servlet/ServletConfig.html) init parameters.
10. Properties from `SPRING_APPLICATION_JSON` (inline JSON embedded in an environment variable or system property).
11. Command line arguments.
12. `properties` attribute on your tests. Available on [`@SpringBootTest`](https://docs.spring.io/spring-boot/4.0.5/api/java/org/springframework/boot/test/context/SpringBootTest.html) and the [test annotations for testing a particular slice of your application](https://docs.spring.io/spring-boot/reference/testing/spring-boot-applications.html#testing.spring-boot-applications.autoconfigured-tests).
13. [`@DynamicPropertySource`](https://docs.spring.io/spring-framework/docs/7.0.x/javadoc-api/org/springframework/test/context/DynamicPropertySource.html) annotations in your tests.
14. [`@TestPropertySource`](https://docs.spring.io/spring-framework/docs/7.0.x/javadoc-api/org/springframework/test/context/TestPropertySource.html) annotations on your tests.
15. [Devtools global settings properties](https://docs.spring.io/spring-boot/reference/using/devtools.html#using.devtools.globalsettings) in the `$HOME/.config/spring-boot` directory when devtools is active.
Config data files are considered in the following order:
1. [Application properties](https://docs.spring.io/spring-boot/reference/features/external-config.html#features.external-config.files) packaged inside your jar (`application.properties` and YAML variants).
2. [Profile-specific application properties](https://docs.spring.io/spring-boot/reference/features/external-config.html#features.external-config.files.profile-specific) packaged inside your jar (`application-{profile}.properties` and YAML variants).
3. [Application properties](https://docs.spring.io/spring-boot/reference/features/external-config.html#features.external-config.files) outside of your packaged jar (`application.properties` and YAML variants).
4. [Profile-specific application properties](https://docs.spring.io/spring-boot/reference/features/external-config.html#features.external-config.files.profile-specific) 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 YAML format in the same location, `.properties` takes precedence. |
| | |
|---|---|
| | 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](https://docs.spring.io/spring-boot/reference/features/external-config.html#features.external-config.typesafe-configuration-properties.relaxed-binding.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. |
To provide a concrete example, suppose you develop a [`@Component`](https://docs.spring.io/spring-framework/docs/7.0.x/javadoc-api/org/springframework/stereotype/Component.html) that uses a `name` property, as shown in the following example:
- Java
- Kotlin
```
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](https://docs.spring.io/spring-boot/reference/actuator/endpoints.html) section for details. |
## Accessing Command Line Properties
By default, [`SpringApplication`](https://docs.spring.io/spring-boot/4.0.5/api/java/org/springframework/boot/SpringApplication.html) 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`](https://docs.spring.io/spring-framework/docs/7.0.x/javadoc-api/org/springframework/core/env/Environment.html). 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`](https://docs.spring.io/spring-framework/docs/7.0.x/javadoc-api/org/springframework/core/env/Environment.html), you can disable them by using `SpringApplication.setAddCommandLineProperties(false)`.
## 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`](https://docs.spring.io/spring-framework/docs/7.0.x/javadoc-api/org/springframework/core/env/Environment.html).
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`](https://docs.spring.io/spring-framework/docs/7.0.x/javadoc-api/org/springframework/core/env/Environment.html).
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`](https://docs.spring.io/spring-framework/docs/7.0.x/javadoc-api/org/springframework/core/env/PropertySourcesPropertyResolver.html) treats `null` properties as missing values. This means that the JSON cannot override properties from lower order property sources with a `null` value. |
## External Application Properties
Spring Boot will automatically find and load `application.properties` and `application.yaml` files from the following locations when your application starts:
1. From the classpath
1. The classpath root
2. The classpath `/config` package
2. From the current directory
1. The current directory
2. The `config/` subdirectory in the current directory
3. Immediate 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 [`PropertySource`](https://docs.spring.io/spring-framework/docs/7.0.x/javadoc-api/org/springframework/core/env/PropertySource.html) instances to the Spring [`Environment`](https://docs.spring.io/spring-framework/docs/7.0.x/javadoc-api/org/springframework/core/env/Environment.html).
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
```
| | |
|---|---|
| | Use the prefix `optional:` if the [locations are optional](https://docs.spring.io/spring-boot/reference/features/external-config.html#features.external-config.files.optional-prefix) and you do not mind if they do not 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 imported directly.
| | |
|---|---|
| | Both directory and file location values are also expanded to check for [profile-specific files](https://docs.spring.io/spring-boot/reference/features/external-config.html#features.external-config.files.profile-specific). 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](https://docs.spring.io/spring-boot/reference/features/external-config.html#features.external-config.files.profile-specific) 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:
1. `optional:classpath:custom-config/`
2. `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:
1. `optional:classpath:/;optional:classpath:/config/`
2. `optional:file:./;optional:file:./config/;optional:file:./config/*/`
3. `optional:classpath:custom-config/`
4. `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.
### Optional Locations
By default, when a specified config data location does not exist, Spring Boot will throw a [`ConfigDataLocationNotFoundException`](https://docs.spring.io/spring-boot/4.0.5/api/java/org/springframework/boot/context/config/ConfigDataLocationNotFoundException.html) 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`](https://docs.spring.io/spring-boot/reference/features/external-config.html#features.external-config.files.importing) 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 [`ConfigDataLocationNotFoundException`](https://docs.spring.io/spring-boot/4.0.5/api/java/org/springframework/boot/context/config/ConfigDataLocationNotFoundException.html) errors 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.
### 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. |
### 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.yaml` and `application-prod.yaml` 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](https://docs.spring.io/spring-boot/reference/features/external-config.html#features.external-config.files.location-groups) 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: When we have a `spring.config.location` of `classpath:/cfg/,classpath:/ext/` we process all `/cfg` files before all `/ext` files: `/cfg/application-live.properties` `/ext/application-prod.properties` `/ext/application-live.properties` When we have `classpath:/cfg/;classpath:/ext/` instead (with a `;` delimiter) we process `/cfg` and `/ext` at the same level: `/ext/application-prod.properties` `/cfg/application-live.properties` `/ext/application-live.properties` |
The [`Environment`](https://docs.spring.io/spring-framework/docs/7.0.x/javadoc-api/org/springframework/core/env/Environment.html) 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 have already directly [imported](https://docs.spring.io/spring-boot/reference/features/external-config.html#features.external-config.files.importing) a profile specific property files then it will not be imported a second time. |
### 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
- YAML
```
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.
#### Using âFixedâ and âImport Relativeâ Locations
Imports may be specified as *fixed* or *import relative* locations. A fixed location always resolves to the same underlying resource, regardless of where the `spring.config.import` property is declared. An import relative location resolves relative to the file that declares the `spring.config.import` property.
A location starting with a forward slash (`/`) or a URL style prefix (`file:`, `classpath:`, etc.) is considered fixed. All other locations are considered import relative.
| | |
|---|---|
| | `optional:` prefixes are not considered when determining if a location is fixed or import relative. |
As an example, say we have a `/demo` directory containing our `application.jar` file. We might add a `/demo/application.properties` file with the following content:
```
spring.config.import=optional:core/core.properties
```
This is an import relative location and so will attempt to load the file `/demo/core/core.properties` if it exists.
If `/demo/core/core.properties` has the following content:
```
spring.config.import=optional:extra/extra.properties
```
It will attempt to load `/demo/core/extra/extra.properties`. The `optional:extra/extra.properties` is relative to `/demo/core/core.properties` so the full directory is `/demo/core/` + `extra/extra.properties`.
#### Property Ordering
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
- YAML
```
spring.config.import=my.properties
my.property=value
```
```
spring:
config:
import: "my.properties"
my:
property: "value"
```
- Properties
- YAML
```
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.
| | |
|---|---|
| | When appropriate, [Profile-specific variants](https://docs.spring.io/spring-boot/reference/features/external-config.html#features.external-config.files.profile-specific) are also considered for import. The example above would import both `my.properties` as well as any `my-<profile>.properties` variants. |
| | |
|---|---|
| | 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](https://docs.spring.io/spring-boot/reference/features/external-config.html#features.external-config.files.configtree). 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. |
### 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
- YAML
```
spring.config.import=file:/etc/config/myconfig[.yaml]
```
```
spring:
config:
import: "file:/etc/config/myconfig[.yaml]"
```
### Using Environment Variables
When running applications on a cloud platform (such as Kubernetes) you often need to read config values that the platform supplies. You can either use environment variables for such purpose, or you can use [configuration trees](https://docs.spring.io/spring-boot/reference/features/external-config.html#features.external-config.files.configtree).
You can even store whole configurations in properties or yaml format in (multiline) environment variables and load them using the `env:` prefix. Assume thereâs an environment variable called `MY_CONFIGURATION` with this content:
```
my.name=Service1
my.cluster=Cluster1
```
Using the `env:` prefix it is possible to import all properties from this variable:
- Properties
- YAML
```
spring.config.import=env:MY_CONFIGURATION
```
```
spring:
config:
import: "env:MY_CONFIGURATION"
```
| | |
|---|---|
| | This feature also supports [specifying the extension](https://docs.spring.io/spring-boot/reference/features/external-config.html#features.external-config.files.importing-extensionless). The default extension is `.properties`. |
### Using Configuration Trees
Storing config values in environment variables has 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`](https://kubernetes.io/docs/tasks/configure-pod-container/configure-pod-configmap/#populate-a-volume-with-data-stored-in-a-configmap) and [`Secrets`](https://kubernetes.io/docs/concepts/configuration/secret/#using-secrets-as-files-from-a-pod).
There are two common volume mount patterns that can be used:
1. A single file contains a complete set of properties (usually written as YAML).
2. 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](https://docs.spring.io/spring-boot/reference/features/external-config.html#features.external-config.files.importing). 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:
- Properties
- YAML
```
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`](https://docs.spring.io/spring-framework/docs/7.0.x/javadoc-api/org/springframework/core/env/Environment.html) in the usual way.
| | |
|---|---|
| | The names of the folders and files under the config tree form the property name. In the above example, to access the properties as `username` and `password`, you can set `spring.config.import` to `optional:configtree:/etc/config/myapp`. |
| | |
|---|---|
| | Filenames with dot notation are also correctly mapped. For example, in the above example, a file named `myapp.username` in `/etc/config` would result in a `myapp.username` property in the [`Environment`](https://docs.spring.io/spring-framework/docs/7.0.x/javadoc-api/org/springframework/core/env/Environment.html). |
| | |
|---|---|
| | Configuration tree values can be bound to both string [`String`](https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/String.html) 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. As with a non-wildcard import, the names of the folders and files under each config tree form the property name.
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:
- Properties
- YAML
```
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:
- Properties
- YAML
```
spring.config.import=optional:configtree:/run/secrets/
```
```
spring:
config:
import: "optional:configtree:/run/secrets/"
```
### Property Placeholders
The values in `application.properties` and `application.yaml` are filtered through the existing [`Environment`](https://docs.spring.io/spring-framework/docs/7.0.x/javadoc-api/org/springframework/core/env/Environment.html) 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
- YAML
```
app.name=MyApp
app.description=${app.name} is a Spring Boot application written by ${username:Unknown}
```
```
app:
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](https://docs.spring.io/spring-boot/reference/features/external-config.html#features.external-config.typesafe-configuration-properties.relaxed-binding) [`@ConfigurationProperties`](https://docs.spring.io/spring-boot/4.0.5/api/java/org/springframework/boot/context/properties/ConfigurationProperties.html). 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 use `${demo.itemPrice}` instead, it will pick up the `demo.itemPrice` form from the `application.properties` file, as well as `DEMO_ITEMPRICE` from the system environment, but `demo.item-price` would not be considered. |
| | |
|---|---|
| | You can also use this technique to create âshortâ variants of existing Spring Boot properties. See the [Use âShortâ Command Line Arguments](https://docs.spring.io/spring-boot/how-to/properties-and-configuration.html#howto.properties-and-configuration.short-command-line-arguments) section in âHow-to Guidesâ for details. |
### 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.yaml` 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](https://docs.spring.io/spring-boot/reference/features/external-config.html#features.external-config.files.activation-properties) for details. |
### 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:
| Property | Note |
|---|---|
| `on-profile` | A profile expression that must match for the document to be active, or a list of profile expressions of which at least one must match for the document to be active. |
| `on-cloud-platform` | The [`CloudPlatform`](https://docs.spring.io/spring-boot/4.0.5/api/java/org/springframework/boot/cloud/CloudPlatform.html) that must be detected for the document to be active. |
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
- YAML
```
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"
```
## Encrypting Properties
If you need a secure way to store credentials and passwords, the [Spring Cloud Vault](https://cloud.spring.io/spring-cloud-vault/) project provides support for storing externalized configuration in [HashiCorp Vault](https://www.vaultproject.io/).
## Working With YAML
[YAML](https://yaml.org/) is a superset of JSON and, as such, is a convenient format for specifying hierarchical configuration data. The [`SpringApplication`](https://docs.spring.io/spring-boot/4.0.5/api/java/org/springframework/boot/SpringApplication.html) class automatically supports YAML as an alternative to properties whenever you have the [SnakeYAML](https://github.com/snakeyaml/snakeyaml) library on your classpath.
| | |
|---|---|
| | If you use starters, SnakeYAML is automatically provided by `spring-boot-starter`. |
### 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`](https://docs.spring.io/spring-framework/docs/7.0.x/javadoc-api/org/springframework/core/env/Environment.html). 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`](https://docs.spring.io/spring-framework/docs/7.0.x/javadoc-api/org/springframework/core/env/Environment.html), 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`](https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/util/List.html) or [`Set`](https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/util/Set.html) objects using Spring Bootâs [`Binder`](https://docs.spring.io/spring-boot/4.0.5/api/java/org/springframework/boot/context/properties/bind/Binder.html) class. For more details see the [Type-safe Configuration Properties](https://docs.spring.io/spring-boot/reference/features/external-config.html#features.external-config.typesafe-configuration-properties) section below. |
| | |
|---|---|
| | YAML files cannot be loaded by using the [`@PropertySource`](https://docs.spring.io/spring-framework/docs/7.0.x/javadoc-api/org/springframework/context/annotation/PropertySource.html) or [`@TestPropertySource`](https://docs.spring.io/spring-framework/docs/7.0.x/javadoc-api/org/springframework/test/context/TestPropertySource.html) annotations. So, in the case that you need to load values that way, you need to use a properties file. |
## Configuring Random Values
The [`RandomValuePropertySource`](https://docs.spring.io/spring-boot/4.0.5/api/java/org/springframework/boot/env/RandomValuePropertySource.html) 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
- YAML
```
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).
## 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`](https://docs.spring.io/spring-boot/4.0.5/api/java/org/springframework/boot/SpringApplication.html) by calling the `setEnvironmentPrefix(âŚâ)` method before the application is run.
For example, if you set the prefix to `input`, a property such as `remote.timeout` will be resolved as `INPUT_REMOTE_TIMEOUT` in the system environment.
| | |
|---|---|
| | The prefix *only* applies to system environment properties. The example above would continue to use `remote.timeout` when reading properties from other sources. |
## 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.
| | |
|---|---|
| | See also the [differences between](https://docs.spring.io/spring-boot/reference/features/external-config.html#features.external-config.typesafe-configuration-properties.vs-value-annotation) [`@Value`](https://docs.spring.io/spring-framework/docs/7.0.x/javadoc-api/org/springframework/beans/factory/annotation/Value.html) and type-safe configuration properties. |
### JavaBean Properties Binding
It is possible to bind a bean declaring standard JavaBean properties as shown in the following example:
- Java
- Kotlin
```
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"))
}
}
```
The preceding POJO defines the following properties:
- `my.service.enabled`, with a value of `false` by default.
- `my.service.remote-address`, with a type that can be coerced from [`String`](https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/String.html).
- `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`](https://docs.spring.io/spring-boot/4.0.5/api/java/org/springframework/boot/security/autoconfigure/SecurityProperties.html).
- `my.service.security.password`.
- `my.service.security.roles`, with a collection of [`String`](https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/String.html) that defaults to `USER`.
| | |
|---|---|
| | To use a reserved keyword in the name of a property, such as `my.service.import`, use the [`@Name`](https://docs.spring.io/spring-boot/4.0.5/api/java/org/springframework/boot/context/properties/bind/Name.html) annotation on the propertyâs field. |
| | |
|---|---|
| | The properties that map to [`@ConfigurationProperties`](https://docs.spring.io/spring-boot/4.0.5/api/java/org/springframework/boot/context/properties/ConfigurationProperties.html) classes available in Spring Boot, which are configured through properties files, YAML files, environment variables, and other mechanisms, 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: Pre-initialized Maps and Collections, as long as they are initialized with a mutable implementation (like the `roles` field in the preceding example). Pre-initialized nested POJOs (like the `Security` field in the preceding example). 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. |
### Constructor Binding
The example in the previous section can be rewritten in an immutable fashion as shown in the following example:
- Java
- Kotlin
```
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`](https://docs.spring.io/spring-boot/4.0.5/api/java/org/springframework/boot/context/properties/bind/ConstructorBinding.html) annotation can be used to specify which constructor to use for constructor binding.
To opt-out of constructor binding for a class, the parameterized constructor must be annotated with [`@Autowired`](https://docs.spring.io/spring-framework/docs/7.0.x/javadoc-api/org/springframework/beans/factory/annotation/Autowired.html) or made `private`. Kotlin developers can use an empty primary constructor to opt-out of constructor binding.
For example:
- Java
- Kotlin
```
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.ConfigurationProperties;
@ConfigurationProperties("my")
public class MyProperties {
// fields...
final MyBean myBean;
private String name;
@Autowired
public MyProperties(MyBean myBean) {
this.myBean = myBean;
}
// getters / setters...
public String getName() {
return this.name;
}
public void setName(String name) {
this.name = name;
}
}
```
```
import org.springframework.boot.context.properties.ConfigurationProperties
@ConfigurationProperties("my")
class MyProperties() {
constructor(name: String) : this() {
this.name = name
}
// vars...
var name: String? = null
}
```
Constructor binding can be used with records. Unless your record has multiple constructors, there is no need to use [`@ConstructorBinding`](https://docs.spring.io/spring-boot/4.0.5/api/java/org/springframework/boot/context/properties/bind/ConstructorBinding.html).
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`](https://docs.spring.io/spring-boot/4.0.5/api/java/org/springframework/boot/context/properties/bind/DefaultValue.html) on constructor parameters and record components. The conversion service will be applied to coerce the annotationâs [`String`](https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/String.html) 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`](https://docs.spring.io/spring-boot/4.0.5/api/java/org/springframework/boot/context/properties/bind/DefaultValue.html) annotation:
- Java
- Kotlin
```
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`](https://docs.spring.io/spring-boot/4.0.5/api/java/org/springframework/boot/context/properties/EnableConfigurationProperties.html) or configuration property scanning. You cannot use constructor binding with beans that are created by the regular Spring mechanisms (for example [`@Component`](https://docs.spring.io/spring-framework/docs/7.0.x/javadoc-api/org/springframework/stereotype/Component.html) beans, beans created by using [`@Bean`](https://docs.spring.io/spring-framework/docs/7.0.x/javadoc-api/org/springframework/context/annotation/Bean.html) methods or beans loaded by using [`@Import`](https://docs.spring.io/spring-framework/docs/7.0.x/javadoc-api/org/springframework/context/annotation/Import.html)) |
| | |
|---|---|
| | To use constructor binding 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 [`Optional`](https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/util/Optional.html) with [`@ConfigurationProperties`](https://docs.spring.io/spring-boot/4.0.5/api/java/org/springframework/boot/context/properties/ConfigurationProperties.html) 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`](https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/util/Optional.html) property and it has no value, `null` rather than an empty [`Optional`](https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/util/Optional.html) will be bound. |
| | |
|---|---|
| | To use a reserved keyword in the name of a property, such as `my.service.import`, use the [`@Name`](https://docs.spring.io/spring-boot/4.0.5/api/java/org/springframework/boot/context/properties/bind/Name.html) annotation on the constructor parameter. |
### Enabling @ConfigurationProperties-annotated Types
Spring Boot provides infrastructure to bind [`@ConfigurationProperties`](https://docs.spring.io/spring-boot/4.0.5/api/java/org/springframework/boot/context/properties/ConfigurationProperties.html) 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`](https://docs.spring.io/spring-boot/4.0.5/api/java/org/springframework/boot/context/properties/ConfigurationProperties.html) 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`](https://docs.spring.io/spring-boot/4.0.5/api/java/org/springframework/boot/context/properties/EnableConfigurationProperties.html) annotation. This can be done on any [`@Configuration`](https://docs.spring.io/spring-framework/docs/7.0.x/javadoc-api/org/springframework/context/annotation/Configuration.html) class, as shown in the following example:
- Java
- Kotlin
```
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
```
- Java
- Kotlin
```
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`](https://docs.spring.io/spring-boot/4.0.5/api/java/org/springframework/boot/context/properties/ConfigurationPropertiesScan.html) annotation to your application. Typically, it is added to the main application class that is annotated with [`@SpringBootApplication`](https://docs.spring.io/spring-boot/4.0.5/api/java/org/springframework/boot/autoconfigure/SpringBootApplication.html) but it can be added to any [`@Configuration`](https://docs.spring.io/spring-framework/docs/7.0.x/javadoc-api/org/springframework/context/annotation/Configuration.html) 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:
- Java
- Kotlin
```
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`](https://docs.spring.io/spring-boot/4.0.5/api/java/org/springframework/boot/context/properties/ConfigurationProperties.html) bean is registered using configuration property scanning or through [`@EnableConfigurationProperties`](https://docs.spring.io/spring-boot/4.0.5/api/java/org/springframework/boot/context/properties/EnableConfigurationProperties.html), the bean has a conventional name: `<prefix>-<fqn>`, where `<prefix>` is the environment key prefix specified in the [`@ConfigurationProperties`](https://docs.spring.io/spring-boot/4.0.5/api/java/org/springframework/boot/context/properties/ConfigurationProperties.html) 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`](https://docs.spring.io/spring-boot/4.0.5/api/java/org/springframework/boot/context/properties/ConfigurationProperties.html) 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`](https://docs.spring.io/spring-framework/docs/7.0.x/javadoc-api/org/springframework/context/EnvironmentAware.html) if you need access to the [`Environment`](https://docs.spring.io/spring-framework/docs/7.0.x/javadoc-api/org/springframework/core/env/Environment.html)). If you still want to inject other beans using the constructor, the configuration properties bean must be annotated with [`@Component`](https://docs.spring.io/spring-framework/docs/7.0.x/javadoc-api/org/springframework/stereotype/Component.html) and use JavaBean-based property binding.
### Using @ConfigurationProperties-annotated Types
This style of configuration works particularly well with the [`SpringApplication`](https://docs.spring.io/spring-boot/4.0.5/api/java/org/springframework/boot/SpringApplication.html) external YAML configuration, as shown in the following example:
```
my:
service:
remote-address: 192.168.1.1
security:
username: "admin"
roles:
- "USER"
- "ADMIN"
```
To work with [`@ConfigurationProperties`](https://docs.spring.io/spring-boot/4.0.5/api/java/org/springframework/boot/context/properties/ConfigurationProperties.html) beans, you can inject them in the same way as any other bean, as shown in the following example:
- Java
- Kotlin
```
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();
// ...
}
// ...
}
```
```
import org.springframework.stereotype.Service
@Service
class MyService(val properties: MyProperties) {
fun openConnection() {
val server = Server(properties.remoteAddress)
server.start()
// ...
}
// ...
}
```
| | |
|---|---|
| | Using [`@ConfigurationProperties`](https://docs.spring.io/spring-boot/4.0.5/api/java/org/springframework/boot/context/properties/ConfigurationProperties.html) also lets you generate metadata files that can be used by IDEs to offer auto-completion for your own keys. See the [appendix](https://docs.spring.io/spring-boot/specification/configuration-metadata/index.html) for details. |
### Third-party Configuration
As well as using [`@ConfigurationProperties`](https://docs.spring.io/spring-boot/4.0.5/api/java/org/springframework/boot/context/properties/ConfigurationProperties.html) to annotate a class, you can also use it on public [`@Bean`](https://docs.spring.io/spring-framework/docs/7.0.x/javadoc-api/org/springframework/context/annotation/Bean.html) 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`](https://docs.spring.io/spring-framework/docs/7.0.x/javadoc-api/org/springframework/core/env/Environment.html) properties, add [`@ConfigurationProperties`](https://docs.spring.io/spring-boot/4.0.5/api/java/org/springframework/boot/context/properties/ConfigurationProperties.html) to its bean registration, as shown in the following example:
- Java
- Kotlin
```
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("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("another")
fun anotherComponent(): AnotherComponent = AnotherComponent()
}
```
Any JavaBean property defined with the `another` prefix is mapped onto that `AnotherComponent` bean in manner similar to the preceding `SomeProperties` example.
### Relaxed Binding
Spring Boot uses some relaxed rules for binding [`Environment`](https://docs.spring.io/spring-framework/docs/7.0.x/javadoc-api/org/springframework/core/env/Environment.html) properties to [`@ConfigurationProperties`](https://docs.spring.io/spring-boot/4.0.5/api/java/org/springframework/boot/context/properties/ConfigurationProperties.html) beans, so there does not need to be an exact match between the [`Environment`](https://docs.spring.io/spring-framework/docs/7.0.x/javadoc-api/org/springframework/core/env/Environment.html) 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`).
- Java
- Kotlin
```
import org.springframework.boot.context.properties.ConfigurationProperties;
@ConfigurationProperties("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("my.main-project.person")
class MyPersonProperties {
var firstName: String? = null
}
```
With the preceding code, the following properties names can all be used:
| Property | Note |
|---|---|
| `my.main-project.person.first-name` | Kebab case, which is recommended for use in `.properties` and YAML 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 YAML files. |
| `MY_MAINPROJECT_PERSON_FIRSTNAME` | 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 `my.main-project.person`). |
| Property Source | Simple | List |
|---|---|---|
| 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](https://docs.spring.io/spring-boot/reference/features/external-config.html#features.external-config.typesafe-configuration-properties.relaxed-binding.environment-variables)). | Numeric values surrounded by underscores (see [Binding From Environment Variables](https://docs.spring.io/spring-boot/reference/features/external-config.html#features.external-config.typesafe-configuration-properties.relaxed-binding.environment-variables)) |
| System properties | Camel case, kebab case, or underscore notation | Standard list syntax using `[ ]` or comma-separated values |
| | |
|---|---|
| | We recommend that, when possible, properties are stored in lower-case kebab format, such as `my.person.first-name=Rod`. |
#### Binding Maps
When binding to [`Map`](https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/util/Map.html) 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
- YAML
```
my.map[/key1]=value1
my.map[/key2]=value2
my.map./key3=value3
```
```
my:
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`](https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/util/Map.html) 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`](https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/Object.html). 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:
- 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`](https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/util/List.html), 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`.
Support for binding from environment variables is applied to the `systemEnvironment` property source and to any additional property source whose name ends with `-systemEnvironment`.
#### Binding Maps From Environment Variables
When Spring Boot binds an environment variable to a property class, it lowercases the environment variable name before binding. Most of the time this detail isnât important, except when binding to [`Map`](https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/util/Map.html) properties.
The keys in the [`Map`](https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/util/Map.html) are always in lowercase, as seen in the following example:
- Java
- Kotlin
```
import java.util.HashMap;
import java.util.Map;
import org.springframework.boot.context.properties.ConfigurationProperties;
@ConfigurationProperties("my.props")
public class MyMapsProperties {
private final Map<String, String> values = new HashMap<>();
public Map<String, String> getValues() {
return this.values;
}
}
```
```
import org.springframework.boot.context.properties.ConfigurationProperties
@ConfigurationProperties("my.props")
class MyMapsProperties {
val values: Map<String, String> = HashMap()
}
```
When setting `MY_PROPS_VALUES_KEY=value`, the `values` [`Map`](https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/util/Map.html) contains a `{"key"="value"}` entry.
Only the environment variable **name** is lower-cased, not the value. When setting `MY_PROPS_VALUES_KEY=VALUE`, the `values` [`Map`](https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/util/Map.html) contains a `{"key"="VALUE"}` entry.
#### Caching
Relaxed binding uses a cache to improve performance. By default, this caching is only applied to immutable property sources. To customize this behavior, for example to enable caching for mutable property sources, use [`ConfigurationPropertyCaching`](https://docs.spring.io/spring-boot/4.0.5/api/java/org/springframework/boot/context/properties/source/ConfigurationPropertyCaching.html).
### 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`:
- Java
- Kotlin
```
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()
}
```
Consider the following configuration:
- Properties
- YAML
```
my.list[0].name=my name
my.list[0].description=my description
#---
spring.config.activate.on-profile=dev
my.list[0].name=my another name
```
```
my:
list:
- name: "my name"
description: "my description"
---
spring:
config:
activate:
on-profile: "dev"
my:
list:
- name: "my another name"
```
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`](https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/util/List.html) is specified in multiple profiles, the one with the highest priority (and only that one) is used. Consider the following example:
- Properties
- YAML
```
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
```
```
my:
list:
- name: "my name"
description: "my description"
- name: "another name"
description: "another description"
---
spring:
config:
activate:
on-profile: "dev"
my:
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`](https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/util/Map.html) 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`:
- Java
- Kotlin
```
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()
}
```
Consider the following configuration:
- Properties
- YAML
```
my.map.key1.name=my name 1
my.map.key1.description=my description 1
#---
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
```
```
my:
map:
key1:
name: "my name 1"
description: "my description 1"
---
spring:
config:
activate:
on-profile: "dev"
my:
map:
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`).
| | |
|---|---|
| | The preceding merging rules apply to properties from all property sources, and not just files. |
### Properties Conversion
Spring Boot attempts to coerce the external application properties to the right type when it binds to the [`@ConfigurationProperties`](https://docs.spring.io/spring-boot/4.0.5/api/java/org/springframework/boot/context/properties/ConfigurationProperties.html) beans. If you need custom type conversion, you can provide a [`ConversionService`](https://docs.spring.io/spring-framework/docs/7.0.x/javadoc-api/org/springframework/core/convert/ConversionService.html) bean (with a bean named `conversionService`) or custom property editors (through a [`CustomEditorConfigurer`](https://docs.spring.io/spring-framework/docs/7.0.x/javadoc-api/org/springframework/beans/factory/config/CustomEditorConfigurer.html) bean) or custom converters (with bean definitions annotated as [`@ConfigurationPropertiesBinding`](https://docs.spring.io/spring-boot/4.0.5/api/java/org/springframework/boot/context/properties/ConfigurationPropertiesBinding.html)).
| | |
|---|---|
| | Beans used for property conversion are requested very early during the application lifecycle so make sure to limit the dependencies that your [`ConversionService`](https://docs.spring.io/spring-framework/docs/7.0.x/javadoc-api/org/springframework/core/convert/ConversionService.html) is using. Typically, any dependency that you require may not be fully initialized at creation time. |
| | |
|---|---|
| | You may want to rename your custom [`ConversionService`](https://docs.spring.io/spring-framework/docs/7.0.x/javadoc-api/org/springframework/core/convert/ConversionService.html) if it is not required for configuration keys coercion and only rely on custom converters qualified with [`@ConfigurationPropertiesBinding`](https://docs.spring.io/spring-boot/4.0.5/api/java/org/springframework/boot/context/properties/ConfigurationPropertiesBinding.html). When qualifying a `@Bean` method with `@ConfigurationPropertiesBinding`, the method should be `static` to avoid âbean is not eligible for getting processed by all BeanPostProcessorsâ warnings. |
#### Converting Durations
Spring Boot has dedicated support for expressing durations. If you expose a [`Duration`](https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/time/Duration.html) property, the following formats in application properties are available:
- A regular `long` representation (using milliseconds as the default unit unless a [`@DurationUnit`](https://docs.spring.io/spring-boot/4.0.5/api/java/org/springframework/boot/convert/DurationUnit.html) has been specified)
- The standard ISO-8601 format [used by](https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/time/Duration.html#parse\(java.lang.CharSequence\)) [`Duration`](https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/time/Duration.html)
- A more readable format where the value and the unit are coupled (`10s` means 10 seconds)
Consider the following example:
- Java
- Kotlin
```
import java.time.Duration;
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:
- `ns` for nanoseconds
- `us` for microseconds
- `ms` for milliseconds
- `s` for seconds
- `m` for minutes
- `h` for hours
- `d` for days
The default unit is milliseconds and can be overridden using [`@DurationUnit`](https://docs.spring.io/spring-boot/4.0.5/api/java/org/springframework/boot/convert/DurationUnit.html) 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:
- Java
- Kotlin
```
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`](https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/Long.html) property, make sure to define the unit (using [`@DurationUnit`](https://docs.spring.io/spring-boot/4.0.5/api/java/org/springframework/boot/convert/DurationUnit.html)) 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 [`Period`](https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/time/Period.html) type. The following formats can be used in application properties:
- A regular `int` representation (using days as the default unit unless a [`@PeriodUnit`](https://docs.spring.io/spring-boot/4.0.5/api/java/org/springframework/boot/convert/PeriodUnit.html) has been specified)
- The standard ISO-8601 format [used by](https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/time/Period.html#parse\(java.lang.CharSequence\)) [`Period`](https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/time/Period.html)
- A simpler format where the value and the unit pairs are coupled (`1y3d` means 1 year and 3 days)
The following units are supported with the simple format:
- `y` for years
- `m` for months
- `w` for weeks
- `d` for days
| | |
|---|---|
| | The [`Period`](https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/time/Period.html) type never actually stores the number of weeks, it is a shortcut that means â7 daysâ. |
#### Converting Data Sizes
Spring Framework has a [`DataSize`](https://docs.spring.io/spring-framework/docs/7.0.x/javadoc-api/org/springframework/util/unit/DataSize.html) value type that expresses a size in bytes. If you expose a [`DataSize`](https://docs.spring.io/spring-framework/docs/7.0.x/javadoc-api/org/springframework/util/unit/DataSize.html) property, the following formats in application properties are available:
- A regular `long` representation (using bytes as the default unit unless a [`@DataSizeUnit`](https://docs.spring.io/spring-boot/4.0.5/api/java/org/springframework/boot/convert/DataSizeUnit.html) has been specified)
- A more readable format where the value and the unit are coupled (`10MB` means 10 megabytes)
Consider the following example:
- Java
- Kotlin
```
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:
- `B` for bytes
- `KB` for kilobytes
- `MB` for megabytes
- `GB` for gigabytes
- `TB` for terabytes
The default unit is bytes and can be overridden using [`@DataSizeUnit`](https://docs.spring.io/spring-boot/4.0.5/api/java/org/springframework/boot/convert/DataSizeUnit.html) 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:
- Java
- Kotlin
```
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`](https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/Long.html) property, make sure to define the unit (using [`@DataSizeUnit`](https://docs.spring.io/spring-boot/4.0.5/api/java/org/springframework/boot/convert/DataSizeUnit.html)) if it is not bytes. Doing so gives a transparent upgrade path while supporting a much richer format. |
#### Converting Base64 Data
Spring Boot supports resolving binary data that have been Base64 encoded. If you expose a `Resource` property, the base64 encoded text can be provided as the value with a `base64:` prefix, as shown in the following example:
- Properties
- YAML
```
my.property=base64:SGVsbG8gV29ybGQ=
```
```
my:
property: base64:SGVsbG8gV29ybGQ=
```
| | |
|---|---|
| | The `Resource` property can also be used to provide the path to the resource, making it more versatile. |
### @ConfigurationProperties Validation
Spring Boot attempts to validate [`@ConfigurationProperties`](https://docs.spring.io/spring-boot/4.0.5/api/java/org/springframework/boot/context/properties/ConfigurationProperties.html) classes whenever they are annotated with Springâs [`@Validated`](https://docs.spring.io/spring-framework/docs/7.0.x/javadoc-api/org/springframework/validation/annotation/Validated.html) 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:
- Java
- Kotlin
```
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
}
```
| | |
|---|---|
| | You can also trigger validation by annotating the [`@Bean`](https://docs.spring.io/spring-framework/docs/7.0.x/javadoc-api/org/springframework/context/annotation/Bean.html) method that creates the configuration properties with [`@Validated`](https://docs.spring.io/spring-framework/docs/7.0.x/javadoc-api/org/springframework/validation/annotation/Validated.html). |
To cascade validation to nested properties the associated field must be annotated with [`@Valid`](https://jakarta.ee/specifications/bean-validation/3.1/apidocs/jakarta/validation/Valid.html). The following example builds on the preceding `MyProperties` example:
- Java
- Kotlin
```
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`](https://docs.spring.io/spring-framework/docs/7.0.x/javadoc-api/org/springframework/validation/Validator.html) by creating a bean definition called `configurationPropertiesValidator`. The [`@Bean`](https://docs.spring.io/spring-framework/docs/7.0.x/javadoc-api/org/springframework/context/annotation/Bean.html) method should be declared `static`. The configuration properties validator is created very early in the applicationâs lifecycle, and declaring the [`@Bean`](https://docs.spring.io/spring-framework/docs/7.0.x/javadoc-api/org/springframework/context/annotation/Bean.html) method as static lets the bean be created without having to instantiate the [`@Configuration`](https://docs.spring.io/spring-framework/docs/7.0.x/javadoc-api/org/springframework/context/annotation/Configuration.html) class. Doing so avoids any problems that may be caused by early instantiation.
### @ConfigurationProperties vs. @Value
The [`@Value`](https://docs.spring.io/spring-framework/docs/7.0.x/javadoc-api/org/springframework/beans/factory/annotation/Value.html) 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`](https://docs.spring.io/spring-boot/4.0.5/api/java/org/springframework/boot/context/properties/ConfigurationProperties.html) and [`@Value`](https://docs.spring.io/spring-framework/docs/7.0.x/javadoc-api/org/springframework/beans/factory/annotation/Value.html):
| Feature | `@ConfigurationProperties` | `@Value` |
|---|---|---|
| [Relaxed binding](https://docs.spring.io/spring-boot/reference/features/external-config.html#features.external-config.typesafe-configuration-properties.relaxed-binding) | Yes | Limited (see [note below](https://docs.spring.io/spring-boot/reference/features/external-config.html#features.external-config.typesafe-configuration-properties.vs-value-annotation.note)) |
| [Meta-data support](https://docs.spring.io/spring-boot/specification/configuration-metadata/index.html) | Yes | No |
| `SpEL` evaluation | No | Yes |
| | |
|---|---|
| | If you do want to use [`@Value`](https://docs.spring.io/spring-framework/docs/7.0.x/javadoc-api/org/springframework/beans/factory/annotation/Value.html), 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](https://docs.spring.io/spring-boot/reference/features/external-config.html#features.external-config.typesafe-configuration-properties.relaxed-binding) [`@ConfigurationProperties`](https://docs.spring.io/spring-boot/4.0.5/api/java/org/springframework/boot/context/properties/ConfigurationProperties.html). 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 use `@Value("${demo.itemPrice}")` instead, it will pickup the `demo.itemPrice` form from the `application.properties` file, as well as `DEMO_ITEMPRICE` from the system environment, but `demo.item-price` 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`](https://docs.spring.io/spring-boot/4.0.5/api/java/org/springframework/boot/context/properties/ConfigurationProperties.html). Doing so will provide you with structured, type-safe object that you can inject into your own beans.
`SpEL` expressions from [application property files](https://docs.spring.io/spring-boot/reference/features/external-config.html#features.external-config.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`](https://docs.spring.io/spring-framework/docs/7.0.x/javadoc-api/org/springframework/beans/factory/annotation/Value.html). If the value of a property from an application property file is a `SpEL` expression, it will be evaluated when consumed through [`@Value`](https://docs.spring.io/spring-framework/docs/7.0.x/javadoc-api/org/springframework/beans/factory/annotation/Value.html). |
| Shard | 155 (laksa) |
| Root Hash | 4731383841208343755 |
| Unparsed URL | io,spring!docs,/spring-boot/reference/features/external-config.html s443 |