[Java - Spring Native] Use Gradle to compile Spring Boot Web app with Spring Native and GraalVM Java
Gradle, Spring Native and GraalVM Java
Spring Native provides support for compiling Spring applications to native executables using the GraalVM native-image compiler.
Compared to the Java Virtual Machine, native images can enable cheaper and more sustainable hosting for many types of workloads. These include microservices, function workloads, well suited to containers, and Kubernetes
Gradle is an open-source build automation tool focused on flexibility and performance. Gradle build scripts are written using a Groovy - https://groovy-lang.org/ or Kotlin - https://kotlinlang.org/ DSL. Read about Gradle features - https://gradle.org/features/ to learn what is possible with Gradle.
Sample Project Setup
The completed “RESTful Web Service” guide can be retrieved using the following commands:
git clone https://github.com/spring-guides/gs-rest-service
Validate Spring Boot version
Spring Native 0.11.1 only supports Spring Boot 2.6.2, so change the version if necessary.
Add the Spring AOT plugin
The Spring AOT plugin performs ahead-of-time transformations required to improve native image compatibility and footprint.
The plugin provides a number of options to customize the transformations, see spring-aot-configuration - https://docs.spring.io/spring-native/docs/current/reference/htmlsingle/#spring-aot-configuration for more details.
Enable native image support
Spring Boot’s Cloud Native Buildpacks - https://docs.spring.io/spring-boot/docs/2.6.2/reference/html/spring-boot-features.html#boot-features-container-images-buildpacks support lets you build a container for your Spring Boot application. The native image buildpack - https://github.com/paketo-buildpacks/native-image can be enabled using the
BP_NATIVE_IMAGE environment variable as follows:
tiny builder allows small footprint and reduced surface attack, you can also use base (the default) or full builders to have more tools available in the image for an improved developer experience.
Additional native-image arguments can be added using the
BP_NATIVE_IMAGE_BUILD_ARGUMENTS environment variable.
Freeze GraalVM version
By default, GraalVM versions will be upgraded automatically by Buildpacks to the latest release. You can explicitly configure Spring Boot Maven or Gradle plugins with a specific version of java-native-image buildpack which will freeze GraalVM version, see related versions mapping. For example, if you want to force using GraalVM 21.3.0, you can configure:
Configure your build to include the required repository for the spring-native dependency, as follows:
The Spring AOT plugin also requires a dedicated plugin repository in the pom.xml file for Maven and in the in the
settings.gradle(.kts) for Gradle.
Build the native application
On MacOS, it is recommended to increase the memory allocated to Docker to at least
8GB with allocation to more CPU core. On Microsoft Windows make sure to enable the Docker WSL 2 backend for better performance.
See How to assign more memory to docker container - Stack Overflow - https://stackoverflow.com/questions/44533319/how-to-assign-more-memory-to-docker-container/44533437#44533437 to learn more.
The native application can be built as follows:
This creates a executable file
This creates a Linux container to build the native application using the GraalVM native image compiler. By default, the container image is installed locally.
Run the native application
To run the application
Or you can use docker the usual way as shown in the following example:
docker run --rm -p 8080:8080 rest-service-complete:0.0.1-SNAPSHOT
If you prefer docker-compose, you can write a
docker-compose.yml at the root of the project with the following content:
And then run
The startup time should be less than 100ms, compared to the roughly 1500ms when starting the application on the JVM.
Now that the service is up, visit
http://localhost:8080/greeting, where you should see:
‘gu’ tool wasn’t found. This probably means that JDK at isn’t a GraalVM distribution.
JAVA_HOME env to GraalVM directory before run
See java - How do I tell Gradle to use specific JDK version? - Stack Overflow - https://stackoverflow.com/questions/18487406/how-do-i-tell-gradle-to-use-specific-jdk-version
Native reflection configuration for org.hibernate.dialect.PostgreSQLDialect is missing
org.hibernate.boot.registry.selector.spi.StrategySelectionException: Unable to resolve name [org.hibernate.dialect.PostgreSQLDialect] as strategy [org.hibernate.dialect.Dialect]
 GraalVM - https://www.graalvm.org/
 Spring Native documentation - https://docs.spring.io/spring-native/docs/current/reference/htmlsingle
 Spring Native: Getting started with GraalVM native images - https://www.thomasvitale.com/spring-native-graalvm-getting-started/
 spring-native-graalvm-demo/build.gradle at main · ThomasVitale/spring-native-graalvm-demo - https://github.com/ThomasVitale/spring-native-graalvm-demo/blob/main/build.gradle
 The Apache Groovy programming language - https://groovy-lang.org/
 Kotlin Programming Language - https://kotlinlang.org/
 Gradle | Gradle Features - https://gradle.org/features/
 Get Started with Docker | Docker - https://www.docker.com/get-started
 Overview of Docker Compose | Docker Documentation - https://docs.docker.com/compose/
 Reflection Use in Native Images | GraalVM - https://www.graalvm.org/reference-manual/native-image/Reflection/