Web UIs mit Kotlin

Was ich am aufregendsten an Kotlin finde, ist dessen Konzeption, ein einheitliches Toolkit (Sprache + Bibliotheken + Tooling) anzubieten, sich aber auch auf die native Umgebung zu verlassen, wo immer eine Kotlin-Anwendung läuft. Die Verwendung von Kotlin auf der JVM bedeutet eine vollständige Interoperabilität mit Java, im Browser können wir auf JavaScript-Bibliotheken zugreifen, und auch wenn es um die UI-Entwicklung geht, gilt Kotlin dasselbe Prinzip.

Continue reading
Posted in Uncategorized | Tagged , , | Leave a comment

Kommunikation zwischen Browser und Backend: Objektserialisierung mit Kotlin

Java bietet eine sogenannte Objektserialisierung, bei der ein Objekt als eine Folge von Bytes dargestellt werden kann, die sowohl die Daten des Objekts als auch Informationen über den Typ des Objekts und die im Objekt gespeicherten Datentypen enthält. Nachdem ein serialisiertes Objekt in einen Datenstrom geschrieben wurde, kann es aus diesem Datenstrom wieder gelesen und deserialisiert werden, d.h. die Typinformationen und Bytes, die das Objekt und seine Daten repräsentieren, können verwendet werden, um das Objekt im Speicher neu zu erstellen.

Am beeindruckendsten ist, dass der gesamte Prozess JVM-unabhängig ist, d.h. ein Objekt kann auf einer Plattform serialisiert und auf einer völlig anderen Plattform deserialisiert werden

Zum Beispiel GWT RPC: Wer schon mit dem Google Web Toolkit (GWT) gearbeitet hat, kann sich gut an GWT RPC erinnern. GWT RPC (GWT Remote Procedure Call) ist der von GWT verwendete Mechanismus, mit dem Client-Code direkt server-seitige Methoden aufrufen kann. GWT RPC ist servlet-basiert und asynchron, d.h. der Client wird während der Kommunikation nie blockiert. Mit GWT RPC können Java-Objekte (die vom GWT-Framework automatisch serialisiert werden) direkt zwischen dem Client und dem Server ausgetauscht werden. Ein server-seitiges Servlet wird als Service bezeichnet. Ein Remote Procedure Call, bei dem Methoden server-seitiger Servlets vom client-seitigen Code aus aufgerufen werden, wird als Aufruf eines Services bezeichnet.

Kotlin hat keinen eigenen RPC-Mechanismus, wie GWT. Aber Kotlin kann Objekte zu/von JSON (de)serialisieren. Das ist total einfach, weil auf beiden Seiten (Browser und Backend) die gleichen Klassen benutzt werden. Ich werde den Prozess Schritt für Schritt erklären.

kotlinx.serialization bietet eine Reihe von Bibliotheken für alle unterstützten Plattformen – JVM, JavaScript, Native – und für verschiedene Serialisierungsformate – JSON, CBOR, Protokollpuffer und andere. Einige Daten-Serialisierungsformate, wie JSON, sind besonders verbreitet. Da sie sprach- und plattformneutral sind, ermöglichen sie den Datenaustausch zwischen Systemen, die in einer beliebigen modernen Sprache geschrieben wurden. Alle Kotlin-Serialisierungsbibliotheken gehören zu org.jetbrains.kotlinx.

kotlinx.serialization enthält Bibliotheken für verschiedene Serialisierungsformate:

  • JSON: kotlinx-serialization-core
  • Protocol buffers: kotlinx-serialization-protobuf
  • CBOR: kotlinx-serialization-cbor
  • Properties: kotlinx-serialization-properties
  • HOCON: kotlinx-serialization-hocon (nur auf JVM)

Einrichtung

