Kotlin. Getting started
Preface
Kotlin is a wonderful language today mostly used for android application development. But it’s a general-purpose language and could be used for backend either. This post is aimed to provide a comprehensive guide on how to start server-side programming for people who aren’t familiar with the language.
IDE
Kotlin was invented in JetBrains, the company which is famous for the best IDE in the world IntelliJ IDEA. So Idea has amazing support of Kotlin out of the box.
New project
IDEA has a built-in wizard for a new project. In the first step, we need to choose a gradle project. Gradle is the most common build tool for Java/Kotlin projects.
IDEA will create a basic project structure for you
.
├── build.gradle
├── gradle
│ └── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradle.properties
├── gradlew
├── gradlew.bat
├── settings.gradle
└── src
├── main
│ ├── java
│ ├── kotlin
│ └── resources
└── test
├── java
├── kotlin
└── resources
11 directories, 7 files
I recommend updating gradle immediately on this stage. IDEA by default generates so-called “gradle wrapper” which is a good approach. It allows you to fix gradle version in the project and always use this vendored version.
To update gradle you need to go to the gradle/wrapper/gradle-wrapper.properties
config and change version in distributionUrl
property.
Before:
distributionUrl=https\://services.gradle.org/distributions/gradle-6.1.1-bin.zip
After:
distributionUrl=https\://services.gradle.org/distributions/gradle-6.6.1-bin.zip
Thus we change gradle version from v6.1.1 to v6.6.1. After it, IDEA will do the rest for you.
Hello world
Now we ready to write our first code in Kotlin: src/main/kotlin
is our main folder for code. Let’s create a package first, as it is used to do in the Java-world. The next step is to create a file for source code, I prefer to name it main.kt
but it doesn’t matter, you can name it whatever you want.
Cool. Now we can start the code in the IDE. But there is no IDE on a server, so let’s go and build an artifact. For this, we will need a gradle application plugin. In build.gradle
we need to add a section like
If the source file has no class in it, Kotlin will create the class for you and name it in pascal-case. Be careful with the property name. For gradle 6.0 it’s called mainClassName
and for version 6.1 it is mainClass
. Can be very confusing.
Also, we need to add an application plugin to the plugins
section like this
Now we can run our app from the console:
$ ./gradlew run
But there is no artifact yet. To create an artifact we need another task
$ ./gradlew build
It will create a lot of interesting stuff in the build
directory
build
├── classes
│ └── ...
├── distributions
│ ├── kronstadt-1.0-SNAPSHOT.tar
│ └── kronstadt-1.0-SNAPSHOT.zip
├── kotlin
│ └── ...
├── libs
│ └── kronstadt-1.0-SNAPSHOT.jar
├── scripts
│ ├── kronstadt
│ └── kronstadt.bat
└── ...
20 directories, 66 files
Archives in distributions
are you artifacts you can deploy to the server. Choose your favorite archive format and send it to the server. Let’s try
$ tar xf kronstadt-1.0-SNAPSHOT.tar
$ cd kronstadt-1.0-SNAPSHOT
$ ./bin/kronstadt
Hello world!
Awesome. You see how application plugin generated script to run our app and grandmotherly put it the bin
directory.
It is also possible to create a single all-in-one jar file (aka uberjar) which can be launched with command java -jar kronstadt.jar
, but it’s not idiomatic.
Adding tests
There is a neat testing library for Kotlin called Spek. It uses very expressive syntax inspired by ruby rspec.
Add jcenter first
Add dependencies to the build.gradle
Setup the test task
Now we are ready to write our first test in src/test/kotlin
folder. To be able to access the testee code without import we need to put tests to the same package.
As you can see spek uses Kotlin advanced features like objects and reflection to make syntax expressive.
You can run tests from IDE or from the console with
$ ./gradlew test
I also encourage you to consider Kotest as it looks very nice
Adding linter
Linter is a very important tool, especially for newcomers. For kotlin I like to use detekt. Detekt is shipped with gradle plugin to simplify configuration. So in build.gradle
add
Then we need to generate a config file
$ ./gradlew detektGenerateConfig
> Task :detektGenerateConfig
Successfully copied default config to kronstadt/config/detekt/detekt.yml
BUILD SUCCESSFUL in 790ms
1 actionable task: 1 executed
Then reference the newly generated config inside the detekt
closure.
Add klint formatting rules
That’s it. The basic configuration is over. To run detekt just put in the console
$ ./gradlew detekt
HTTP Server
As a fan of ruby’s roda I prefer minimalistic web servers. Luckily there is one for Java/Kotlin. Meet Spark!
Add dependency to build.gradle
Let’s rewrite our main
function
And test it with curl
$ curl localhost:4567/hello
Hello world!%
Very good!
Docker
As all cool guys, we will deploy our app with docker.
Dockerfile will look like
FROM openjdk:8 AS build-stage
WORKDIR /opt/app
COPY . .
RUN ./gradlew distTar
FROM openjdk:8
COPY --from=build-stage /opt/app/build/distributions/kronstadt-1.0-SNAPSHOT.tar /opt/app/kronstadt-1.0-SNAPSHOT.tar
WORKDIR /opt/app
RUN tar xf kronstadt-1.0-SNAPSHOT.tar && rm kronstadt-1.0-SNAPSHOT.tar
WORKDIR /opt/app/kronstadt-1.0-SNAPSHOT
CMD ./bin/kronstadt
Build:
$ docker build -t kronstadt .
Run:
$ docker run --rm -p 4567:4567 kronstadt:latest
Test:
$ curl localhost:4567/hello
The end!