Introduction

As I get more into DevOps,Containers and Serverless; I find myself writing my containerized code in lightweight containers or FaaS using Python or JavaScript. Java it is just too slow to boot up to use in a Serverless framework and for microservices JavaScript or Python have faster boot times and smaller container size than Java making them more efficient.

Python and JavaScript are the best languages for cloud native microservices

Java is more than 20 years old, the world back them was vastly different from what is now. The JVM solved a huge problem and allowed us to write code once and run it in multiple platforms and operating systems. With Containers we can now package our apps, libs and OS resources into a single container that can run anywhere. The JVM portability is now less relevant. Back in the day, the extra overhead was a cost that we were willing to pay for portability, but not anymore. Now we want fast, low latency and reactive applications that are always available. Containers and container orchestration tools like Kubernetes provide this independently of the programming language.

As companies migrate to microservices, they take their Spring Java services, bundle them into a fat jars, add the JDK and run it in a Linux based container. This solution works but you have to manage heavy weight containers that are 500MB in size and take 10 to 30 seconds to be available; and this is a problem. Many companies after migrating, they slowly move to Python or Java for their backend services; and eventually, to FaaS. Serverless and FaaS are now very popular because allow us to focus on writing functions without worrying about the infrastructure. They still run inside containers but the cloud provider manage its life cycle. The neat thing is that after certain time, the cloud provider will kill completely the container and start it again on the next call, so you only pay for the usage. The first call to a function may take a bit longer, this is the famous cold start. This is happens because the container needs to boot up. With Python or JavaScript this is not a huge problem, but for Java this could be 10–15 seconds which is a deal breaker and the cause of the decline in Java. Now we need code that can run, do its job and then stop. We don’t want multiple threads or long running processes, we want short lived processes that can boot very quickly.

Introducing Quarkus

If you read tech blogs or follow the news, you may think that Serverless is eating the world, everybody is super excited about it. Startups can now write functions as a service in the cloud using JavaScript and scale them to support millions of users without having to manage any infrastructure. Then, you have the real word, outside Silicon Valley; financial institutions, government, retail and many other industries which have millions of lines of code written in Java which they cannot afford to rewrite, so they kind of accept the fact that they need to live with heavy weight containers.

GraalVM and specifically Substrate VM are now opening the door for a bright and long future for the Java language. GraalVM is a universal virtual machine for running applications written in JavaScript, Python, Ruby, R, JVM-based languages like Java, Scala or Kotlin. The cool thing is that GraalVM allows you to compile your programs ahead-of-time(AOT) into a native executable. This means, that you can compile your Java code directly into a machine specific code. The resulting program does not run on the Java HotSpot VM, but uses necessary components like memory management, thread scheduling from a different implementation of a virtual machine, called Substrate VM. Substrate VM is written in Java and compiled into the native executable. The resulting program has faster startup time and lower runtime memory overhead compared to a Java VM. This is great, but you may be thinking, AOT? this is against the whole idea of having the JVM, this is Java code that I cannot run anywhere!, this is crazy!!!. But think about it, we have containers now, we don’t need the JVM. The common container based Spring boot apps have an extra level of abstraction which is completely unnecessary in the world of Kubernetes. You have a Java app running on JVM inside a container, this container will never change, since the deliverable nowadays is the container not the app, you package containers and not WARs anymore. So, all the overhead of running the app in a JVM inside a container is useless, so AOT makes perfect sense if you are going to package your apps in containers.

However, the dynamic nature of Java is severely constrained by AOT compiling (class loading at runtime, reflection, proxies, etc). In practice, it means 90% of the Java ecosystem does not work without change. So the Java ecosystem must adapt. The good news is that we can do most of them at build time!

This is the power of Quarkus. It uses GraalVM and provides an ecosystem that supports AOT at build time, so you can create native binaries using Java. Quarkus makes GraalVM usable for Java developers!

Getting Started with Quarkus

As explained above, Quarkus provides ahead of time compiling for Java applications creating a Supersonic Subatomic Java ecosystem that has a extremely small size and super fast boot time, bringing Java back in the game for cloud native development. I have never been as excited about a new technology in years, and I’m not the only one.

Try the getting started guide to see it for yourself. Follow the 3 guides to see the power of Quarkus and mesure the boot time. There are still thousands of companies are there that use Java+JPA, inside a container, this can take 15 seconds to boot, in Quarkus 0.005!

Quarkus stats

You use the same IDE and tooling as you are used to in the Spring Boot world. You use Maven or Gradle to build your project. You can run it directly in the IDE, and on top of that, you have hot live reload of any changes, no need to restart the app. Quarkus it is not Spring, so if you are using Spring Boot you will need to migrate the Spring specific code, fortunately, Quarkus comes with a Spring DI compatibility layer that makes this very easy. The Quarkus framework is based on standards which means that the code will be portable and easy to maintain.

Quarkus Development Process

