Running Reactive Spring Boot on GraalVM in Docker
By: Maarten Smeets
Tags: Docker, R, Llvm, Graalvm, Spring Boot

The reactive Spring Boot RESTful web service and client

When looking at the sample, you can see how you can implement a non-blocking web service and client. Basically this means you use;

org.springframework.web.reactive.function.server.ServerRequest and ServerResponse and instead of the org.springframework.web.bind.annotation.RestController

Mono<ServerResponse> for the response of the web service

for a web service client you use org.springframework.web.reactive.function.client.ClientResponse and Mono<ClientResponse> for getting a response

since you won’t use the (classic blocking) RestController with the RequestMapping annotations, you need to create your own configuration class which defines routes using org.springframework.web.reactive.function.server.RouterFunctions

Since the response is not directly a POJO, it needs to be converted into one explicitly like with res.bodyToMono(String.class). For more details look at this tutorial or browse this repository

Personally I would have liked to have something like a ReactiveRestController and keep the rest (pun intended) the same. This would make refactoring to reactive services and clients more easy.

GraalVM

GraalVM is a polyglot VM open sourced by Oracle. It has a community edition and enterprise edition which provides improved performance (a smaller footprint) and better security (sandboxing capabilities for native code) as indicated here. The community edition can be downloaded from GitHub and the enterprise edition from Oracle’s Technology Network. Support for GraalVM for Windows is currently still under development and not released yet. A challenge for Oracle with GraalVM will be to keep the polyglot systems it supports up to date version wise. This already was a challenge with for example the R support in Oracle database and Node support in Application Container Cloud Service. See here.

When you download GraalVM CE you’ll get GraalVM with a specific OpenJDK 8 version (for GraalVM 1.0.0-rc8 this is 1.8.0_172). When you download GraalVM EE from OTN, you’ll get Oracle JDK 8 of the same version.

To see which components are available, you can do:

bash-4.2# gu available

Downloading: Component catalog

ComponentId Version Component name

— — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — —

python 1.0.0-rc8 Graal.Python

R 1.0.0-rc8 FastR

ruby 1.0.0-rc8 TruffleRuby

GraalVM and LLVM

GraalVM supports LLVM. LLVM is a popular toolset to provide language agnostic compilation and optimization of code for specific platforms. LLVM is one of the reasons many programming languages have starting popping up recently. Read more about LLVM here or visit their site here. If you can compile a language into LLVM bitcode or LLVM Intermediate Representation (IR), you can run it on GraalVM (see here). The LLVM bitcode is additionally optimized by GraalVM to receive even better results.

GraalVM and R

GraalVM uses FastR which is based on GNU-R, the reference implementation of R. This is an alternative implementation of the R language for GraalVM and thus not actual R! For example: ‘support for dplyr and data.table are on the way’. Read more here. Especially if you use exotic packages in R, I expect there to be compatibility issues. It is interesting to compare the performance of FastR on GraalVM to compiling R code to LLVM instructions and run that on GraalVM (using something like RLLVMCompile). Haven’t tried that though. GraalVM seems to have momentum at the moment and I’m not so sure about RLLVMCompile.

Updating the JVM of GraalVM

You can check out the following post here for building GraalVM with a JDK 8 version. This refers to documentation on GitHub here.

Graal depends on a JDK that supports a compatible version of JVMCI (JVM Compiler Interface). There is a JVMCI port for JDK 8 and the required JVMCI version is built into the JDK as of JDK 11 (build 20 or later).

I have not tried this but it seems thus relatively easy to compile GraalVM from sources with support for a different JDK.

GraalVM in Docker

Oracle has recently provided GraalVM as Docker images and put the Dockerfile’s in their Github repository. See here. These are only available for the community edition. Since the Dockerfiles are provided on GitHub, it is easy to make your own GraalVM EE images if you want (for example want to test with GraalVM using Oracle JDK instead of OpenJDK).

To checkout GraalVM you can run the container like:

docker run -it oracle/graalvm-ce:1.0.0-rc8 bash

Spring Boot in GraalVM in Docker

How to run a Spring Boot application in Docker is relatively easy and described here. I’ve run Spring Boot applications on various VM’s also and described the process on how to achieve this here. As indicated above, I’ve used this Ubuntu Development VM.



git clone

cd gs-reactive-rest-service/complete sudo apt-get install mavengit clone https://github.com/spring-guides/gs-reactive-rest-service.git cd gs-reactive-rest-service/complete

Now create a Dockerfile:

FROM oracle/graalvm-ce:1.0.0-rc8

VOLUME /tmp

ARG JAR_FILE

COPY ${JAR_FILE} app.jar

ENTRYPOINT [“java”,”-Djava.security.egd=file:/dev/./urandom”,”-jar”,”/app.jar”]

Edit the pom.xml file

Add to the properties tag a prefix variable:

<properties>

<java.version>1.8</java.version>

<docker.image.prefix>springio</docker.image.prefix>

</properties>

Add a build plugin

<build>

<plugins>

<plugin>

<groupId>org.springframework.boot</groupId>

<artifactId>spring-boot-maven-plugin</artifactId>

</plugin>

<plugin>

<groupId>com.spotify</groupId>

<artifactId>dockerfile-maven-plugin</artifactId>

<version>1.3.6</version>

<configuration> <repository>${docker.image.prefix}/${project.artifactId}</repository>

<buildArgs><JAR_FILE>target/${project.build.finalName}.jar</JAR_FILE></buildArgs>

</configuration>

</plugin>

</plugins>

</build>

Now you can do:

mvn clean package

mvn dockerfile:build

And run it:

docker run -p 8080:8080 -t springio/gs-reactive-rest-service:latest

It’s as simple as that!