How to use Environment Variables in Kotlin + Spring Boot

How to use Environment Variables in Kotlin + Spring Boot

Overview

  • With the advent of the serverless container era, managing the state of applications has become crucial. Constants that were loosely hard-coded in the past must now be appropriately received and injected through environment variables for safe and consistent container management. This article summarizes the confusing environment variable application priorities in Spring Boot and the methods of managing operating system environment variables.

Spring Boot Environment Variable Priority

  • The application priority of environment variables passed when launching a Spring Boot application is as follows. Higher priority environment variables will be considered, and identical variables at lower ranks will be ignored.
1. JVM options: "-D--spring.profiles.active=local"

2. Operating system environment variables: "SPRING_PROFILES_ACTIVE=local"

3. application-{profile}.yml
----------------------------
spring:
  profiles:
    active: local

4. application.yml
------------------
spring:
  profiles:
    active: local
  • Storing the application state in the source code, as in 3 and 4, is not a good approach from a security standpoint. The use of operating system environment variables, as in method 2, is the most recommended way to pass state to containers. (Details are explained below.)

Method 1: Environment::getProperty()

  • In Spring Boot, you can obtain and verify the applied environment variables in all Spring Beans as follows.
@Component
class FooComponent(
    val environment: Environment
) {
    val springProfilesActive: String = environment.getProperty("SPRING_PROFILES_ACTIVE") ?: "defaultValue"
}

Method 2: @Value

  • Similarly, you can obtain and verify the applied environment variables in all beans of Spring Boot using @Value as follows.
@Component
class FooComponent(
    @Value("\${spring.profiles.active}") val springProfilesActive: String
) {
    ...
}

Method 3: Operating System Environment Variables

  • Managing operating system environment variables is the most recommended method in real-world operational environments. Without writing any application.yml files in the source code, managing environment variable files in a securely isolated repository and injecting them through the CI/CD process is the safest way to manage them.
$ nano foo-local.env
SPRING_APPLICATION_NAME=foo
SPRING_PROFILES_ACTIVE=local
  • The created environment variable file can be applied in a local development environment as follows:
$ nano run
#!/bin/bash
set -a; source foo-local.env; set +a
./gradlew bootRun

$ chmod +x run
  • In the IntelliJ IDEA development environment, it's possible to apply this using the EnvFile plugin. After installing the plugin, check Enable EnvFile in the Edit Run Configuration menu, and then add the linked env file.

  • The injected environment variables can be acquired at the code level as follows. It's very convenient as it can be accessed globally across the code, not just within Spring Beans.

class Env {

    companion object {

        val SPRING_APPLICATION_NAME = System.getenv("SPRING_APPLICATION_NAME") ?: "foo"
        val SPRING_PROFILES_ACTIVE = System.getenv("SPRING_PROFILES_ACTIVE") ?: "local"
    }
}