Sebelum Gradle menjadi dominan, Maven adalah build tool standar untuk ekosistem JVM. Banyak organisasi besar masih memakai Maven untuk proyek mereka, dan beberapa library Kotlin publik tetap mempertahankan pom.xml untuk kompatibilitas. Maven mengikuti filosofi convention over configuration dengan struktur tetap dan lifecycle yang ditentukan secara declarative. Pada chapter ini kita akan membahas struktur pom.xml, cara mengintegrasikan kotlin-maven-plugin, serta lifecycle phases yang paling sering dipakai.

Struktur pom.xml #

pom.xml adalah file Project Object Model Maven. File ini berisi koordinat proyek, dependensi, dan plugin. Struktur minimal untuk proyek Kotlin:

xml pom.xml — Kotlin minimal
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.example</groupId>
    <artifactId>halo-kotlin</artifactId>
    <version>1.0.0</version>
    <packaging>jar</packaging>

    <properties>
        <kotlin.version>2.0.21</kotlin.version>
        <maven.compiler.release>21</maven.compiler.release>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.jetbrains.kotlin</groupId>
            <artifactId>kotlin-stdlib</artifactId>
            <version>${kotlin.version}</version>
        </dependency>
    </dependencies>

    <build>
        <sourceDirectory>${project.basedir}/src/main/kotlin</sourceDirectory>
        <testSourceDirectory>${project.basedir}/src/test/kotlin</testSourceDirectory>

        <plugins>
            <plugin>
                <groupId>org.jetbrains.kotlin</groupId>
                <artifactId>kotlin-maven-plugin</artifactId>
                <version>${kotlin.version}</version>
                <executions>
                    <execution>
                        <id>compile</id>
                        <goals><goal>compile</goal></goals>
                    </execution>
                    <execution>
                        <id>test-compile</id>
                        <goals><goal>test-compile</goal></goals>
                    </execution>
                </executions>
                <configuration>
                    <jvmTarget>21</jvmTarget>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

Lifecycle Phases #

Maven memiliki tiga lifecycle bawaan: default, clean, dan site. Lifecycle default terdiri dari phase-phase berurutan:

PhaseYang terjadi
validateValidasi proyek dan properti
compileKompilasi src/main
testJalankan unit test (src/test)
packageKemas ke JAR/WAR
verifyIntegrasi test + cek kualitas
installPasang artefak ke ~/.m2/repository lokal
deployUnggah ke repository remote

Saat kita memanggil mvn package, Maven akan menjalankan semua phase sebelumnya (validate, compile, test) secara berurutan. Inilah perbedaan utama dengan Gradle, yang hanya menjalankan task yang dibutuhkan beserta dependensinya.

kotlin-maven-plugin #

Plugin kotlin-maven-plugin adalah jembatan antara Maven dan kotlinc. Plugin ini mendaftarkan dua execution standar:

  • compile — kompilasi src/main/kotlin ke target/classes
  • test-compile — kompilasi src/test/kotlin ke target/test-classes

Eksekusi dipanggil saat Maven memasuki phase compile dan test-compile. Konfigurasi tambahan (jvmTarget, args, compilerPlugins) dapat ditambahkan di <configuration> block.

Demonstrasi Maven #

Kode berikut mencantumkan struktur dasar Maven dan perintah-perintah yang paling sering dipakai.

kotlin
fun main() {
    println("=== Maven Fundamentals ===")
    println()
    println("File konfigurasi: pom.xml (Project Object Model)")
    println()
    println("Plugin Kotlin untuk Maven:")
    println("  <plugin>")
    println("    <groupId>org.jetbrains.kotlin</groupId>")
    println("    <artifactId>kotlin-maven-plugin</artifactId>")
    println("    <version>2.0.21</version>")
    println("    <executions> compile / test-compile </executions>")
    println("  </plugin>")
    println()
    println("Lifecycle phases utama:")
    println("  validate      : validasi proyek")
    println("  compile       : kompilasi src/main")
    println("  test          : jalankan unit test")
    println("  package       : kemas ke JAR")
    println("  verify        : integrasi test + cek kualitas")
    println("  install       : pasang ke ~/.m2/repository lokal")
    println("  deploy        : unggah ke repository remote")
    println()
    println("Perintah Maven:")
    println("  mvn compile              : kompilasi")
    println("  mvn test                 : jalankan test")
    println("  mvn package              : kemas JAR")
    println("  mvn install             : pasang ke .m2 lokal")
    println("  mvn clean install        : bersihkan lalu install")
    println("  mvn dependency:tree       : pohon dependensi")
}

