Kotlin und Java Code im Spring Projekt mischen

Kotlin und Java sind beides Programmiersprachen, die auf der JVM aufsetzen. Deshalb ist es möglich Java Klassen in einem Kotlin Projekt zu schreiben und zu verwenden. Java-Dateien können aber auch automatisch in Kotlin übersetzt werden. Ich werde euch hier einen entsprechenden Mischmasch präsentieren! 😄

Warum Kotlin und Java mischen?

Ein riesen Vorteil der Programmiersprache Kotlin ist aus meiner Sicht, dass wir einen großen Teil der vielen vorhandenen Java Frameworks und Bibliotheken (z.B. Spring) verwenden können. Das funktioniert, weil Kotlin genau wie Java auf der JVM (Java Virtual Machine) aufsetzt.

Wenn man in Kotlin Java-Bibliotheken (jar Dateien) verwenden kann, kann man auch direkt Java Klassen verwenden und so den Code bzw. die Programmiersprachen mischen. In richtigen Projekten solltet ihr das nicht tun, weil es unnötige Komplexität erzeugt. Warum zeige ich es dann hier?
Kotlin ist für mich die nächste Evolutionsstufe und ich möchte zeigen wie einfach und risikofrei ihr diesen Schritt gehen könnt.

Kotlin und Java Code im Spring Boot Projekt gemischt

Java war zwar zuerst da, kann aber nicht als Ausgangspunkt verwendet werden. Wir benötigen ein Kotlin Projekt, da dieses den Kotlin Compiler, die Kotlin Bibliotheken und ein JDK beinhaltet. Ein solches Projekt könnt ihr mit Spring Boot erstellen, so wie ich es hier gezeigt habe:
kotlin-spring-api.html
Ohne Spring Boot ist es nicht so einfach passende Build-Konfigurationen zu erstellen, die Bytecode für die Kotlin- und Java-Klassen erstellen.

Verzeichnisse erstellen und Spring Component Scan konfigurieren 

Die Kotlin Sourcecode-Dateien befinden sich nun standardmäßig im Verzeichnis "src/main/kotlin". Für den Java Sourcecode habe ich ein 2. Verzeichnis erstellt, so wie es standardmäßig in Java basierten Spring Projekten existiert: "src/main/java". In beiden Verzeichnissen habe ich danach Packages mit gleichem Prefix "de.bsi" erstellt. Da wir unterschiedliche Sourcecode Basis-Verzeichnisse haben "src/main/kotlin" und "src/main/java", musste ich die Klasse mit der main-Methode zum Starten der Spring Anwendung minimal anpassen - ich habe im Attribut scanBasePackages der Annotation @SpringBootApplicationdie die verwendeten Packages bzw. den gemeinsamen Prefix "de.bsigesetzt, da ansonsten die Beans im "src/main/java" Verzeichnis nicht gefunden werden:

@SpringBootApplication(scanBasePackages = ["de.bsi"])
class RestKotlinApplication

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

Code bzw. Beans mischen

Als Beispiel zum Mischen von Kotlin und Java-Code, zeige ich euch einen Spring RestController in Kotlin, der eine Spring Bean per Constructor Injection injiziert bekommt. Weitere Details zu Dependency Injection mit Spring findet ihr hier: kernkonzepte-von-spring.html
@RestController
class MixedController(@Autowired val javaIdGenerator: IdGenerator,
@Autowired val kotlinPrefixGenerator: PrefixGenerator) {

@GetMapping("/id")
@ResponseStatus(HttpStatus.OK)
fun generateId() =
"KOTLIN:".plus(kotlinPrefixGenerator.generateId())
.plus("___JAVA:").plus(javaIdGenerator.generateId())

}
  • Alle hier verwendeten Annotationen habe ich in diesem Artikel vorgestellt:
    rest-json-apis-in-java-mit-spring.html
  • Im restlichen Kotlin-Code passiert auch nicht viel außergewöhnliches. Weitere Details zu Kotlin findet ihr hier: https://kotlinlang.org/docs/home.html
  • Die per Constructor Injection (@Autowired) injizierte Bean javaIdGenerator ist in Java geschrieben und sieht so aus:
@Component
public class IdGenerator {

private Integer prefix;

@PostConstruct
private void initPrefixAfterConstruction() {
this.prefix = new Random().nextInt(100);
}

public String generateId() {
String uuid = UUID.randomUUID().toString();
return String.format("%d_%s", this.prefix, uuid);
}

}
  • Auch in der Spring Bean IdGenerator gibt es keine Besonderheiten. Ich generiere eine Zufallszahl kleiner 100 als Prefix für die UUIDs, die in der Methode generateId generiert werden.
Mein Ziel war mit dieser Demo zu zeigen, dass Kotlin- und Java-Code im selben Projekt zusammen funktionieren. Ihr könnt euch davon überzeugen, indem ihr die Spring Boot Anwendung startet und mittels dieser URL testet: http://localhost:8080/id

Java Code in Kotlin umwandeln

Wenn ihr vermischten Code habt oder ein bestehendes Java-Projekt mit Kotlin weiterentwickeln wollt, bietet IntelliJ euch die Möglichkeit Java-Code in Kotlin-Code umzuwandeln. Das funktioniert automatisch und mit den von mir getesteten, einfachen Klassen auch sehr gut. Alles was ihr tun müsst ist die Java Klasse mit der rechten Maustaste anklicken und dann im Pop-Up Menu den Punkt "Convert Java File to Kotlin File" auswählen, den Rest mach IntelliJ.

Java-Klasse per Klick in Kotlin-Klasse konvertieren

Das Ergebnis der Konvertierung sieht dann so aus:
@Component
class IdGenerator {
private var prefix: Int? = null
@PostConstruct
private fun initPrefixAfterConstruction() {
prefix = Random().nextInt(100)
}

fun generateId(): String {
val uuid = UUID.randomUUID().toString()
return String.format("%d_%s", prefix, uuid)
}
}

Fazit

Mit diesem Artikel möchte ich euch ermutigen Kotlin in künftigen Projekten auszuprobieren. Ihr habt immer den Workaround "komplizierte" Klassen in Java zu schreiben und sie dann wie hier gezeigt in euren Kotlin-Klassen zu verwenden - umgekehrt funktioniert das natürlich auch. Alternativ könnt ihr sogar in Java entwickeln und dann nach Kotlin konvertieren lassen. Grundsätzlich denke ich aber, dass ihr euch relativ schnell (im Vergleich zu anderen Programmiersprachen) in Kotlin zurecht finden werden, wenn ihr bisher mit Java gearbeitet habt.

Den kompletten Code zu diesem Artikel findet ihr in GitHub:

Kommentare

Beliebte Posts aus diesem Blog

OpenID Connect mit Spring Boot 3

Authentifizierung in Web-Anwendungen mit Spring Security 6

Reaktive REST-Webservices mit Spring WebFlux