https://kotlinlang.org logo
#http4k
Title
# http4k
r

Razi Kheir

01/20/2020, 5:41 AM
@dave I’m running into a similar issue that was resolved in 3.193.1, where specifying an optional in an a environment lens throws exception in runtime. Only this time it’s happening in a composite environment object. Version Used: 3.193.1
Copy code
Caused by: org.http4k.lens.LensFailure: location 'NON_OPTIONAL_VAR' must be object
	at org.http4k.lens.Lens.invoke(lens.kt:17)
	at config.CompositeEnvironmentHandler$$special$$inlined$composite$1.invoke(lensSpec.kt:262)
	at config.CompositeEnvironmentHandler$$special$$inlined$composite$1.invoke(lensSpec.kt)
	at org.http4k.lens.LensGet$invoke$1.invoke(lensSpec.kt:15)
	at org.http4k.lens.LensGet$invoke$1.invoke(lensSpec.kt:14)
	at org.http4k.lens.LensSpec$required$1.invoke(lensSpec.kt:99)
	at org.http4k.lens.Lens.invoke(lens.kt:13)
Code Snippet:
Copy code
class CompositeConfig(
    val nonOptionalVar: String,
    val optionalVar: String?
)

internal object CompositeEnvironmentHandler {

    val config: CompositeConfig

    private val spec = BiDiLensSpec("location", ParamMeta.ObjectParam,
        LensGet { location: String, env: Environment ->
            listOf(env[location]!!)
        },
        LensSet { _: String, _: List<String>, env: Environment ->
            env
        })
    private val lens = spec.composite {
        CompositeConfig(
            nonOptionalVar = required("NON_OPTIONAL_VAR")(it),
            optionalVar = optional("OPTIONAL_VAR")(it)
        )
    }

    init {

        // Fallback default config.
        val defaultEnvironment = Environment.defaults(
            EnvironmentKey.k8s.SERVICE_PORT of 8000
        )

        // Environment overrides by priority JVM > System > File > Default.
        val environment = Environment.JVM_PROPERTIES overrides
                Environment.ENV overrides
                fileSystemEnvironment() overrides
                defaultEnvironment
        config = lens(environment)
    }

    /**
     * Fetches configuration file from file system.
     * Will search for file under [environmentVariable] in JVMProps then in ENV.
     * If not found will search for it in file system with [fallbackName].
     */
    private fun fileSystemEnvironment(
        environmentVariable: String = "APP_CONFIG",
        fallbackName: String = "testConfig.yml"
    ): Environment {

        // Fetch file from env environmentVariable JVM > ENV > Default
        return (Environment.JVM_PROPERTIES[environmentVariable]
            ?: Environment.ENV[environmentVariable])?.let {
            Environment.from(File(it))
        } ?: Environment.fromResource(fallbackName)
    }
}
4 Views