Quarkus can run in dev mode which is similar to Spring Boot, you can also package you project into fat jars. This is great to test your code and debug since it support live reload; but for prod ahead of time compiling is required. The diagram below shows the process:

First you build your app in your favorite IDE, you can run it in dev mode using: “mvnw compile quarkus:dev” like a Spring Boot app, you can also package into a fat jar.

Once you are happy, you are ready to create a Java binary!, just run: “mvnw package -Pnative”, this will take some time since is doing ahead of time compiling creating native code!, once is done, you will have a binary that is super small and fast but can run only on your platform/OS, so it is not portable! but this is okay because we can put it inside a container and then it will be portable!. Use: ./mvnw package -Pnative -Dnative-image.docker-build=true to produce an executable from inside a Docker container, which means we do the native build inside a container and create the binary, this may not run in your laptop if you don’t have the same platform as the target container as specified int he DockerFile that is generated by Quarkus during project creation.

to produce an executable from inside a Docker container, which means we do the native build inside a container and create the binary, this may not run in your laptop if you don’t have the same platform as the target container as specified int he DockerFile that is generated by Quarkus during project creation. Then, once we have the binary, we just need create the image from the docker file. docker build -f src/main/docker/Dockerfile.native -t quarkus-quickstart/quickstart .

Finally you can run it in Docker or Kubernetes: docker run -i --rm -p 8080:8080 quarkus-quickstart/quickstart

Quarkus Features

Quarkus has a lot more features that just native Java code.

Unifies Imperative and Reactive: Combine both the familiar imperative code and the non-blocking reactive style when developing applications, so you can use reactive programming or classic imperative.

Reactive End point

Developer Joy: Unified configuration, Zero config, live reload in the blink of an eye, Streamlined code for the 80% common usages, flexible for the 20%, No hassle native executable generation, live coding.

Amazingly fast boot time, incredibly low RSS memory (not just heap size!) offering near instant scale up and high density memory utilization in container orchestration platforms like Kubernetes. Learn more.

Quarkus brings a cohesive, fun to use full-stack framework by leveraging best of breed libraries you love and use wired on a standard backbone. Learn more.

It support libraries such Hibernate, JPA, REST, JWT, etc.

Support Kubernetes and OpenShift deployments

and deployments Open Tracing using Jaeger

Kotlin Support

Support Messaging using Kafka , Camel…

, Camel… And much more, check the list of extensions!

Quarkus Ecosystem

In short, now you can run your traditional JPA/JTA transactional services in super fast lightweight containers in any environment, cloud or on-prem.

Quarkus Example

In this section, lets simplify the getting started guide to get an idea of the power of Quarkus.

The easiest way to create a new Quarkus project is to open a terminal and run the following command:

mvn io.quarkus:quarkus-maven-plugin:0.12.0:create \

-DprojectGroupId=org.acme \

-DprojectArtifactId=getting-started \

-DclassName="org.acme.quickstart.GreetingResource" \

-Dpath="/hello"

It generates a Maven project with a GreetingResuce exposing /hello end point. It also generates a Dockerfile for native and jvm(fat jar traditional images) docker images. The code is very clean and simple:

@Path("/hello")

public class GreetingResource { @GET

@Produces(MediaType.TEXT_PLAIN)

public String hello() {

return "hello";

}

}

To run our application. Use: ./mvnw compile quarkus:dev

The application is packaged using ./mvnw package . It produces 2 jar files:

getting-started-1.0-SNAPSHOT.jar - containing just the classes and resources of the projects, it’s the regular artifact produced by the Maven build;

- containing just the classes and resources of the projects, it’s the regular artifact produced by the Maven build; getting-started-1.0-SNAPSHOT-runner.jar - being an executable jar. Be aware that it’s not an über-jar as the dependencies are copied into the target/lib directory.

You can run the application using: java -jar target/getting-started-1.0-SNAPSHOT-runner.jar

Then, you need to download and install GraalVM and set GRAALVM_HOME environment variable.

Now you can create a native executable using: ./mvnw package -Pnative -Dnative-image.docker-build=true .

The create the Docker image: docker build -f src/main/docker/Dockerfile.native -t quarkus-quickstart/quickstart .

Now you can run it in any container orchectration engine, in case you use minishift:

kubectl run quarkus-quickstart --image=quarkus-quickstart/quickstart:latest --port=8080 --image-pull-policy=IfNotPresent

kubectl expose deployment quarkus-quickstart --type=NodePort

And that’s it!; you have a container with a Java REST service booting up in 0.004 seconds!

Conclusion

I’m really excited about Quarkus which is supported by Red Hat and has gotten lots of attention since its release just a week ago. I do believe it is going to change the Java landscape and make possible a real migration to the cloid for regular enterprises.

Kubernetes + Knative + Quarkus are a game changer for cloud native development and a joy for any Java developer.

Checkout this GIT Repo with lots of examples!