spring-boot : declare yaml partials

It has been a question for me for many years :

How can I inject spring properties from a library right into my application without any overhead
* no copy / paste
* no reference in the configuration
* just by adding a maven / gradle dependency in the classpath.

I also need to declare these partials by discriminating by spring profiles (just like in application.yml)
These properties also need to be accessible in my own yaml

I want the library to declare common variables like these

domain-name: ${container-eks}.${environment}.${region}.${domain-name-suffix}

---
spring.profiles: eu

environment: dev
region: eu-west-1
domain-name-suffix: company.ext
container-deployer: eks

And then reuse them in my application.yml

user-api-url : https://user.${domain-name}/v2/
invoicing-api-url : https://invoicing.${domain-name}/v1/

Is that possible ?
Actually, you can write a very simple tool to load these yaml partials in your library,
just reuse that code in your library : https://gist.github.com/libetl/cb45dccaf27fd68a95fd79e3e02fad75

Then add an EnvironmentPostProcessor to your library :

package com.company.library.lib1

import com.company.library.tools.LoadYaml
import com.company.library.tools.LoadYaml.LoadOptions
import org.springframework.boot.SpringApplication
import org.springframework.boot.env.EnvironmentPostProcessor
import org.springframework.core.Ordered
import org.springframework.core.env.ConfigurableEnvironment
import org.springframework.core.io.ClassPathResource

internal class ApplicationSettingsConfiguration : EnvironmentPostProcessor {

override fun postProcessEnvironment(environment: ConfigurableEnvironment?, application: SpringApplication?) {

LoadYaml with LoadOptions(
environment,
deactivationProfile = "without-settings",
forApplicationScopeOnly = true,
yamlName = "lib1-settings(application)",
yamlClassPathResource = ClassPathResource("lib1-settings.yml"),
checkProfiles = true
)
}
}
In the above example, I have saved a yaml file in src/main/resources in my library called lib1-settings.yml where I have put all my common variables.

When checkProfiles is set to true, I can define several sections separated by ‘—‘ each where I can define differentiated values for predefined spring.profiles values.
deactivationProfile allows to skip the declaration of the yaml file if a profile is activated.
forApplicationScopeOnly determines whether to inject the vars in the bootstrap and application scopes or only in the application scope.

And with that, I am able to shrink how many variables I have to declare in my application, since a lot of them are already injected in my libraries.
My configuration file went down from 30kb to just 2kb, by defining variables for every environment and for every aspect.


Leave a Reply

Your email address will not be published. Required fields are marked *

*

This site uses Akismet to reduce spam. Learn how your comment data is processed.