Ein Blick auf Ktor – 7 Eindrücke

Am letzten MayDay habe ich mir das Anwendungs-Framework Ktor [ˈkeɪˈtor] angesehen und einen kleinen Webservice damit aufgesetzt. In diesem Artikel möchte ich Ktor vorstellen und sieben Gründe nennen, die für den Einsatz des Frameworks sprechen.

Was ist Ktor?

Ktor ist ein in Kotlin verfasstes Multiplattform-Anwendungs-Framework aus dem Hause JetBrains. Es ermöglicht die Entwicklung von Web-Client- und Server-Applikationen. Außerdem eignet es sich zur Erstellung von Microservices in vernetzten Systemen.

1. Ktor ist leichtgewichtig

Ktor zeichnet sich durch einfache Anwendung und gute Lesbarkeit aus. Diese Eigenschaften ziehen sich durch alle Facetten. Eine einfache Hello-World-Applikation für einen Netty-Server auf localhost:8080 mit einer simplen GET-Route auf den Base Path / ist klein genug, um in einen Tweet zu passen:

    fun main() {
        embeddedServer(Netty, port = 8080) {
            routing {
                get("/") {
                    call.respondText("Hello World!")
                }
            }
        }.start(wait = true)
    }

Neue Routen können einfach hinzugefügt werden. Im folgenden Beispiel wird die POST-Route /user erstellt, die aus dem JSON-Request-Body ein User-Objekt entgegennimmt und zur Collection myUserStack hinzufügt:

    fun main() {
        embeddedServer(Netty, port = 8080) {
            routing {
                get("/") {
                    call.respondText("Hello World!")
                }
                post("/user") {
                    myUserStack.add(call.receive())
                    call.respond(HttpStatusCode.Created)
                }
            }
        }.start(wait = true)
    }

Mit nur wenig Code können auch zahlreiche statische Dateitypen zurückgegeben werden. Das folgende Beispiel liefert eine PDF-Datei mit dem entsprechenden Header zurück:

    fun main() {
        embeddedServer(Netty, port = 8080) {
            routing {
                get("/") {
                    call.respondText("Hello World!")
                }
                get("/legal") {
                    call.respondFile(File("/res/pdf/legal.pdf"))
                }
            }
        }.start(wait = true)
    }

Unser viertes Beispiel liefert uns mit wenig Code einen Gson-Response-Body:

    fun main() {
        embeddedServer(Netty, port = 8080) {
            routing {
                get("/") {
                    call.respondText("Hello World!")
                }
                get("/json/gson") {
                    call.respond(
                        mapOf(
                            "status" to "success",
                            "value" to mapOf(
                                "id" to 51,
                                "joke" to "The quickest way to a man's heart is with Chuck Norris' fist."
                    )))
                }
            }
        }.start(wait = true)
    }

2. Kotlin als Basis

Ktor ist komplett in JetBrains hauseigener Programmiersprache Kotlin verfasst und nutzt deren Sprachfeatures. Beispielsweise werden durch den Einsatz von Kotlins Koroutinen komplexe und asynchrone Codekonstrukte geschaffen, die sequentiell und gut lesbar definiert werden können.

In diesem Beispiel wird eine zuvor initiierte User-Authentifizierung auf eine neue Route angewandt:

    fun main() {
        embeddedServer(Netty, port = 8080) {
            routing {
                get("/") {
                    call.respondText("Hello World!")
                }
                authenticate("myBasicAuth") {
                    get("/protected") {
                        val principal = call.principal<UserIdPrincipal>()!!
                        call.respondText("Hello ${principal.name}")
                    }
                }
            }
        }.start(wait = true)
    }

Hier wird ein HTML-Body gerendert und zurückgegeben:

    fun main() {
        embeddedServer(Netty, port = 8080) {
            routing {
                get("/") {
                    call.respondText("Hello World!")
                }

                get("/html-dsl") {
                    call.respondHtml {
                        body {
                            h1 { +"HTML" }
                            ul {
                                for (n in 1..10) {
                                    li { +"$n" }
                                }
                            }
                        }
                    }
                }
            }
        }.start(wait = true)
    }

3. Umfangreiche API-Features

Ktors API ist nicht nur leichtgewichtig, sondern auch umfangreich und flexibel erweiterbar. Benötigte Features können jederzeit über den Package Manager Gradle nachinstalliert werden. Unter anderem bietet das API Unterstützung für die folgenden Features und Use Cases:

  • Auto-Reload-Feature des Webservers für den Entwicklungsprozess
  • Diverse Template-Engines für Frontend-Komponenten
  • Static Content Serving für viele Default-Dateitypen, beispielsweise HTML, JavaScript oder PDF
  • Ein umfangreiches Logging-Framework, das in alle Komponenten integriert ist
  • Unterstützung für verschiedene User-Authentifizierung-Standards (JWT, JWK, LDAP u. OAuth).

4. Modernes Projekt-Setting

Ktor basiert auf einem modernen Technologie-Stack. Als Build Tool und Packager Manager wird Gradle verwendet, über den standardisiert auf ein Repository an Bibliotheken und Frameworks für Java und Kotlin zugegriffen werden kann.

Das Test-Framework JUnit mitsamt Beispieltests ist bereits in der Ktor-Projektvorlage integriert. Die Definition und Ausführung weiterer Tests sowie die Generierung der Code Coverage via Gradle sind daher auch für Einsteiger transparent und zugänglich.

Zudem können zahlreiche ausgereifte Code-Quality-Tools für Java und Kotlin installiert und genutzt werden. Beispiele hierfür wären CheckMark, detekt oder SonarLint.

Viele automatisierte Code-Inspection- oder Build-Tools können als Gradle-Plugins auch zur Realisierung einer eigenen CI-/CD-Pipelineeingesetzt werden.

5. Alternative zu Spring Boot

Spring Boot bietet deutlich mehr Funktionalität und Flexibilität, ist dafür aber nicht so leichtgewichtig wie Ktor.

Gerade in kleinen Projekten halte ich die verwendeten Kotlin-Sprachfeatures wie beispielsweise Koroutinen für besser lesbar und somit auch für besser verwaltbar als die in Sprint Boot verwendeten Annotations, Beans und Configurations. Vor allem für kleinere Projekte bietet sich Ktor daher als Alternative an.

6. Schneller Einstieg

JetBrains bietet einen Online-Ktor-Projekt-Generator, in dem alle für das neue Projekt initial zur Verfügung stehenden APIs und Features angepasst werden können. Anschließend kann das neue Gradle-Projekt heruntergeladen und als Grundlage für ein neues Projekt verwendet werden.

Alternativ kann mit dem Plugin für IntelliJ lokal ein neues Projekt konfiguriert und erstellt werden.

7. Spaßfaktor

Ktor ermöglicht die schnelle Realisierung von Anwendungen und Microservices. Die Features und das API sind ausgereift und das Zusammensetzen der geschaffenen Schnittstellen ermöglicht eine schnelle und modulare Umsetzung der gewünschten Features.

Auch die gute Dokumentation zahlt auf die hohe Developer Experience ein.

Einschätzung

Ktor ist mehr high-level und weniger Magic.

In einem folgendem Artikel zeige ich einen schnellen Einstieg in die praktische Arbeit mit Ktor. Ich freue mich, wenn ich Euer Interesse für Kotlin wecken konnte. Über Feedback oder Rückfragen könnt ihr mich jederzeit via christopher.stock@mayflower.de erreichen.

Für neue Blogupdates anmelden:


Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.