Small and simple configuration injection for Kotlin.
Inspired by Spring's @Value
but more explicit and idiomatic.
Also, easy as pie and a tad opinionated.
Konfig
allows injecting configuration file content as a tree-like Map
.
Konfig
is a globally accessible, immutable singleton object
implementing
the Map
-interface and can be used as such. It is initialised on startup,
any (meta) configuration has to be done via providing environment variables.
The contents of the Konfig
map support access via either flat dot-notation,
as used by properties
files, as well as regular tree-like nesting access.
Konfig
supports the following file formats:
YML
JSON
Properties
By default Konfig
loads a konfig.{yml,json,properties}
file from the classpath,
if present. If none is present initialisation will fail with an Error
.
Configuration files can also be loaded from custom non-classpath locations by
specifying the environment variable KONFIG_URL
and providing a valid URL
pointing to the external configuration file.
This mechanism supports the following protcols:
HTTP
HTTPS
FILE
, with absolute and relative paths
Provided one of the following is on the classpath:
konfig.yml
string: A string
int: 9000
double: 0.5
konfig.json
{
"string": "A string",
"int": 9000,
"double": 0.5
}
konfig.properties
string=A string
int=9000
double=0.5
Inject the parameters by way of Kotlin field delegation:
class Service {
val string: String by Konfig
val int: Int by Konfig
val double: Double by Konfig
}
Note: This follows the same pattern of delegation as via a Map<String, Any>
,
i.e. you have to make sure the field name and the configuration key match.
If you want to use a different field name, use Konfig.nested("key path")
instead -
you are free to choose your field name as you wish in this case.
To inject a nested, i.e. not top-level, element of your configuration, specify the key-path to it via:
Konfig.nested("path.to.subtree")
This can even be a whole subtree, and can be used to avoid one of Spring's @Value
shortcomings; instead of injecting each respective value by specifying its full
key-path prefix for every single one, inject the prefix element as a NestedKonfig
or
Map<String, Any>
, and delegate injection to the prefix element:
konfig.yml
(YML
only for brevity)
complex:
multilevel:
structure:
int: 9000
double: 0.5
And use it like this:
class Service {
val nested: NestedKonfig by Konfig.nested("complex.multilevel.structure")
val int: Int by nested
val double: Double by nested
}
Note the absence of duplicated Konfig.nested("complex.multilevel.structure")
prefix
declarations.
Some of Kotlin's primitive types:
- Boolean
- Int
- Double
- String
And two collection types:
- List (where T is one of the valid primitives or collection types;
YML
andJSON
only) - Map<String, T> (where T is one of the valid primitives or collections types)
Note: As per usual with field delegation, loading and thus also type checking occurs lazily on first access of the field.
Since configuration is not merged from multiple files, make sure to only provide one configuration file format at once.
Default (classpath) configuration files are looked up in the following order:
- YML
- JSON
- Properties
<dependency>
<groupId>io.github.vyo.konfig</groupId>
<artifactId>konfig</artifactId>
<version>0.2.1</version>
</dependency>
- Jackson, plus its Kotlin module
- Snake YAML