Setelah enam bab Fase 0 membekali kita dengan fundamental bahasa Kotlin — null safety, OOP, functional programming, collections, coroutines, dan error handling — sekarang saatnya pindah dari test terisolasi ke aplikasi backend sungguhan. Mulai bab ini kita membangun Order Service, service pertama dari tiga service yang akan kita kembangkan sepanjang seri ini, dengan Spring Boot.
Kenapa Spring Boot?
Kalau kamu datang dari Laravel atau Go/Fiber, bayangkan Spring Boot sebagai gabungan antara "framework besar dengan konvensi kuat" ala Laravel dan "performa JVM yang matang untuk beban production tinggi". Spring (frameworknya) sudah jadi standar de-facto di dunia enterprise Java selama hampir dua dekade — dependency injection, transaction management, integrasi database, security, semuanya sudah teruji di skala besar. Spring Boot menambahkan lapisan "auto-configuration": kamu tidak perlu menulis konfigurasi XML atau Java Config yang panjang untuk hal-hal umum seperti web server tertanam, koneksi database, atau serialisasi JSON — Spring Boot menebak kebutuhanmu dari dependency yang kamu tambahkan, lalu mengonfigurasi semuanya otomatis.
Yang membuat kombinasi ini relevan untuk seri kita: Spring punya dukungan Kotlin kelas satu, bukan sekadar "bisa dipakai karena sama-sama jalan di JVM". Ada modul khusus (spring-fu, ekstensi Kotlin di Spring Framework), DSL routing khusus Kotlin, dukungan coroutines langsung di controller, dan — yang paling langsung kita rasakan mulai bab ini — plugin Gradle khusus yang menambal beberapa gesekan antara desain bahasa Kotlin dan cara kerja Spring di baliknya. Ini alasan Kotlin + Spring Boot jadi kombinasi umum untuk microservice production di banyak perusahaan, bukan sekadar eksperimen.
Asal Project Ini: Spring Initializr
Project order-service yang akan kita bedah sepanjang Fase 1 ini di-scaffold lewat start.spring.io (Spring Initializr) dengan pilihan Kotlin sebagai bahasa dan Gradle - Kotlin DSL sebagai build tool. Spring Initializr men-generate struktur project standar plus build.gradle.kts yang sudah terisi dependency starter sesuai pilihan kita — kita tidak menulis struktur ini dari nol, tapi penting untuk paham apa yang di-generate dan kenapa.
Membedah build.gradle.kts
Bagian paling atas file ini mendeklarasikan plugin yang dipakai project:
plugins {
kotlin("jvm") version "2.3.21"
kotlin("plugin.spring") version "2.3.21"
id("org.springframework.boot") version "4.1.1"
id("io.spring.dependency-management") version "1.1.7"
kotlin("plugin.jpa") version "2.3.21"
}
Lima plugin ini masing-masing punya peran spesifik:
kotlin("jvm")— plugin dasar yang mengaktifkan compiler Kotlin untuk target JVM. Tanpa ini, Gradle tidak tahu cara meng-compile file.kt.kotlin("plugin.spring")— ini bagian yang paling penting dipahami di awal. Kelas di Kotlin itufinalsecara default (tidak bisa di-subclass), berbeda dari Java yangopensecara default. Masalahnya, banyak fitur Spring — proxy untuk@Transactional,@Async, bean@Configuration, dan sejenisnya — bekerja dengan cara membuat subclass proxy di belakang layar (biasanya lewat CGLIB) dari kelas yang kita tulis. Kalau kelasnyafinal, Spring tidak bisa membuat proxy itu, dan fitur-fitur tersebut diam-diam tidak berfungsi. Pluginplugin.springmenyelesaikan ini otomatis: dia membuka (open) kelas mana pun yang dianotasi dengan anotasi Spring tertentu (@Component,@Service,@RestController,@Configuration, dst), tanpa kita perlu menulisopen classmanual di setiap kelas.org.springframework.boot— plugin resmi Spring Boot untuk Gradle, menyediakan task sepertibootRundanbootJar, plus mengelola versi dependency yang kompatibel satu sama lain.io.spring.dependency-management— mengatur versi dependency secara terpusat berdasarkan BOM (Bill of Materials) Spring Boot, supaya kita tidak perlu menuliskan nomor versi di setiap barisimplementation(...).kotlin("plugin.jpa")— masalah serupa denganplugin.spring, tapi untuk JPA/Hibernate. Entity JPA butuh constructor tanpa argumen (no-arg constructor) yang dipakai Hibernate lewat reflection untuk membuat instance kosong sebelum diisi data dari database — sesuatu yang tidak otomatis ada didata classKotlin yang constructor-nya sudah terisi parameter. Plugin ini men-generate no-arg constructor itu secara otomatis untuk kelas yang dianotasi@Entity,@MappedSuperclass, atau@Embeddable(persis anotasi yang didaftarkan di blokallOpendi bagian bawah file), sekaligus membuka kelasnya sepertiplugin.spring. Kita akan pakai ini langsung begitu masuk Fase 2.
Java Toolchain dan Dependency
java {
toolchain {
languageVersion = JavaLanguageVersion.of(21)
}
}
Blok ini memberi tahu Gradle: compile dan jalankan project ini pakai JDK 21 (LTS), berapa pun versi JDK yang terinstal di komputer developer secara default. Gradle akan otomatis mencari atau mengunduh toolchain yang sesuai. Ini penting untuk konsistensi tim — semua orang yang kerja di project ini pasti compile dengan versi Java yang sama, tidak tergantung JAVA_HOME masing-masing mesin.
Bagian dependencies { ... } berisi daftar library yang dipakai. Untuk sekarang, cukup tahu gambaran besarnya dulu — detail masing-masing akan kita bahas saat topiknya relevan di bab-bab berikutnya:
spring-boot-starter-webmvc,spring-boot-starter-validation— web layer dan validasi (Fase 1, bab ini seterusnya).spring-boot-starter-data-jpa,spring-boot-starter-flyway,flyway-database-postgresql, driverpostgresql— database dan migration (Fase 2).jackson-module-kotlin,kotlin-reflect— dukungan Jackson (serialisasi JSON) dan reflection untuk kelas Kotlin.kotlinx-coroutines-core— coroutines, sudah kita kenal konsepnya di Fase 0.- Berderet dependency
testImplementation(MockK, Testcontainers, dst) — akan jadi bintang utama di Fase 3.
OrderServiceApplication.kt — Titik Masuk Aplikasi
package com.indokoding.orderservice
import org.springframework.boot.autoconfigure.SpringBootApplication
import org.springframework.boot.context.properties.ConfigurationPropertiesScan
import org.springframework.boot.runApplication
@SpringBootApplication
@ConfigurationPropertiesScan
class OrderServiceApplication
fun main(args: Array<String>) {
runApplication<OrderServiceApplication>(*args)
}
Beberapa hal menarik di sini. Pertama, class OrderServiceApplication tidak punya body ({ }) sama sekali — di Kotlin, kelas tanpa constructor parameter dan tanpa isi memang boleh ditulis sesingkat itu. Kelas ini murni jadi penanda untuk Spring: anotasi @SpringBootApplication di atasnya sebenarnya gabungan dari tiga anotasi (@Configuration, @EnableAutoConfiguration, @ComponentScan) yang memberi tahu Spring "mulai auto-configuration dari sini, dan scan semua kelas di package ini ke bawah untuk dijadikan bean". @ConfigurationPropertiesScan akan kita bahas detail di bab berikutnya — singkatnya, dia memperluas scan itu untuk kelas konfigurasi properties.
Kedua, perhatikan fun main di luar kelas — konsisten dengan gaya Kotlin, fungsi top-level (tidak harus dibungkus kelas seperti public static void main di Java). Baris runApplication<OrderServiceApplication>(*args) adalah versi Kotlin idiomatis dari SpringApplication.run(OrderServiceApplication::class.java, args) di Java — runApplication<T>() adalah inline function dengan reified generic, jadi tipe OrderServiceApplication bisa langsung dipakai sebagai argumen generic tanpa perlu ::class.java secara eksplisit. Operator *args di depan args adalah spread operator: args sudah berupa array, dan spread operator "membongkarnya" jadi daftar argumen individual yang diteruskan ke parameter vararg fungsi runApplication.
Menjalankan Project
Untuk development sehari-hari, dua tools yang direkomendasikan: IntelliJ IDEA (Community Edition sudah cukup) karena dukungan Kotlin-nya paling matang di antara semua IDE, dan menjalankan aplikasi lewat:
./gradlew bootRun
./gradlew adalah Gradle Wrapper — script yang memastikan semua orang di tim pakai versi Gradle yang sama persis, tanpa perlu install Gradle manual. Task bootRun men-compile project lalu langsung menjalankannya, cocok untuk iterasi cepat saat development.
Struktur dan konfigurasi dasar sudah kita pahami. Bab berikutnya kita masuk ke jantung Spring: bagaimana Spring mengelola object (dependency injection) dan bagaimana kita membaca konfigurasi dari application.yml lewat AppInfoProperties dan PingController — dua kelas paling sederhana di project ini, tapi merangkum pola yang akan berulang di seluruh service.
Bagian dari Series: Kotlin Backend Microservice - Belajar Fundamental sampai Microservice Nyata
Belajar Kotlin + Spring Boot dari fundamental bahasa (null safety, OOP, coroutines) sampai membangun sistem microservice sungguhan - REST API, Postgre...
Lihat Series Lengkap