Quarkus with Kotlin
Java is everywhere and we can use it for anything, but it’s not always the best choice. Quarkus wants to make it default choice when it comes to the cloud and in my opinion it’s doing a very good job so far: we get native binaries for kubernetes with very fast startup, low memory consumption and with a bunch of very useful libs you already know from other projects out of the box.
I heard about Quarkus something like two months ago and since then I’ve wanted to give it a try. Especially because they advertised that I could write my code in Kotlin. My first idea was to compare it with most popular Spring Boot so I started with some plain apps. Well - not that plain to be honest but really minimal - a small rest applications. Both Spring Boot and Quarkus have their own initializer pages (here and here) that work in a similar way - you choose what you need to start with and you get it. After a few clicks you get your project in your favourite IDE and start the fun.
The good, the bad and the gradle
I wanted to make things a bit more complicated and wanted to try Quarkus with Kotlin and Gradle (by default from Quarkus initializer we get Java with Maven). In such case we need to rememeber about these things:
- kotlin classes are final by default (you can use allopen extension to open some of them)
- set proper source and output dirs
- enable HTTP URL handler for buildNative task (and you may need to set the proper GraalVM path - for some reason Gradle plugin has problems with getting it from environment variables)
The minimal Gradle build script looks like this:
One thing I personally liked about Quarkus from the first lines of code was hot-reloading. You start your app with
./gradlew quarkusDev and in browser (or whatever tool you are using) you always see the latest version. Not that difficult to achieve with any java app but well - you get it out of the box (with the hacker-ish code feel).
The very minimal quarkus app can look like this:
As you see - there is nothing Quarkus specific - very basic rest app with CDI and JAX-RS. But when it comes to building native images - the GraalVM analyzes the call tree and removes all the classes, methods and fields that are not used directly, so e.g. when some classes are used via reflection they need to be annotated with @RegisterForReflection or information about them needs to be put into reflection-config.json file - see here for more details on this subject.
Similar app in Spring Boot would look like this:
Let’s compare startup times. On my machine (Intel(R) Core(TM) i5-7200U CPU @ 2.50GHz, 16G RAM) I got (all values are in ms):
- Quarkus dev mode 628
- Native build 4
- Spring Boot 2714
Of course this is because of the amount of stuff thet’s happening at startup and amount of libs included - we all know Spring Boot is pretty heavy, but Quarkus can build native binaries and they are extremely fast - one of reasons is of course mentioned removal of not used classes, methods and fields at build time. Still - this is very impressive for a java app.
And now for something completely different
To add a bit complexity I’ve created two more apps - JDBC and JPA based.
Below are the numbers we’ll get when we compare startup times of the first one that additionaly does a small import at startup. All sources are here.
- Quarkus dev mode 1531
- Native build 33
- Spring Boot 3875
And here are startup times of a JPA app:
- Quarkus dev mode 2847
- Native build 15
- Spring Boot 5294
Nobody expects… AWS Lambda
Since the native apps start that fast let’s try to write a lambda and deploy it in the AWS cloud! That’s pretty easy too. You just need a lambda:
And a serverless config file (well, you’ll need also an AWS account but I guess you’ve figured that out already):
And when you navigate to AWS X-Ray you will see some really small numbers:
Just comapre to similar very minimal java lambda:
Quarkus is not yet production ready - but I think it is already pretty impresive. Of course the main problem are the libs that work with GraalVM - the ones provided with Quarkus of course do work, but you can’t take any lib - if you do your app just might and probably will crash at runtime. You are limited to what Quarkus gives you - fortunately the list is not that short.
All source code is on our official Github repo.