Zuerst muss man sein Build-Skript so konfigurieren, dass man die Kotlin-Serialisierungstools im Projekt verwenden kann. Zweitens wendet  man das Kotlin Serialisierungs-Plugin für Gradle org.jetbrains.kotlin.plugin.serialization (oder kotlin ("plugin.serialization") in der Kotlin Gradle-DSL) an.

plugins {
   
kotlin("multiplatform") version "1.3.71"
    application //to run JVM part
    kotlin("plugin.serialization") version "1.3.71"
    kotlin("plugin.spring") version "1.3.71"

}

Als nächstes fügt man die Abhängigkeit zu der JSON-Serialisierungsbibliothek hinzu.

implementation("org.jetbrains.kotlinx:kotlinx-serialization-runtime-js:$serialization_version")

Beispiel Todo-Liste

Ich habe eine Todo-Liste erstellt, deren Einträge drei Eingabeparameter erhalten, nämlich Kategorie, Beschreibung und Id, wie man in der TodoEntry-Klasse sehen kann.

data class TodoEntry(val category: String, val description: String, val id: Int = 0)

Diese Klasse kann jedoch noch nicht für Serialisierungszwecke verwendet werden, da wir den Compiler noch nicht angewiesen haben, Serialisierungscode zu generieren. An dieser Stelle kommt die @Serializable Annotation zum Einsatz. Diese Annotation weist den Compiler dazu an, den Code zu generieren, der für die Durchführung der Serialisierung für unsere Klasse erforderlich ist:

@Serializable
data class TodoEntry(val category: String, val description: String, val id: Int = 0)

Jetzt kann der Compiler TodoEntry-Objekte verstehen und serialisieren.

Wir werden auch definieren müssen, welche Art von JSON wir erwarten. Wir definieren dies mit Hilfe von JsonConfiguration. Diese Klasse hilft uns, das Verhalten für das JSON-Objekt zu konfigurieren. Sie stellt uns zwei gebrauchsfertige Konfigurationen zur Verfügung – Stable und Default. Wir werden die Konfiguration Stable verwenden, die sich an die Einschränkung der JSON-Spezifikation hält und von der Laufzeitbibliothek bereitgestellt wird. Um ein Objekt zu serialisieren (d.h. in JSON zu konvertieren), kann die Methode stringify() verwendet werden.

Im folgenden Beispiel sehen wir, wie wir mit einem JSON-Konfigurationsobjekt ein TodoEntry-Objekt in einen JSON String umwandeln können:

val json = Json(JsonConfiguration.Stable)
val todo = json.stringify(TodoEntry.serializer(), TodoEntry(category.value, description.value))

Wir wissen bereits aus dem vorherigen Blog-Beitrag, wie man eine Spring-Boot-Anwendung mit Kotlin erstellt. Jetzt können wir die Kommunikation zwischen Browser und Backend herstellen.

Zuerst erstellen wir einen Controller, mit dem man Todo-Einträge bearbeiten kann. Er enthält vier Methoden, um die Einträge auszulesen, einen Eintrag hinzuzufügen, zu aktualisieren und zu löschen.

Controller:

@RestController
@RequestMapping("/todo")
class TodoController @Autowired constructor(val service: TodoService) {

    @GetMapping(produces = arrayOf(MediaType.APPLICATION_JSON_VALUE))
    fun getEntries(): String {
        val json = Json(JsonConfiguration.Stable)
        return json.stringify(TodoEntry.serializer().list, service.getTodoEntries())
    }

    @PostMapping
    fun addEntry(@RequestBody todoJson: String) {
        val json = Json(JsonConfiguration.Stable)
        val todoEntry = json.parse(TodoEntry.serializer(), todoJson)
        service.addEntry(todoEntry)
    }

    @PutMapping(consumes = arrayOf(MediaType.APPLICATION_JSON_VALUE))
    fun updateEntry(@RequestBody todoJson: String) {
        val json = Json(JsonConfiguration.Stable)
        val todoEntry = json.parse(TodoEntry.serializer(), todoJson)
        service.updateEntry(todoEntry)
    }

