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
@Changeclasses, discovered templates, and their payload types. - The
flamingock-graalvmartifact ships a GraalVMFeature(RegistrationFeature) together with aMETA-INF/native-image/native-image.propertiesdescriptor. 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.
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
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.
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
- Gradle
- Maven
plugins {
id("io.flamingock") version "[VERSION]"
}
flamingock {
community()
graalvm()
}
Add the runtime dependency. The Flamingock annotation processor must also be configured — see the Quick start for the full Maven setup.
<dependency>
<groupId>io.flamingock</groupId>
<artifactId>flamingock-graalvm</artifactId>
<version>${flamingock.version}</version>
</dependency>
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-timeFlamingock 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.
- Run a clean build:
./gradlew clean build(ormvn clean install). - 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.
- Verify that
flamingock-graalvmis declared asimplementation(notruntimeOnly) so it appears on the native-image classpath. - Confirm the dependency is present in the artifacts passed to
nativeCompileor to thenative-imagecommand.
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.
- Identify the offending classes from the error (often
org.slf4j.*orch.qos.logback.*). - Add the corresponding
--initialize-at-build-time(or--initialize-at-run-time) entries for your logger. - For
slf4j-simple, this typically looks like--initialize-at-build-time=org.slf4j,org.slf4j.impl,org.slf4j.simple.