Created
August 2, 2022 15:18
-
-
Save toefel18/caf5f219f5850117a975b3e43eb4c7e1 to your computer and use it in GitHub Desktop.
Hoplite configuration
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// configuration properties | |
implementation("com.sksamuel.hoplite:hoplite-core:2.4.0") | |
implementation("com.sksamuel.hoplite:hoplite-yaml:2.4.0") | |
implementation("com.sksamuel.hoplite:hoplite-datetime:2.4.0") |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
object ConfigurationLoader { | |
val log: Logger = LoggerFactory.getLogger(ConfigurationLoader::class.java) | |
/** Applications should rely on overriding env vars in the default profiles. This mechanism can be simplified */ | |
private val profileKeys = listOf("profileOverride") // used to be "profile", "profiles", "spring.profiles.active" | |
private fun lazyCheckSystemProperty(name: String): Lazy<String?> = checkProfileVia("system property", name) { System.getProperty(name) } | |
private fun lazyCheckEnvVar(name: String): Lazy<String?> = checkProfileVia("environment var", name) { System.getenv(name) } | |
private fun checkProfileVia(source: String, name: String, supplier: () -> String?) = lazy { | |
val profile = supplier() | |
if (profile == null) { | |
log.info("did not find application config profile via $source '$name'") | |
} else { | |
log.info("found application config profile '$profile' via $source '$name'") | |
} | |
profile | |
} | |
/** | |
* Contains the configured profile from the environment. | |
* The following locations will be checked in order: | |
* ``` | |
* jvm arg: -DprofileOverride=acc,local | |
* env var: PROFILEOVERRIDE=acc,local | |
* ``` | |
* First config location wins. | |
* - If no profileOverride is found, only the default 'application.yaml' will be loaded | |
* - If there are multiple values present, such as 'acc,local' then both are loaded but local will overwrite the values form acc. | |
*/ | |
val configuredProfiles: List<String> = profileKeys | |
.asSequence() | |
.flatMap { name -> | |
listOf( | |
lazyCheckSystemProperty(name), | |
lazyCheckEnvVar(name.uppercase().replace('.', '_')) | |
) | |
} | |
.firstOrNull { it.value != null } | |
?.value?.split(",") ?: listOf() | |
fun load(): ApplicationConfig = readConfigFilesWithConfiguredProfiles() | |
/** | |
* Reads the config files using the configured profiles via system properties or environment variables | |
*/ | |
inline fun <reified T> readConfigFilesWithConfiguredProfiles(): T = readConfigWithProfiles(*configuredProfiles.toTypedArray()) | |
/** | |
* Reads application.yaml + the other given profiles and maps the configuration to the object it is assigned to. | |
* The last profile has highest priority and overwrites values in earlier profiles. | |
* | |
* `val obj : MyConfigType = readConfigWithProfiles("acc")` | |
* | |
*/ | |
inline fun <reified T> readConfigWithProfiles(vararg profiles: String): T { | |
// highest prio config files need to be fed first to the config loader | |
val resourceFiles = profiles.reversed().map { "/application-$it.yaml" } + "/application.yaml" | |
log.info("reading config files $resourceFiles") | |
return ConfigLoader.builder() | |
.addDefaults() | |
.build() | |
.loadConfigOrThrow(resourceFiles) | |
} | |
} | |
// dto's read from yaml | |
data class ApplicationConfig( | |
val server: ServerConfig, | |
val profile: String, | |
val applicationName: String | |
) | |
// dto's read from yaml. | |
data class ServerConfig(val port: Int) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment