Episode ini membahas pengelolaan konfigurasi aplikasi dengan Groovy menggunakan ConfigSlurper, penanganan secrets yang aman, dan external config sources. Kalian juga akan belajar perilaku per environment dan runtime overrides untuk aplikasi yang berjalan di banyak lingkungan.

Aplikasi production membutuhkan konfigurasi yang bisa berubah tanpa mengubah kode. Episode 14 membahas cara mengelola konfigurasi dengan Groovy secara elegan, termasuk menyimpan secrets dengan aman dan membuat aplikasi berperilaku berbeda di tiap environment.
Kalian akan belajar ConfigSlurper untuk parsing konfigurasi, secure handling of secrets, external config sources, serta environment-specific behavior dan runtime overrides.
Groovy menyediakan ConfigSlurper — parser khusus untuk file konfigurasi berformat Groovy. Struktur konfigurasi ditulis sebagai map bersarang:
// application.groovy
app {
name = "belajar-groovy"
port = 8080
retry = 3
}
database {
host = "db.internal"
timeout = 30
}Baca dan akses konfigurasi tersebut:
def config = new ConfigSlurper().parse(new File("application.groovy").toURL())
println config.app.name
println config.database.hostnew ConfigSlurper().parse(...) mengurai file konfigurasi menjadi objek yang bisa diakses dengan dot-notation. config.app.name membaca nilai bersarang tanpa parsing manual — pola yang jauh lebih nyaman daripada file properties.
ConfigSlurper memiliki dukungan bawaan untuk environment. Nilai bisa didefinisikan per environment dan dioverride sesuai konteks:
environments {
dev {
app {
name = "belajar-groovy-dev"
debug = true
}
}
production {
app {
name = "belajar-groovy"
debug = false
}
}
}Muat dengan menentukan environment:
def env = System.getProperty("env") ?: "dev"
def config = new ConfigSlurper(env).parse(new File("application.groovy").toURL())
println config.app.name
println "Debug: ${config.app.debug}"new ConfigSlurper(env).parse(...) memuat blok sesuai environment. System.getProperty("env") ?: "dev" memilih environment dari system property dengan fallback ke dev — pola runtime overrides yang fleksibel.
Konfigurasi bisa dioverride saat runtime tanpa mengubah file. Nilai environment atau system property diutamakan:
def env = System.getenv("ENV") ?: "dev"
def config = new ConfigSlurper(env).parse(new File("application.groovy").toURL())
config.app.port = System.getProperty("app.port")?.toInteger() ?: config.app.port
println "Port: ${config.app.port}"config.app.port = System.getProperty("app.port") ?: config.app.port menimpa nilai dari system property jika tersedia. ?.toInteger() ?: config.app.port menggabungkan safe navigation dan Elvis untuk fallback yang bersih.
Aturan pertama keamanan: secrets tidak pernah ditulis di kode atau file konfigurasi yang masuk version control. Berikut praktik yang dianjurkan:
Pola paling sederhana: secrets berasal dari environment variables:
def apiKey = System.getenv("API_KEY")
if (!apiKey) {
throw new IllegalStateException("API_KEY belum diset")
}
println "API key tersedia (disembunyikan)"System.getenv("API_KEY") membaca secret dari environment, dan if (!apiKey) throw new IllegalStateException(...) menghentikan aplikasi saat secret hilang. throw new IllegalStateException("API_KEY belum diset") mencegah aplikasi berjalan dengan konfigurasi tidak lengkap.
Untuk secret yang lebih kompleks, gunakan secret manager seperti HashiCorp Vault atau OpenBao. Groovy bisa membaca secret dari API mereka:
def uri = "https://vault.internal/v1/kv/data/app"
def token = System.getenv("VAULT_TOKEN")
def conn = new URL(uri).openConnection()
conn.setRequestProperty("X-Vault-Token", token)
def response = conn.inputStream.text
println "Response diterima (ukuran ${response.length()} byte)"new URL(uri).openConnection() membuka koneksi HTTP ke Vault, dan conn.setRequestProperty("X-Vault-Token", token) mengirim token autentikasi. conn.inputStream.text membaca respons. Secret manager akan kita bahas lebih dalam di episode 20.
Mari gabungkan pola yang sudah dipelajari:
def env = System.getenv("ENV") ?: "dev"
def config = new ConfigSlurper(env).parse(new File("application.groovy").toURL())
config.database.password = System.getenv("DB_PASSWORD") ?: config.database.password
config.app.port = System.getProperty("app.port")?.toInteger() ?: config.app.port
println "App: ${config.app.name} di port ${config.app.port}"
println "DB: ${config.database.host}"config.database.password = System.getenv("DB_PASSWORD") ?: config.database.password menggabungkan secrets dari environment dengan nilai default dari file. config.app.port = System.getProperty("app.port")?.toInteger() ?: config.app.port menerapkan override runtime. Hasilnya: satu file konfigurasi yang melayani banyak environment dengan aman.
Episode 14 membekali kalian pengelolaan konfigurasi modern: ConfigSlurper untuk parsing, environment blocks untuk perbedaan lingkungan, runtime overrides, serta pola penyimpanan secrets yang aman.
Inti yang harus dibawa pulang:
environments {} memungkinkan konfigurasi berbeda per environment.Di episode 15 selanjutnya kita akan membahas metaprogramming dan AST transformations — dynamic methods, propertyMissing, methodMissing, perbandingan runtime metaprogramming dengan compile-time AST transformations, serta contoh dekorator dan dynamic proxy pattern.