    @DeleteMapping("/{id}")
    fun deleteEntry(@PathVariable("id") id: Int) {
        service.removeEntry(id)
    }
}

@RestController zeigt an, dass die von jeder Methode zurückgegebenen Daten direkt in den Antwortbody geschrieben werden, anstatt ein Seitentemplate zu rendern.

Wir haben Routen für jede Operation (@GetMapping, @PostMapping, @PutMapping und @DeleteMapping, entsprechend den HTTP-Aufrufen GET, POST, PUT und DELETE). Dazu werde ich nicht weiter ins Detail gehen.

Service Components sind Klassen, die mit @Service annotiert sind. Diese Klassen werden verwendet, um Geschäftslogik in einer eigenen Schicht, getrennt von der @RestController-Klasse, zu schreiben. Die Logik einer Service-Klasse zur Behandlung von TodoEntry-Objekten ist hier dargestellt:

Service:

@Component
class TodoService() {

    var entries: MutableMap<Int, TodoEntry> = HashMap();
    var counter: Int = 0;

    @PostConstruct
    fun initEntries() {
        addEntry(TodoEntry("shopping","Butter"))
        addEntry(TodoEntry("shopping","Bread"))
        addEntry(TodoEntry("work","Learn Kotlin"))
    }

    fun getTodoEntries(): List<TodoEntry> {
        return ArrayList(entries.values)
    }

    fun addEntry(entry: TodoEntry) {
        val id = counter++
        entries.put(id, TodoEntry(entry.category, entry.description, id))
    }

    fun updateEntry(entry: TodoEntry) {
        val id = entry.id
        if (!entries.containsKey(id)) {
            throw IllegalArgumentException("Unknown entry id " + id)
        }
        entries.put(id, entry)
    }

    fun removeEntry(id: Int) {
        entries.minus(id)
    }
}

Wenn man über localhost auf Port 8080 zugreift und das /todo aus dem @RequestMapping hinzufügt, kann man die hinzugefügte Todo-Liste als JSON Objekte sehen.

Man kann Listen hinzufügen mit Hilfe eines Buttons: UI-Elemente, die in weiteren Blog-Beiträgen aus dieser Serie diskutiert werden.

Ich hoffe, dass der Beitrag interessant war. Es folgen noch weitere Beiträge zu Kotlin – UI, Web Basics und “Development Server”.

Posted in Other languages for the Java VM | Tagged , , | Leave a comment

Spring Boot mit Kotlin

Spring Boot makes it easy to create stand-alone, production-grade Spring-based Applications that you can ‘just run’.

Kotlin wurde so konzipiert, dass es gut mit dem Java-Ökosystem zusammenspielt, und es scheint mir, dass es die gleiche pragmatische und innovative Denkweise teilt wie Spring Boot, sodass sie gut zusammenspielen. In diesem Beitrag werde ich eine Spring Boot-Anwendung von Anfang an mit Kotlin als Hauptsprache erstellen. Man wird lernen, wie Kotlin mit Spring arbeitet. Am Ende wird man eine einfache Spring-Anwendung haben, die mit Kotlin implementiert ist. Mit jeder neuen Version von Spring Boot haben wir eine bessere Kotlin-Unterstützung und können Spring-Anwendungen mit minimalem Boilerplate programmieren.

Spring Boot bietet eine idiomatische Möglichkeit, eine Anwendung mit runApplication<MyApplication>(*args) auszuführen. Wir haben die Methode mit dem reifizierten Typparameter MyApplication qualifiziert, jetzt ist er innerhalb der Funktion zugänglich. Da die Funktion inline ist, ist der Zugriff auf den Typparameter zur Laufzeit ohne Reflection möglich. Normale Funktionen (nicht als inline markiert) können keine reified Typparameter haben.

Anwendungsbeispiel

