spring-boot + gradle-kotlin-dsl

Spring Boot Gradle Kotlin DSL starter

Spring Boot

plugins definition

build.gradle.kts

plugins {
  id("org.jetbrains.kotlin.jvm").version("1.3.21")
  id("org.jetbrains.kotlin.plugin.spring").version("1.3.21")
  id("org.springframework.boot").version("2.2.0.BUILD-SNAPSHOT")
}

apply(plugin = "war")
apply(plugin = "io.spring.dependency-management")

repositories {
  mavenCentral()
  maven(url = "https://repo.spring.io/snapshot")
  maven(url = "https://repo.spring.io/milestone")
}

settings.gradle.kts

pluginManagement {
  repositories {
    gradlePluginPortal()
    maven(url = "https://repo.spring.io/snapshot")
    maven(url = "https://repo.spring.io/milestone")
    gradlePluginPortal()
  }
  resolutionStrategy {
    eachPlugin {
      if (requested.id.id == "org.springframework.boot") {
        useModule("org.springframework.boot:spring-boot-gradle-plugin:${requested.version}")
      }
    }
  }
}

TIP

we need this because we wanna use spring 2.2.0-BUILD-SNAPSHOT version

dependencies

build.gradle.kts

dependencies {
  implementation("org.springframework.boot:spring-boot-starter-hateoas")
  implementation("org.springframework.boot:spring-boot-starter-webflux")
  implementation("org.springframework.boot:spring-boot-starter-actuator")
  implementation("org.springframework.boot:spring-boot-starter")
  annotationProcessor("org.projectlombok:lombok")
  testAnnotationProcessor("org.projectlombok:lombok")
  annotationProcessor("org.springframework.boot:spring-boot-configuration-processor")
  testAnnotationProcessor("org.springframework.boot:spring-boot-configuration-processor")
  runtimeOnly("org.springframework.boot:spring-boot-devtools")
  testImplementation("org.springframework.boot:spring-boot-starter-test")
  testImplementation("io.projectreactor:reactor-test")
}

executable artifact

build.gradle.kts

tasks.withType<org.springframework.boot.gradle.tasks.bundling.BootJar>().configureEach {
  launchScript()
}

kotlin

build.gradle.kts

tasks.withType<org.jetbrains.kotlin.gradle.tasks.KotlinCompile>().configureEach {
  kotlinOptions {
    freeCompilerArgs += "-Xjsr305=strict"
    jvmTarget = JavaVersion.VERSION_1_8.toString()
  }
}

dependencies {
  implementation("org.jetbrains.kotlin:kotlin-reflect")
  implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8")
  implementation("com.fasterxml.jackson.module:jackson-module-kotlin")
}

override parent versions

build.gradle.kts

val kotlinVersion = "1.3.21"
val junitJupiterVersion = "5.4.0"

extra["kotlin.version"] = kotlinVersion
extra["junit-jupiter.version"] = junitJupiterVersion

war

build.gradle.kts

plugins {
  id("war")
}

tasks.withType<BootWar>().configureEach {
  launchScript()
}

ServletInitializer.kt

class ServletInitializer : SpringBootServletInitializer() {
  override fun configure(application: SpringApplicationBuilder): SpringApplicationBuilder {
    return application.sources(SptingBootGradleKotlinDslExampleApplication::class.java)
  }
}

build and run executable WAR artifact

./gradlew build
bash ./build/libs/*.war

JUnit / Jupiter

build.gradle.kts

dependencies {
  testImplementation("junit:junit")
  testAnnotationProcessor("org.projectlombok:lombok")
  testImplementation(platform("org.junit:junit-bom:$junitJupiterVersion"))
  testImplementation("org.junit.jupiter:junit-jupiter-api")
  testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine")
  testRuntimeOnly("org.junit.vintage:junit-vintage-engine")
  testRuntime("org.junit.platform:junit-platform-launcher")
}

tasks.withType<Test> {
  useJUnitPlatform()
  testLogging {
    showExceptions = true
    showStandardStreams = true
    events(PASSED, SKIPPED, FAILED)
  }
}

java <-> kotlin

don't miss your src/*/kotlin/**.java and src/*/java/**.kt sources files location!

sourceSets {
  main {
    java.srcDir("src/main/kotlin")
  }
  test {
    java.srcDir("src/test/kotlin")
  }
}

Wrapper

build.gradle.kts

tasks.withType<Wrapper>().configureEach {
  gradleVersion = gradleVersion
  distributionType = Wrapper.DistributionType.BIN
}

re-generate gradle wrapper

./gradlew :wrapper

NodeJS

build.gradle.kts

plugins {
  id("com.moowork.node") version "1.2.0"
}

node {
  download = true
  version = "10.9.0"
  npmVersion = "6.9.0"
}

tasks.create("start")
tasks["start"].dependsOn("npm_start")
tasks["npm_start"].dependsOn("npm_i")
tasks["build"].dependsOn("npm_run_build")
tasks["npm_run_build"].dependsOn("npm_install")

run 'npm start' by using gradle node plugin

./gradlew start

build VuePress documentation

./gradlew npm_run_build

docker

docker-compose.yaml

version: "3.7"
services:
  app:
    image: openjdk:8u191-jdk-alpine3.9
    volumes: ["./build/libs:/tmp/app"]
    ports: ["8080:8080"]
    networks: [app-network]
    command: ash -c "java -jar /tmp/app/*.war"
    healthcheck:
      disable: true
networks:
  app-network:
    driver: bridge

build.gradle.kts

plugins {
  id("com.avast.gradle.docker-compose").version("0.8.14")//.apply(false)
}

val dockerPs: Task = tasks.create<Exec>("dockerPs") {
  dependsOn("assemble")
  shouldRunAfter("assemble")
  executable = "docker"
  args("ps", "-a", "-f", "name=${project.name}")
}

apply(plugin = "com.avast.gradle.docker-compose")

dockerCompose {
  isRequiredBy(dockerPs)
}

run and test

./gradlew composeUp
http :8080/actuator
./gradlew composeDown

create sources.zip


tasks {
  getByName("clean") {
    doLast {
      delete(project.buildDir)
    }
  }
}

tasks.create<Zip>("sources") {
  dependsOn("clean")
  shouldRunAfter("clean")
  description = "Archives sources in a zip file"
  group = "Archive"
  from("src") {
    into("src")
  }
  from("build.gradle.kts")
  from("settings.gradle.kts")
  from(".vuepress") {
    into(".vuepress")
  }
  from("README.md")
  from("package.json")
  archiveFileName.set("${project.buildDir}/sources-${project.version}.zip")
}
Updated at: 4/7/2019, 9:25:13 PM