kotlin-baker

Facilitates Kotlin objects creation from properties

View on GitHub

Maven Central Build Status

Tl;DR

Create Kotlin data classes in a highly customizable way from Spring Cloud Config.

Description

Spring Cloud Config is a great way to manage application configuration. Kotlin is one of the best JVM languages, but there is a gap between that two - even though Spring provides @ConfiugrationProperties, they don’t really work with data classes.

Another concern is that it’s hard to achieve hierarchical configuration with collection/map properties.

Kotlin Baker library facilitates data classes creation with highly customizable setup and support for hierarchical configuration.

Example

Consider that we have the following domain:

data class Tasks(val tasks: Map<String, TaskConfig>)

data class TaskConfig(val id: String, val properties: Map<String, Any>)

We can create configs hierarchy for it:

Now we can configure our domain class in Spring using Kotlin Baker:

@Bean
open fun tasks(creator: KotlinCreator, context: Context): Tasks {
    return creator.create("", Tasks::class.createType(), context)
}

@Bean
open fun creator(environment: Environment): KotlinCreator {
    return CacheAwareCreator()
}

@Bean
open fun creatorContext(environment: Environment): Context {
    val allKeys = getAllPropertyKeys(environment)
    return Context.builder {
        environment[it]
    }.withMapKeyStrategy { baseName, _ ->
        val prefix = "$baseName."
        allKeys.mapNotNull { key ->
            if (key.startsWith(prefix)) {
                val i = key.indexOf(".", prefix.length)
                if (i < 0) {
                    key.substring(prefix.length)
                } else {
                    key.substring(prefix.length, i)
                }
            } else {
                null
            }
        }.toSet()
    }.build()
}

When Spring context with profiles production,APAC is initialized, we can see that

Note: the last declared profile has higher precedence, i.e. if we want ‘APAC’ values to override ‘common production’ values, we need to define profiles like ‘production,APAC’. Feel free to read more about that in Spring documentation

The example above can be found here:

  1. Launch ServerApplication
  2. Launch ClientApplication
  3. Check that client application reports the following domain class setup:
    Found the following tasks: Tasks(tasks={task2=TaskConfig(id=task2, properties={prop2=apacTask2Prop2, prop1=commonTask2Prop1}), task1=TaskConfig(id=task1, properties={prop2=productionTask1Prop2, prop1=commonTask1Prop1})})
    

Releases

Release Notes

How to Contribute