Lass uns eintauchen und eine Kotlin-Anwendung mit Spring Boot 2 erstellen! Die Unterstützung von Spring durch Kotlin ist in der Referenzdokumentation zu Spring Framework und Spring Boot dokumentiert.

Gradle ist das am häufigsten verwendete Build-Werkzeug für Kotlin und stellt eine Kotlin-DSL zur Verfügung, die bei der Generierung eines Kotlin-Projekts standardmäßig verwendet wird, sodass dies die empfohlene Wahl ist. Man kann aber auch Maven verwenden, wenn man damit besser zurechtkommt. Zuerst müssen wir eine Spring Boot Anwendung erstellen, was auf verschiedene Arten geschehen kann. Ich werde den Spring Initializer von https://start.spring.io verwenden, um das Grundgerüst für eine Spring-Anwendung mit der Spring Web-Abhängigkeit zu generieren:

Das Projekt sollte die folgende Struktur haben:

Wenn man das Projekt importiert hat, sieht man, dass es eine einzige Anwendungsdatei mit dem Namen SpringKotlinApplication.kt enthält. In der Datei finden man den folgenden Code:

import org.springframework.boot.autoconfigure.SpringBootApplication
import org.springframework.boot.runApplication

@SpringBootApplication
class SpringBootKotlinApplication

fun main(args: Array<String>) {
   runApplication<SpringBootKotlinApplication>(*args)
}

Diese Datei enthält die main Funktion, mit der die Anwendung gestartet wird. Um eine Funktion in Kotlin zu deklarieren, verwendet man das Schlüsselwort fun, gefolgt von ihrem Namen, den Parametern und dem Rückgabetyp. Wenn es keinen Rückgabetyp gibt, gibt man nichts an, was bei dieser Funktion der Fall ist.

Auch hier hat man eine mit @SpringBootApplication annotierte Klasse, die sich genauso verhält wie in Java. Man wird auch feststellen, dass SpringKotlinApplication nicht als public deklariert ist. Der Grund ist ziemlich einfach: Alle Klassen sind in Kotlin standardmäßig public! Zusätzlich kann eine Klasse, die keine Variablen und keine Funktionen hat, ohne geschweifte Klammern deklariert werden. Im Wesentlichen haben wir also gerade eine Klasse definiert.
Jede außerhalb des Körpers einer Klasse definierte Funktion ist automatisch statisch. Dadurch ist diese Funktion für die Startausführung geeignet.

Gradle

Die Schlussfolgerung, die wir aus der Gradle-Konfiguration ziehen, ist die folgende: Sie enthält die Spring-Framework-Plugins mit Abhängigkeiten für Spring-Boot. Sie enthält Abhängigkeiten wie:

  • kotlin-stdlib-jdk8 – ist die Java-8-Variante der Kotlin-Standardbibliothek
  • kotlin-reflect – ist die Kotlin Reflection-Bibliothek
  • jackson-module-kotlin – fügt Unterstützung für die Serialisierung/Deserialisierung von Kotlin-Klassen und Datenklassen hinzu, ein Thema, das in weiteren Blogbeiträgen diskutiert werden soll.

Die Datei build.gradle.kts enthält folgenden Code

import org.jetbrains.kotlin.gradle.tasks.KotlinCompile

plugins {
   id("org.springframework.boot") version "2.3.2.RELEASE"
   id("io.spring.dependency-management") version "1.0.9.RELEASE"
   kotlin("jvm") version "1.3.72"
   kotlin("plugin.spring") version "1.3.72"
}

group = "com.trivadis"
version = "0.0.1-SNAPSHOT"
java.sourceCompatibility = JavaVersion.VERSION_11

repositories {
   mavenCentral()
}

dependencies {
   implementation("org.springframework.boot:spring-boot-starter-web")
   implementation("com.fasterxml.jackson.module:jackson-module-kotlin")
   implementation("org.jetbrains.kotlin:kotlin-reflect")
   implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8")
   testImplementation("org.springframework.boot:spring-boot-starter-test") {
      exclude(group = "org.junit.vintage", module = "junit-vintage-engine")
   }
}

