Ktor 3.2.0 will add support for automatically deserializing configuration files into data classes.
Let's define a simple application.yaml
that defines some database configuration.
database:
driverClassName: "$DB_DRIVER_CLASS_NAME:org.postgresql.Driver"
host: "$DB_HOST:localhost"
port: "$DATABASE_PORT:5432"
name: "$DB_NAME:ktor_sample"
username: "$DB_USERNAME:ktor_user"
password: "$DB_PASSWORD:ktor_password"
flyway:
locations: "$FLYWAY_LOCATIONS:classpath:db/migration"
baselineOnMigrate: "$FLYWAY_BASELINE_ON_MIGRATE:true"
Note: Ktor HOCON/YAML supports overriding from enviroment variables using: "$ENVIROMENT_KEY:fallback-value"
as shown above.
In order to deserialise into structure data, we need to define it first.
So we define 2 data classes that match our application.yaml
.
@Serializable
data class DatabaseConfig(
val driverClassName: String,
val host: String,
val port: Int,
val name: String,
val username: String,
val password: String,
val flyway: FlywayConfig
)
@Serializable data class FlywayConfig(val locations: String, val baselineOnMigrate: Boolean)
We need to make sure that the names of the data class properties match the fields defined in our yaml
.
Or you'll see errors like MissingRequiredPropertyException
or UnknownPropertyException
depending on the kind-of missmatch.
To deserialise we need to explicitely extract the desired property
from the configuration,
this can be done directly within the Application
DSL.
fun Application.module() {
property<DatabaseConfig>("database")
// Can also retrieve nested fields/objects
val flyway = property<FlywayConfig>("database.flyway")
}
In the test enviroment you can continue leveraging, and overwrite certain values.
fun test() = testApplication {
enviroment {
config = ApplicationConfig("application.yaml")
.mergeWith(MapApplicationConfig(
"database.host" to "other-host",
"database.username" to "SA",
"database.password" to ""
))
}
}
See Ktor EAP for more details.