Quarkus - Using Kotlin
Kotlin is a very popular programming language that targets the JVM (amongst other environments). Kotlin has experienced a surge in popularity the last few years making it the most popular JVM language, except for Java of course.
Quarkus provides first class support for using Kotlin as will be explained in this guide.
Prerequisites
To complete this guide, you need:
-
less than 10 minutes
-
an IDE
-
JDK 1.8+ installed with
JAVA_HOME
configured appropriately -
Apache Maven 3.5.3+
Creating the Maven project
First, we need a new Kotlin project. This can be done using the following command:
mvn io.quarkus:quarkus-maven-plugin:0.12.0:create \
-DprojectGroupId=org.acme \
-DprojectArtifactId=rest-kotlin \
-DclassName="org.acme.rest.GreetingResource" \
-Dpath="/greeting" \
-Dextensions="kotlin"
When adding kotlin
to the extensions list, the Maven plugin will generate a project that is properly
configured to work with Kotlin. Furthermore the org.acme.rest.GreetingResource
class is implemented as Kotlin source code (as is the case with the generated tests).
GreetingResource.kt
looks like this:
package org.acme.rest
import javax.ws.rs.GET
import javax.ws.rs.Path
import javax.ws.rs.Produces
import javax.ws.rs.core.MediaType
@Path("/greeting")
class GreetingResource {
@GET
@Produces(MediaType.TEXT_PLAIN)
fun hello() = "hello"
}
Important configuration points
The generated pom.xml
contains the following modifications compared to its counterpart when Kotlin is not selected:
-
The
quarkus-kotlin
artifact is added to the dependencies. This artifact provides support for Kotlin in the live reload mode (more about this later on) -
The
kotlin-stdlib-jdk8
is also added as a dependency. -
Maven’s
sourceDirectory
andtestSourceDirectory
build properties are configured to point to Kotlin sources (src/main/kotlin
andsrc/test/kotlin
respectively) -
The
kotlin-maven-plugin
is configured as follows:
<plugin>
<artifactId>kotlin-maven-plugin</artifactId>
<groupId>org.jetbrains.kotlin</groupId>
<version>${kotlin.version}</version>
<executions>
<execution>
<id>compile</id>
<goals>
<goal>compile</goal>
</goals>
</execution>
<execution>
<id>test-compile</id>
<goals>
<goal>test-compile</goal>
</goals>
</execution>
</executions>
<configuration>
<compilerPlugins>
<plugin>all-open</plugin>
</compilerPlugins>
<pluginOptions>
<!-- Each annotation is placed on its own line -->
<option>all-open:annotation=javax.ws.rs.Path</option>
</pluginOptions>
</configuration>
<dependencies>
<dependency>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-maven-allopen</artifactId>
<version>${kotlin.version}</version>
</dependency>
</dependencies>
</plugin>
The important thing to note is the use of the all-open Kotlin compiler plugin.
In order to understand why this plugin is needed, first we need to note that by default all the classes generated from the Kotlin compiler are marked as final
.
Having final
classes however does not work well with various frameworks that need to create Dynamic Proxies.
Thus, the all-open
Kotlin compiler plugin allows us to configure the compiler to not mark as final
classes that have certain annotations. In the snippet above,
we have specified that classes annotated with javax.ws.rs.Path
should not be final
.
If your application contains classes annotated with javax.enterprise.context.ApplicationScoped
for example, then <option>all-open:annotation=javax.enterprise.context.ApplicationScoped</option>
needs to be added as well. Same goes for any class that needs to have a dynamic proxy created at runtime.
Future versions of Quarkus will configure the Kotlin compiler plugin in a way that will make it unnecessary to alter this configuration.
Live reload
Quarkus provides support for live reloading changes made to source code. This support is also available to Kotlin, meaning that developers can update their Kotlin source code and immediately see their changes reflected.
To see this feature in action, first execute: ./mvnw compile quarkus:dev
When executing an HTTP GET request against http://localhost:8080/greeting
, you should get hello
as a response.
Now using your favorite editor or IDE, update GreetingResource.kt
and change the hello
method to the following:
fun hello() = "hi"
When you now execute an HTTP GET request against http://localhost:8080/greeting
, you should see hi
as a response.
One thing to note is that the live reload feature is not available when making changes to both Java and Kotlin source that have dependencies on each other. We hope to alleviate this limitation in the future.