Output yang Dihasilkan:

text
=== Maven Fundamentals ===

File konfigurasi: pom.xml (Project Object Model)

Plugin Kotlin untuk Maven:
  <plugin>
    <groupId>org.jetbrains.kotlin</groupId>
    <artifactId>kotlin-maven-plugin</artifactId>
    <version>2.0.21</version>
    <executions> compile / test-compile </executions>
  </plugin>

Lifecycle phases utama:
  validate      : validasi proyek
  compile       : kompilasi src/main
  test          : jalankan unit test
  package       : kemas ke JAR
  verify        : integrasi test + cek kualitas
  install       : pasang ke ~/.m2/repository lokal
  deploy        : unggah ke repository remote

Perintah Maven:
  mvn compile              : kompilasi
  mvn test                 : jalankan test
  mvn package              : kemas JAR
  mvn install             : pasang ke .m2 lokal
  mvn clean install        : bersihkan lalu install
  mvn dependency:tree       : pohon dependensi

Mari kita telaah kode di atas:

  1. Struktur plugin: setiap plugin di Maven diidentifikasi via groupId:artifactId:version. Untuk kotlin-maven-plugin, koordinatnya adalah org.jetbrains.kotlin:kotlin-maven-plugin:2.0.21.
  2. Lifecycle phases: Maven menjalankan phase secara berurutan. mvn package menjalankan validate, compile, test, lalu package. Pembaca dapat memverifikasi dengan menambah flag -X (debug) untuk melihat urutan eksekusi.
  3. mvn clean install: pola yang sering dipakai di CI. clean menghapus target/, install membangun dari nol dan menyimpan artefak ke repository lokal untuk konsumsi modul lain.

Koordinat Maven #

Setiap artefak Maven diidentifikasi oleh tiga field:

  • groupId: organisasi (com.example, org.jetbrains.kotlin)
  • artifactId: nama artefak (halo-kotlin, kotlin-stdlib)
  • version: versi (1.0.0, 2.0.21)

Tiga field ini membentuk koordinat unik: groupId:artifactId:version. Format ini sama dengan koordinat Gradle group:name:version — hanya penamaan field yang berbeda.

Repository #

Maven mengunduh dependensi dari repository. Repository default adalah Maven Central (https://repo1.maven.org/maven2/). Konfigurasi tambahan:

xml pom.xml — repositories
<repositories>
    <repository>
        <id>central</id>
        <url>https://repo1.maven.org/maven2</url>
    </repository>
    <repository>
        <id>jetbrains</id>
        <url>https://maven.pkg.jetbrains.space/public/p/kotlinx-html/maven</url>
    </repository>
</repositories>

Maven vs Gradle #

AspekMavenGradle
Bahasa build scriptXML (declarative)Kotlin / Groovy (programmatic)
Build inkrementalTerbatas (per file)Full (per task, up-to-date checking)
CachingRepository lokal (.m2)Repository lokal + build cache + configuration cache
Plugin Kotlinkotlin-maven-pluginkotlin-gradle-plugin
Multi-modul<modules> di parent POMinclude() di settings.gradle.kts

Untuk proyek Kotlin baru, preferensi default adalah Gradle. Maven dipakai bila organisasi sudah punya ekosistem Maven, atau bila library akan dikonsumsi oleh konsumer Maven yang mengharapkan POM tertentu.

Referensi Lanjutan #

Penutup #

Maven tetap menjadi pilihan valid untuk proyek Kotlin, terutama bila organisasi sudah memegang ekosistem Maven. Pemahaman pom.xml, lifecycle phases, dan kotlin-maven-plugin menjadi modal untuk berkontribusi di proyek Maven. Pada chapter berikutnya kita akan membahas deklarasi dependensi Maven secara lebih detail: scope, repository, dan dependency:tree.