# 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.
    

```bash
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.
    

```kotlin
@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.
    

```kotlin
@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.
    

```bash
$ 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:
    

```bash
$ 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.
    

```kotlin
class Env {
 
    companion object {
 
        val SPRING_APPLICATION_NAME = System.getenv("SPRING_APPLICATION_NAME") ?: "foo"
        val SPRING_PROFILES_ACTIVE = System.getenv("SPRING_PROFILES_ACTIVE") ?: "local"
    }
}
```