tasks.withType<Test> {
   useJUnitPlatform()
}

tasks.withType<KotlinCompile> {
   kotlinOptions {
      freeCompilerArgs = listOf("-Xjsr305=strict")
      jvmTarget = "11"
   }
}

Danach muss nur noch eine RestController-Klasse hinzugefügt und die Anwendung gestartet werden. Die RestController-Annotation @RestController zeigt an, dass die Klasse eingehende Anforderungen behandelt, und die @GetMapping-Annotation zeigt Methoden an, die einzelne Endpunkte behandeln:

import org.springframework.web.bind.annotation.GetMapping
import org.springframework.web.bind.annotation.RequestParam
import org.springframework.web.bind.annotation.RestController

@RestController
class Controller {

    @GetMapping("/helloWorld")
    fun helloWorld(): String {
        return "Hello, World"
    }

    @GetMapping("/helloName")
    fun helloName(@RequestParam("name") name: String): String {
        return "Hello, $name"
    }
}

Man führt die Anwendung aus, indem man die Klasse SpringKotlinApplication in der IDE ausführt (oder mit ./gradlew bootRun). Man geht danach auf http://localhost:8080/helloWorld. Es sollte die folgende Begrüßungsnachricht im Browser zu sehen sein:

Wir können es dynamischer gestalten, indem wir die Nachricht in dem Endpunkt für die Begrüßung aller Personen verfügbar machen. Bei der zweiten Methode, helloName(), erhält die Funktion einen Parameter namens name.

In Kotlin deklariert man Parameter, indem man zuerst den Namen angibt, gefolgt von einem Doppelpunkt und seinem Typ. Dies ist die gleiche Konvention, die zur Deklaration des Rückgabetypen einer Funktion verwendet wird. Die Annotation @RequestParam wird an die gleiche Stelle gesetzt wie im Java-Code.

Vielleicht ist euch auch aufgefallen, dass man Strings nicht konkatenieren muss, um variable Werte einzufügen. Kotlin hat eine eingebaute Funktion namens String-Templates, die es erlaubt, eine Variable zu referenzieren, indem man das $-Zeichen gefolgt vom Variablennamen selbst setzt.

Startet man die Anwendung erneut und öffnet den folgenden Link http://localhost:8080/helloName?name=Andrada, dann sollte man die nachstehende Meldung sehen:

In diesem Artikel befassten wir uns mit der Kotlin-Unterstützung in Spring Boot 2.x. Anhand eines Beispiels sahen wir, dass Kotlin unsere Anwendungen vereinfachen und verbessern kann, indem es uns dabei unterstützt, kürzeren und sichereren Code zu schreiben. Kotlin unterstützt auch einige erstaunliche Funktionen wie Datenklassen, Extension Functions und ist vollständig kompatibel mit vorhandenem Java-Code. Das bedeutet, dass man Kotlin-Code schreibt und von den Java-Klassen aus aufrufen kann und umgekehrt. Darüber hinaus wurde Kotlin von Grund auf so aufgebaut, dass es fantastische Unterstützung in einer IDE bietet, und das tut es auch.

Es gibt viele Gründe, Kotlin auszuprobieren, und mit der Unterstützung von Google und Spring ist es jetzt an der Zeit, es auszuprobieren. Dieser Blog-Beitrag ist der dritte Blog-Beitrag (Kotlin für Java-Entwickler, Kotlin Multi-Platform Projekte für die Web-Entwicklung) aus einer Serie von Kotlin-Blog-Beiträgen. Es ist geplant, weitere interessante Artikel zu schreiben, also bleibt dran.

Posted in Other languages for the Java VM | Tagged , | 1 Comment

Re-deploy your containerized Java application on Azure

