Gradle 5 mit Kotlin DSL in Multi-Project Build
Um ein Java oder Kotlin Projekt aufzusetzen muss man sich für ein Build-Management-Tool entscheiden. Für einen Test den ich durchführen möchte musste ich das gestern tun und habe mich diesmal für Kotlin und Gradle entschieden. Außerdem möchte ich Spring und Spring Dependency Management einsetzen und das ganze soll als Multi-Project-Build funktionieren. Dabei bin ich auf die relativ neue Möglichkeit gestoßen Gradle mit der Kotlin DSL zu konfigurieren.
Ich habe mir folgende Fragen gestellt: Wie konfiguriere ich möglichst viel im Parent-Projekt durch Vererbung? Und wie kann ich Dependency Management (Versionen), so wie in Maven, durch Spring durchführen lassen? Das Ergebnis möchte ich hier vorstellen.
Grundgerüst
Zuerst legt man sich ein neues Projekt mit folgendem Befehl an:
gradle init --type=kotlin-application --dsl kotlin
Dadurch wird ein Grundgerüst des Projekts erstellt und in der Kotlin DSL die benötigten Einstellungen in der build.gradle.kts durchgeführt um in Kotlin entwickeln zu können.
Multi-Module
Um daraus ein Multi-Project Build zu machen, sollten die Sub-Projects in form von leeren Ordnern angelegt werden. In diesem Fall „message-dashboard“ und „message-factory“.
mkdir message-dashboard mkdir message-factory
Anschließend kopieren wir den src-Ordner aus dem root-Project in die Sub-Projects um die für die Entwicklung nötige Ordnerstruktur zu erhalten. Anschließend löschen wir den src-Ordner im root-Project.
cp -r ./src ./message-dashboard/src cp -r ./src ./message-factory/src rm -rf src
In jedem sub-Project muss nun eine build.gradle.kts angelegt werden.
touch message-dashboard/build.gradle.kts touch message-factory/build.gradle.kts
In der settings.gradle fügt man nun die Sub-Projects hinzu.
rootProject.name = "gradle-kotlin-spring" include("message-factory") include("message-dashboard")
Das Projekt sollte nun beim ausführen von Gradle keine Fehler mehr werfen, den code in den Sub-Projects allerdings noch nicht verarbeiten. Dafür muss die build.gradle.kts folgendermaßen verändert werden:
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile plugins { // Apply the Kotlin JVM plugin to add support for Kotlin on the JVM. kotlin("jvm") version "1.3.11" apply false } allprojects { group = "de.mrclrchtr.education" version = "1.0-SNAPSHOT" repositories { jcenter() } } subprojects { tasks.withType<KotlinCompile>().configureEach { println("Configuring $name in project ${project.name}...") kotlinOptions { jvmTarget = "1.8" freeCompilerArgs = listOf("-Xjsr305=strict") } } }
In plugins wurde die neue Schreibweise des Kotlin Plugins hinzugefügt. In allpropjects wird die Group und die Version für alle Projekte festgelegt. In subprojects wird der KotlinCompiler konfiguriert.
In den build.gradle.kts der Sub-Projects muss folgendes hinzugefügt werden:
plugins { kotlin("jvm") } dependencies { compile(kotlin("stdlib-jdk8")) // Use the Kotlin test library. testImplementation("org.jetbrains.kotlin:kotlin-test") // Use the Kotlin JUnit integration. testImplementation("org.jetbrains.kotlin:kotlin-test-junit") }
Hier wird das Kotlin-Plugin aktiviert und die individuellen Dependencies hinzugefügt. Nun ist das Projekt ein Multi-Project-Build.
Spring & Spring Dependency Management
Um Spring Dependency Management zu aktivieren wird wieder die Gradle-Config des Root-Projects angepasst.
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile import io.spring.gradle.dependencymanagement.dsl.DependencyManagementExtension plugins { base kotlin("jvm") version "1.3.11" apply false id("org.jetbrains.kotlin.plugin.spring") version "1.3.11" apply false id("org.springframework.boot") version "2.1.1.RELEASE" apply false } allprojects { group = "de.mrclrchtr.education" version = "1.0-SNAPSHOT" repositories { jcenter() } } subprojects { apply(plugin = "org.springframework.boot") println("Enabling Kotlin Spring plugin in project ${project.name}...") apply(plugin = "org.jetbrains.kotlin.plugin.spring") println("Enabling Spring Boot Dependency Management in project ${project.name}...") apply(plugin = "io.spring.dependency-management") the<DependencyManagementExtension>().apply { imports { mavenBom(org.springframework.boot.gradle.plugin.SpringBootPlugin.BOM_COORDINATES) } } tasks.withType<KotlinCompile>().configureEach { println("Configuring $name in project ${project.name}...") kotlinOptions { jvmTarget = "1.8" freeCompilerArgs = listOf("-Xjsr305=strict") } } tasks.withType<Test> { useJUnitPlatform() } } dependencies { // Make the root project archives configuration depend on every subproject subprojects.forEach { archives(it) } }
Es werden die Plugins org.jetbrains.kotlin.plugin.spring und org.springframework.boot hinzugefügt und anschließend in subprojects aktiviert. Zusätzlich wird das Dependency Management mit der DependencyManagementExtension durchgeführt. In den Sub-Projects können nun einfach Spring Dependencies ohne Angabe von Versionen wie in Folgendem Beispiel genutzt werden.
plugins { kotlin("jvm") } dependencies { compile(kotlin("stdlib-jdk8")) compile("org.springframework.boot:spring-boot-starter-web") compile("org.springframework.boot:spring-boot-starter-actuator") // Use the Kotlin test library. testImplementation("org.jetbrains.kotlin:kotlin-test") // Use the Kotlin JUnit integration. testImplementation("org.jetbrains.kotlin:kotlin-test-junit") }
Das Ergebnis mit Beispielanwendung und weiteren Erweiterungen ist auf GitHub zu finden.