Configuration
Module is responsible for mapping the values of configuration files to classes in Kora and then using them for application settings.
HOCON¶
Support for HOCON is implemented with Typesafe Config. HOCON is a JSON-based config file format. The format is less strict than JSON and has a slightly different syntax.
services {
foo {
bar = "SomeValue" //(1)!
baz = 10 //(2)!
propRequired = ${REQUIRED_ENV_VALUE} //(3)!
propOptional = ${?OPTIONAL_ENV_VALUE} //(4)!
propDefault = 10
propDefault = ${?NON_DEFAULT_ENV_VALUE} //(5)!
propReference = ${services.foo.bar}Other${services.foo.baz} //(6)!
propArray = ["v1", "v2"] //(7)!
propArrayAsString = "v1, v2" //(8)!
propMap { //(9)!
"k1" = "v1"
"k2" = "v2"
}
}
}
- String configuration value
- Numeric configuration value
- Mandatory configuration value that is substituted from the
REQUIRED_ENV_VALUE
environment variable. - Optional configuration value which is substituted from the
OPTIONAL_ENV_VALUE
environment variable, if no such variable is found, the configuration value will be omitted. 5. - Configuration value with default value, the default value is specified in
propDefault = 10
and ifNON_DEFAULT_ENV_VALUE
environment variable is found, its value will replace the default value. - Configuration value assembled from substitutions of other parts of the configuration and the
Other
value between the - String list configuration value, the value is set as an array of strings or can also be set as a string with values separated by commas
- String list configuration value, the value is set as a string with values separated by commas or can also be set as an array of strings
- Configuration value as a dictionary key and value
Configuration representation in code:
Dependency¶
Dependency build.gradle
:
Module:
Dependency build.gradle.kts
:
Module:
File¶
By default, the configuration files reference.conf and application.conf are expected.
First, all reference.conf
files are merged, second, the application.conf
file is overlaid on the unresolved
reference.conf
file, the result is calculated and checked that all variable values are available.
It is assumed that the application configuration is in application.conf
and the library configurations are in reference.conf
.
Prioritize reading the application.conf
configuration file:
- Use the file from
config.resource
if specified (file fromresources
directory) - Use the file from
config.file
if specified (file from the file system) - Use the
application.conf
file if available (file fromresources
directory) - Use an empty configuration file if none of the above is present
YAML¶
Support for YAML is implemented using SnakeYAML.
services:
foo:
bar: "SomeValue" #(1)!
baz: 10 #(2)!
propRequired: ${REQUIRED_ENV_VALUE} #(3)!
propOptional: ${?OPTIONAL_ENV_VALUE} #(4)!
propDefault: ${?NON_DEFAULT_ENV_VALUE:10} #(5)!
propReference: ${services.foo.bar}Other${services.foo.baz} #(6)!
propArray: ["v1", "v2"] #(7)!
propArrayAsString: "v1, v2" #(8)!
propMap: #(9)!
k1: "v1"
k2: "v2"
- String configuration value
- Numeric configuration value
- Mandatory configuration value that is substituted from the
REQUIRED_ENV_VALUE
environment variable. - Optional configuration value which is substituted from the
OPTIONAL_ENV_VALUE
environment variable, if no such variable is found, the configuration value will be omitted. 5. - Configuration value with default value, the default value is specified as
10
and ifNON_DEFAULT_ENV_VALUE
environment variable is found, its value will replace the default value. - Configuration value assembled from substitutions of other parts of the configuration and the
Other
value between the - String list configuration value, the value is set as an array of strings or can also be set as a string with values separated by commas
- String list configuration value, the value is set as a string with values separated by commas or can also be set as an array of strings
- Configuration value as a dictionary key and value
Configuration representation in code:
Dependency¶
Dependency build.gradle
:
Module:
Dependency build.gradle.kts
:
Module:
File¶
By default, the reference.yaml
and application.yaml
configuration files are expected.
First, all reference.yaml
files are merged, second, the application.yaml
file is overlaid on an unresolved
reference.yaml
file, the result is calculated and it is checked that all variable values are available.
It is assumed that the application configuration is in the application.yaml
file and the library configurations are in reference.yaml
.
Prioritize reading the application.yaml
configuration file:
- Use the file from
config.resource
if specified (file fromresources
directory) - Use the file from
config.file
if specified (file from the file system) - Use the
application.yaml
file if available (file fromresources
directory) - Use an empty configuration file if none of the above is present
Custom configuration¶
A custom configuration provides a mapping of the configuration file to a user interface. Such a user interface can later be injected as a dependency along with other components.
Application config¶
In order to simplify the creation of custom configurations, the @ConfigSource
annotation should be used:
This code sample will add an instance of the FooServiceConfig
class to the dependency container, which when created will expect the following kind of configuration:
After that, the FooServiceConfig
class can already be used as a dependency in other classes:
Library config¶
In order to create custom configurations within custom libraries, use the @ConfigValueExtractor
annotation
which will create rules for processing a configuration file into an instance of a configuration class.
Let's consider an example when there is such a configuration class:
In order for the library to provide configuration, you need to implement the factory in a module:
The factory will expect a configuration of the following kind:
Then by connecting the FooLibraryModule
module in the application, the FooServiceConfig
config can be used as a dependency in other classes.
Required values¶
By default, all values declared in the config are considered required (NotNull) and must be present in the configuration file.
Optional values¶
If you need to specify a value from the configuration file as optional, you can use this format:
It is suggested to use the @Nullable
annotation over the method signature:
@ConfigSource("services.foo")
public interface FooServiceConfig {
@Nullable//(1)!
String bar();
int baz();
}
- Any
@Nullable
annotation will do, such asjavax.annotation.Nullable
/jakarta.annotation.Nullable
/org.jetbrains.annotations.Nullable
/ etc.
It is expected to use the Kotlin Nullability syntax and mark such a parameter as Nullable:
Default values¶
If there is a need to use default values in a class, you can use this format:
Injecting configuration¶
You can inject the base class ru.tinkoff.kora.config.common.Config
which provides a common abstraction over the
configuration file mapping. The resulting configuration mapping consists of several layers that represent:
- Environment variables
- System variables
- Configuration file
Environment variables¶
In case you want to embed the configuration only environment variables,
you can use the @Environment
annotation as a tag for the configuration class:
System variables¶
In case you want to inject a configuration of only system variables,
then you can use the @SystemProperties
annotation as a tag for the configuration class:
Configuration file¶
In case you want to inject a complete application configuration that consists only of a configuration file,
you can use the @ApplicationConfig
annotation as a tag for the configuration class:
Resulting configuration¶
If you want to inject a complete application configuration that consists of a configuration file, environment variables and system variables, you simply inject the configuration class without the tag:
Recommendations¶
Tip
We do not recommend using ru.tinkoff.kora.config.common.Config
directly as a dependency in components,
because when you update the configuration it will cause all graph components that use it to be updated,
it is recommended to always create custom user configuration interfaces.
Config Watcher¶
By default, Kora has a configuration file watcher that updates the contents of the configuration file, which causes the dependency graph for the affected components to be updated if the configuration file is changed.
You can disable the watcher by using:
- Environment variable
KORA_CONFIG_WATCHER_ENABLED
. - System property
kora.config.watcher.enabled
.
Supported types¶
Configuration Extractors provide an extensive list of supported types that covers most of what
you might need to specify in custom configurations, or you can extend the behavior with your custom ConfigValueExtractor<T>
component.
List of supported types
- boolean / Boolean
- short / Short
- int / Integer
- long / Long
- double / Double
- float / Float
- double[]
- String
- BigInteger
- BigDecimal
- Period
- Duration
- Size
- Properties
- Pattern
- UUID
- Properties
- LocalDate
- LocalTime
- LocalDateTime
- OffsetTime
- OffsetDateTime
- Enum (any custom ENUM type)
List<T>
(whereT
is any of the above listed types)Set<T>
(whereT
is any of the above types)Map<String, T>
(whereT
is any of the above types)Either<A, B>
(whereA
andB
are any of the above types)
Size¶
Size
is a special type that allows you to specify the size of bytes in a human-friendly system of calculations according to both the IEEE 1541-2002 (binary) standard and the SI (decimal) standard.
Example values:
1Mb
- 1 megabytes (1.000.000
bytes)1Mib
- 1 megabit (1.048.576
bytes)1024b
- 1024 bytes1024
- 1024 bytes
If just a number without a suffix is specified, it is considered that bytes are specified.