In my previous post a while ago I showed you how to deploy your dockerized Java application on Azure. It was a step-by-step introduction switching from browser to IDE, to command line (Docker CLI or Azure CLI), to the Azure web interface. It worked out, but regarding that it was just about the deployment of your code it took quite some time, right? So what about re-deploying your application maybe after making small changes, like fixing a tiny bug? Do you want to do those steps

-> change your code
-> re-build your project
-> build a new docker image
-> tag the image correctly
-> push it to your remote repo
-> stop the running container (?)
-> re-deploy the new container to Azure

over and over again? No, certainly not!

You just want to change the piece of code and then run the following steps as automated as possible. Switching from one tool to another is also not what you want. There are faster ways to achieve this than executing all those steps by hand, depending on your actual environment and personal preferences. So as a Java developer you will most likely build your project with Gradle or Maven. This comes in handy as they offer great plugins to make your life easier. In the following I will stick to Gradle, however similar things are possible using Maven.

My goal was to see how far I could possibly push the whole build and deployment process.

Continue reading
Posted in Java Runtimes - VM, Appserver & Cloud | Tagged , , , | Leave a comment

Kotlin Multiplattform-Projekte für die Web-Entwicklung

Kotlin Multiplatform says that it will take care of the business logic and we just need to take care of the UI.

Laut GitHub war Kotlin die am schnellsten wachsende Programmiersprache des Jahres 2018, was die Verwendung in GitHub-Repositorien betrifft. Die Kotlin-Multiplattformfunktion ist seit Version 1.2, die Ende 2017 veröffentlicht wurde, Teil der Kotlin-Programmiersprache. Der Kotlin-Compiler bietet Unterstützung für die Kompilierung von Code in ein natives Zielformat. Folglich können Kotlin-Anwendungen in Umgebungen ausgeführt werden, die virtuelle Maschinen zum Ausführen von Anwendungen nicht unterstützen, z. B. Apple Smartphones mit iOS. Die unterstützten Plattformen für native Anwendungen sind Android NDK, iOS, Linux, MacOS, Windows und WebAssembly. Kotlin bietet auch Unterstützung für die Kompilierung nach Javascript.

Continue reading
Posted in Other languages for the Java VM, Web as a Platform | Tagged , | Leave a comment

Kotlin für Java Web-Entwickler

Ende-zu-Ende Entwicklung ohne Technologiebruch, Übertragung von Objekten zwischen Backend und Browser-Anwendung, Ausgleich der Unterschiede zwischen Browsern, starke Typisierung, Nutzung des gleichen Codes in UI, Backend oder Android Apps? Ist es möglich, dass eine Programmiersprache all dies leisten kann? Ja, das ist es. Und dies sind nur einige Eigenschaften, die Kotlin bietet. Lass uns losgehen.

Continue reading
Posted in Web as a Platform | Tagged , , | 2 Comments

Dependency Injection mit Angular 9

Der Angular 9 Release, eines der grössten Updates in den letzten drei Jahren, ist bereits knapp vier Monate her. Der Schwerpunkt vom Release und somit auch von vielen der Release Notes lag sicherlich auf dem Ivy-Compiler. Dieser ist nun standardmässig in Angular aktiviert. Ivy wurde bereits mit Angular 8 als Opt-In-Möglichkeit eingeführt und in einem früheren Blog-Artikel erläutert.

Auch wenn die Änderungen mit Ivy sehr umfangreich sind, ist dies jedoch nicht das einzige neue Feature, welches mit dem Angular 9 Release eingeführt wurde. Denn es wurden zum Beispiel auch die Möglichkeiten der Dependency Injection erweitert mit zwei neuen Optionen für providedIn. Dies wurde jedoch im Release Note nur kurz erläutert. Aufgrund dessen wird in diesem Blog-Artikel ein Überblick über die bisherigen und die nun erweiterten Möglichkeiten der Dependency Injection in Angular gegeben.

Continue reading
Posted in Web as a Platform | Tagged , | Leave a comment