Gradle plugin reference
The io.stoatflow convention plugin encapsulates StoatFlow's build conventions: the JDK 25 toolchain, the required preview + native-access JVM flags, a runnable fat JAR, and opt-in Docker (Jib) and GraalVM native-image builds. Configure it through the typed stoatflow { } extension (Kotlin DSL). For the Maven equivalent — the same conventions via a parent POM — see the Maven reference.
Apply it after registering the plugin-marker repository — see Project setup and Installation.
// build.gradle.kts
plugins {
kotlin("jvm") version "2.4.0" // omit for a Java-only project
id("io.stoatflow") version "<stoatflow-version>"
}
stoatflow {
mainClass.set("com.example.MainKt")
}
The current release is 1.0.0-alpha.16 — substitute it for the <stoatflow-version> placeholder.
Extension DSL
The plugin registers a stoatflow { } extension. The full surface, with every default:
stoatflow {
mainClass.set("com.example.MainKt") // default: unset
docker {
enabled.set(true) // default: false
imageName.set("my-app") // default: project.name
port.set(8080) // default: 8080
user.set("1000:1000") // default: 1000:1000
baseImage.set("eclipse-temurin:25-jre-noble") // default shown (JVM/Jib only)
stateDir.set("/data/state") // default: /data/state
rocksdbMb.set(256) // default: auto-detect (see below)
reproducibleBuild.set(true) // default: true
jvmFlags.set(listOf("-XX:+UseG1GC")) // overridable; preview/native-access always added
}
nativeImage {
enabled.set(true) // default: false
gc.set("G1") // default: absent (Serial GC)
runtimeTarget.set("runtime") // default: runtime; or "runtime-lean"
additionalInitializeAtRunTime.add("com.example.MyClass")
removeInitializeAtRunTime.add("org.rocksdb.RocksDB")
}
}
stoatflow { }
| Property | Type | Default | Description |
|---|---|---|---|
mainClass | Property<String> | (unset) | Application entry point. Wired as a lazy provider into the application plugin's mainClass, the shadow-jar Main-Class manifest attribute, and (when enabled) the Docker and native-image main class. Required for a runnable JAR or any image. |
docker { } | nested | — | Opt-in Jib Docker image build. See below. |
nativeImage { } | nested | — | Opt-in GraalVM native-image build. See below. |
docker { }
| Property | Type | Default | Description |
|---|---|---|---|
enabled | Property<Boolean> | false | When true, applies the Jib plugin and the StoatFlow image conventions. |
imageName | Property<String> | project.name | Target image name. Tagged latest and <project.version>. |
port | Property<Int> | 8080 | Exposed container port (the runtime's HTTP admin / metrics server). |
user | Property<String> | 1000:1000 | Non-root run-as user (uid:gid). |
baseImage | Property<String> | eclipse-temurin:25-jre-noble | JVM base image (JVM/Jib path only; the native runtime base stays distroless). |
stateDir | Property<String> | /data/state | RocksDB state directory; set as STOATFLOW_STATE_DIR. Mount a volume here. |
rocksdbMb | Property<Int> | auto-detect | Off-heap RocksDB reservation (MiB) → STOATFLOW_ROCKSDB_MB. Unset = 256 if RocksDB is on the runtime classpath, else the env var is omitted; 0 always omits it; an explicit value always wins. |
reproducibleBuild | Property<Boolean> | true | Pins the image creationTime to the HEAD commit timestamp. false = wall-clock (USE_CURRENT_TIMESTAMP). |
jvmFlags | ListProperty<String> | ["-XX:+UseG1GC"] | Container JVM flags. Overridable — but --enable-preview and --enable-native-access=ALL-UNNAMED are always added on top. |
nativeImage { }
| Property | Type | Default | Description |
|---|---|---|---|
enabled | Property<Boolean> | false | When true, applies the GraalVM native-build plugin and registers the nativeDockerBuild task. |
gc | Property<String> | absent | GC algorithm, passed as --gc=<value>. Absent = the native image default (Serial GC). Set "G1" for stateful (RocksDB) workloads — G1 needs Oracle GraalVM. |
runtimeTarget | Property<String> | runtime | Docker target stage for nativeDockerBuild (--target): runtime (busybox distroless + container-aware heap entrypoint) or runtime-lean (minimal distroless, no heap entrypoint — SubstrateVM sizes the heap itself). |
additionalInitializeAtRunTime | ListProperty<String> | [] | Extra fully-qualified class names added to the curated --initialize-at-run-time base. |
removeInitializeAtRunTime | ListProperty<String> | [] | Curated --initialize-at-run-time entries to drop — lets a consumer remove a problematic entry without forking the plugin. |
What the plugin applies
Applied unconditionally on every project the plugin is added to:
| Concern | Effect |
|---|---|
application plugin | Applied. mainClass wired from the extension; applicationDefaultJvmArgs set to the preview JVM args (below). |
com.gradleup.shadow plugin | Applied. Configures ShadowJar with archiveClassifier = "all", mergeServiceFiles(), and a Main-Class manifest attribute (from mainClass). |
| Java toolchain | JavaLanguageVersion.of(25). |
| Kotlin toolchain | jvmToolchain(25) — applied (reflectively) only when the org.jetbrains.kotlin.jvm plugin is present. The Kotlin Gradle plugin is not bundled; you bring your own. |
JavaCompile tasks | --enable-preview added to compiler args on every JavaCompile task. |
test task | JUnit Platform with the IntegrationTest tag excluded; the test JVM args (below) applied. |
integrationTest task | Registered (when the java plugin is present); runs only @Tag("IntegrationTest") tests, after test. |
JVM args
| Context | Flags |
|---|---|
Application run (applicationDefaultJvmArgs) and Docker container | --enable-preview, --enable-native-access=ALL-UNNAMED, plus docker { jvmFlags } (default -XX:+UseG1GC) |
Test tasks (test, integrationTest) | --enable-preview, --enable-native-access=ALL-UNNAMED, -Dnet.bytebuddy.experimental=true |
--enable-preview is required because StoatFlow builds on JDK preview features; --enable-native-access=ALL-UNNAMED is required because RocksDB's state store uses the Foreign Function & Memory API. See Installation for the rationale behind -XX:+UseG1GC.
Tasks the plugin contributes
| Task | Group | Available when | Purpose |
|---|---|---|---|
run | application | always (from application) | Runs the app with the preview JVM args. |
shadowJar | shadow | always (from shadow) | Builds the runnable fat JAR (-all classifier, merged service files, Main-Class manifest). |
integrationTest | verification | the java plugin is present | Runs JUnit Platform tests tagged IntegrationTest (Docker / Testcontainers). Runs after test. |
copyStoatFlowEntrypoint | (none) | docker.enabled = true | Stages the container-aware heap entrypoint into the Jib extra directory. All jib* tasks depend on it. |
jib, jibDockerBuild, jibBuildTar | — | docker.enabled = true (from Jib) | Build the image. jibDockerBuild targets the local Docker daemon. |
nativeDockerBuild | build | nativeImage.enabled = true | Builds a native image inside Docker from the prebuilt fat JAR, against the bundled generic Dockerfile.native (staged into build/stoatflow-native/). Tags <imageName>:native and <imageName>:<version>-native. |
nativeCompile, nativeRun | — | nativeImage.enabled = true (from GraalVM) | Build / run the native image directly on the host GraalVM toolchain. |
docker.enabled and nativeImage.enabled are read in a single afterEvaluate (the only deferral the plugin needs), because they're set in the build-script body — the Jib and GraalVM plugins are applied only when the corresponding flag is true. mainClass and the ShadowJar Main-Class are wired as lazy providers, not in afterEvaluate.Docker image defaults
When docker.enabled = true, the Jib build is configured with:
| Aspect | Value |
|---|---|
| Base image | baseImage (default eclipse-temurin:25-jre-noble) |
| Platform | linux/arm64 on aarch64 hosts, otherwise linux/amd64 |
| Target image | imageName (or project.name), tagged latest and project.version |
creationTime | HEAD commit timestamp when reproducibleBuild = true (default), else wall-clock |
| Entrypoint | /app/stoatflow-entrypoint.sh (bundled container-aware heap script) |
| Working directory | /app |
| Exposed port | port (default 8080) |
| User | user (default 1000:1000) |
| JVM flags | --enable-preview, --enable-native-access=ALL-UNNAMED, + docker { jvmFlags } |
Env: STOATFLOW_STATE_DIR | stateDir (default /data/state) |
Env: STOATFLOW_ROCKSDB_MB | rocksdbMb, or 256 when RocksDB is auto-detected on the runtime classpath (omitted otherwise) |
jibDockerBuild is not CC-compatible — an upstream jib-gradle-plugin limitation, not StoatFlow's. Run docker builds without --configuration-cache.See Docker for the full container guide.
Native image defaults
When nativeImage.enabled = true, the GraalVM build is configured from the bundled native-image.args (the single source of truth, identical for Gradle, Maven, and the containerized build), plus the dynamic gc / add / remove deltas:
| Aspect | Value |
|---|---|
| Toolchain detection | enabled |
| Static build args | -H:+JNI, -H:+ReportExceptionStackTraces, -H:+AddAllCharsets, the Kotlin resource includes (*.kotlin_builtins, META-INF/*.kotlin_module), --enable-preview, --no-fallback |
--initialize-at-run-time | org.rocksdb, org.rocksdb.RocksDB, org.rocksdb.util.Environment, io.stoatflow.core.state.rocksdb.backend.ffm.FfmRocksDbNative, org.apache.kafka.common.security.authenticator.SaslClientAuthenticator — plus additionalInitializeAtRunTime, minus removeInitializeAtRunTime |
--gc | added only when nativeImage { gc } is set |
SOURCE_DATE_EPOCH | HEAD commit timestamp when reproducibleBuild = true |
| Runtime stage | --target from runtimeTarget (default runtime) |
The nativeDockerBuild task tags the resulting image <imageName>:native and <imageName>:<version>-native. See Native image for the full guide.
Version compatibility
The plugin pins the build tools it bundles. As of 1.0.0-alpha.16 the pins are:
| Tool | Version |
|---|---|
| Gradle | 9.5+ (developed and tested on 9.6.1) |
Shadow (com.gradleup.shadow) | 9.4.3 |
Jib (com.google.cloud.tools.jib) | 3.5.2 |
GraalVM Native (org.graalvm.buildtools.native) | 1.1.3 |
| Kotlin Gradle plugin | 2.4.0 (you bring your own; the plugin doesn't bundle it) |
Related
- Project setup — applying the conventions in a fresh project (Gradle or Maven).
- Maven reference — the same conventions for Maven projects.
- Docker — building and running the container image.
- Native image — ahead-of-time compilation with GraalVM.
REST API reference
Every HTTP endpoint the StoatFlow runtime exposes — path, method, purpose, response shape, content negotiation, status codes, and gating.
Maven reference
StoatFlow's Maven support — the stoatflow-bom, the stoatflow-parent convention POM, and the stoatflow-maven-plugin. The three artifacts, every <properties> key, the four goals, and the pinned plugin versions.