Kotlin microservices pattern

It's no secret for developers that creating a new service entails a lot of routine configuration: build scripts, dependencies, tests, docker, k8s descriptors. Since we're doing this job, the current IDE templates aren't enough. Under the cut, my attempts to automate every single cross-platform "do well" button accompanied by code, examples and the final result.





If the prospects of creating services in one click with subsequent automatic deployment in Digital Ocean sound tempting, then this article is for you.



Let's start creating our template and first of all consider the assembly organization. Despite the love of many for maven for its simplicity and declarativeness, we will use gradle, because it is more modern and allows you to write a build script in the same language as the project. In addition to the Kotlin plugin itself, we need one more:





plugins {
  kotlin("jvm") version "1.4.30"

  //     jvm
  id("org.beryx.runtime") version "1.12.1"
}
      
      



Of the dependencies, the "native" Kotlin Ktor framework was chosen as the server framework . For testing, a bunch of JUnit + Hamkrest is used with its expressive DSL, which allows you to write tests in this way:





assertThat("xyzzy", startsWith("x") and endsWith("y") and !containsSubstring("a"))
      
      



Putting it all together, focusing on Java 15+





dependencies {
  implementation("com.github.ajalt.clikt:clikt:3.1.0")
  implementation("io.ktor:ktor-server-netty:1.5.1")
  testImplementation("org.junit.jupiter:junit-jupiter:5.8.0-M1")
  testImplementation("com.natpryce:hamkrest:1.8.0.1")
  testImplementation("io.mockk:mockk:1.10.6")
}

application {
  mainClass.set("AppKt")
}

tasks {
  test {
    useJUnitPlatform()
  }
  compileKotlin {
    kotlinOptions.jvmTarget = "15"
  }
}
      
      



entry-point , , ( Hamkrest).





, Kotlin codestyle - .editorsconfig:





[*.{kt, kts, java, xml, html, js}]
max_line_length = 120
indent_size = 2
continuation_indent_size = 2
      
      



, , , , , .







gradle clean test runtime
      
      



( build/image) , build/image/bin



Dockerfile, . :





# syntax = docker/dockerfile:experimental
FROM gradle:jdk15 as builder
WORKDIR /app
COPY src ./src
COPY build.gradle.kts ./build.gradle.kts
RUN --mount=type=cache,target=./.gradle gradle clean test install

FROM openjdk:15 as backend
WORKDIR /root
COPY --from=builder /app/build/install/app ./
      
      



jdk ( jvm) c jstack/jmap jdk.



Docker Compose:





version: "3.9"

services:
  backend:
    build: .
    command: bin/app
    ports:
      - "80:80"
      
      



, jdk/gradle,





docker-compose up
      
      



? Digital Ocean - . , Apps Platform ... ! Docker , , , , , . 5$ :





master , , .





Finally, everything described in the article is documented in detail in the README.md file of the template, so that after creating the project, the subsequent build and deployment would not cause difficulties.



You can use the template to get a ready-made repository by simply clicking the button "Use this template"



on GitHub:

github.com/demidko/Projekt-portable



Or, if you need a self-executable jar option without a portable jvm:

github.com/demidko/Projekt-jar



After that, it remains just write logic :) Like any approach, this template is not without its flaws, so it is interesting to hear suggestions, comments and criticism.








All Articles