Skip to main content

GraalVM support

Flamingock provides first-class support for GraalVM native images, so your application can compile into a fast, self-contained executable without losing change tracking, rollback, or template support.

This page covers two setups: a plain Java project with Gradle and a Spring Boot project using Spring Boot's Native Build Tools.

How it works

  • At compile time, the Flamingock annotation processor records the classes that need reflective access at runtime — your @Change classes, discovered templates, and their payload types.
  • The flamingock-graalvm artifact ships a GraalVM Feature (RegistrationFeature) together with a META-INF/native-image/native-image.properties descriptor. When the artifact is on the native-image classpath, GraalVM applies the feature automatically.
  • At native-image build time, the feature reads Flamingock's compile-time records and registers the required classes for reflection.

No hand-written reflect-config.json, no resource-config.json, and no --features=... flag are required.

tip

For a primer on GraalVM native images, see the GraalVM Native Image basics guide.

Setup: Spring Boot

When you use Spring Boot, prefer Spring Boot's Native Build Tools plugin. It produces the AOT artifacts Spring Boot needs and invokes native-image for you. Flamingock's feature is picked up automatically alongside Spring's contributions.

1. Apply the plugins

plugins {
java
id("org.springframework.boot") version "[SPRING_BOOT_VERSION]"
id("io.spring.dependency-management") version "[DEP_MGMT_VERSION]"
id("io.flamingock") version "[VERSION]"
id("org.graalvm.buildtools.native") version "[NATIVE_BUILDTOOLS_VERSION]"
}

2. Enable Flamingock GraalVM support

flamingock {
springboot()
graalvm()
// Add any template methods you use, e.g. sql(), mongodb(), etc.
}

Template methods are listed on the Gradle plugin page.

3. Build the native image

./gradlew nativeCompile

Spring Boot's AOT processing and Flamingock's GraalVM feature interoperate without additional configuration. For a container-based image, ./gradlew bootBuildImage works the same way.

4. Run the native image

./build/native/nativeCompile/your-app
JDK

Spring Boot pins to specific JDK and GraalVM versions for native image builds. Match your JDK to the Spring Boot version you are using; see Spring Boot's native image documentation for the supported combination.

tip

For more on image creation options, see the GraalVM build overview.

Setup: plain Java with Gradle

Use this path when your application does not depend on Spring Boot's AOT and Native Build Tools.

1. Apply the plugin and enable GraalVM support

plugins {
id("io.flamingock") version "[VERSION]"
}

flamingock {
community()
graalvm()
}

2. Configure the JAR

The native-image tool needs a runnable JAR that contains your application classes, your dependencies, and a Main-Class entry in the manifest. The simplest way in Gradle is to bundle everything into a single JAR:

tasks.withType<Jar> {
manifest {
attributes["Main-Class"] = "com.example.app.MyFlamingockApp"
}
duplicatesStrategy = DuplicatesStrategy.EXCLUDE

from(sourceSets.main.get().output)
from({
configurations.runtimeClasspath.get().map { if (it.isDirectory) it else zipTree(it) }
})
}

Then build:

./gradlew clean build

3. Create the native image

native-image \
--no-fallback \
-H:+ReportExceptionStackTraces \
-jar build/libs/your-app.jar

The flamingock-graalvm artifact contributes the feature registration automatically — you do not need to pass --features or supply a resource configuration.

--initialize-at-build-time

Flamingock itself does not require any build-time initialization. If your logging library benefits from it (for example, slf4j-simple), add the relevant entries — but only for that purpose. Omit if unsure.

4. Run the native image

./build/native-image/your-app

Troubleshooting

ClassNotFoundException for a @Change class at runtime

Usually means the annotation processor did not see the class at build time. Most common cause: the project was first compiled before flamingock-graalvm was on the classpath, or the Flamingock version was bumped without a clean build.

  1. Run a clean build: ./gradlew clean build (or mvn clean install).
  2. Rebuild the native image.

This is also the one-time clean build required when upgrading to Flamingock 1.3.0+.

No Flamingock registration log during the native-image build

If you do not see lines starting with [Flamingock] Starting GraalVM classes registration, the feature was not picked up by native-image.

  1. Verify that flamingock-graalvm is declared as implementation (not runtimeOnly) so it appears on the native-image classpath.
  2. Confirm the dependency is present in the artifacts passed to nativeCompile or to the native-image command.

Reflection errors about Flamingock internals during nativeCompile

Typically a version mismatch between flamingock-graalvm and flamingock-core. Pin both via flamingock-bom so they upgrade in lockstep.

Native image build fails with logging-library errors

Flamingock itself does not require build-time initialization. Some logging libraries do.

  1. Identify the offending classes from the error (often org.slf4j.* or ch.qos.logback.*).
  2. Add the corresponding --initialize-at-build-time (or --initialize-at-run-time) entries for your logger.
  3. For slf4j-simple, this typically looks like --initialize-at-build-time=org.slf4j,org.slf4j.impl,org.slf4j.simple.