Gradle plugin reference

The io.stoatflow convention plugin — the full stoatflow { } extension DSL, the plugins and JVM flags it applies, the tasks it contributes, and the Docker and native-image defaults.

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 { }

PropertyTypeDefaultDescription
mainClassProperty<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 { }nestedOpt-in Jib Docker image build. See below.
nativeImage { }nestedOpt-in GraalVM native-image build. See below.

docker { }

PropertyTypeDefaultDescription
enabledProperty<Boolean>falseWhen true, applies the Jib plugin and the StoatFlow image conventions.
imageNameProperty<String>project.nameTarget image name. Tagged latest and <project.version>.
portProperty<Int>8080Exposed container port (the runtime's HTTP admin / metrics server).
userProperty<String>1000:1000Non-root run-as user (uid:gid).
baseImageProperty<String>eclipse-temurin:25-jre-nobleJVM base image (JVM/Jib path only; the native runtime base stays distroless).
stateDirProperty<String>/data/stateRocksDB state directory; set as STOATFLOW_STATE_DIR. Mount a volume here.
rocksdbMbProperty<Int>auto-detectOff-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.
reproducibleBuildProperty<Boolean>truePins the image creationTime to the HEAD commit timestamp. false = wall-clock (USE_CURRENT_TIMESTAMP).
jvmFlagsListProperty<String>["-XX:+UseG1GC"]Container JVM flags. Overridable — but --enable-preview and --enable-native-access=ALL-UNNAMED are always added on top.

nativeImage { }

PropertyTypeDefaultDescription
enabledProperty<Boolean>falseWhen true, applies the GraalVM native-build plugin and registers the nativeDockerBuild task.
gcProperty<String>absentGC algorithm, passed as --gc=<value>. Absent = the native image default (Serial GC). Set "G1" for stateful (RocksDB) workloads — G1 needs Oracle GraalVM.
runtimeTargetProperty<String>runtimeDocker 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).
additionalInitializeAtRunTimeListProperty<String>[]Extra fully-qualified class names added to the curated --initialize-at-run-time base.
removeInitializeAtRunTimeListProperty<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:

ConcernEffect
application pluginApplied. mainClass wired from the extension; applicationDefaultJvmArgs set to the preview JVM args (below).
com.gradleup.shadow pluginApplied. Configures ShadowJar with archiveClassifier = "all", mergeServiceFiles(), and a Main-Class manifest attribute (from mainClass).
Java toolchainJavaLanguageVersion.of(25).
Kotlin toolchainjvmToolchain(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 taskJUnit Platform with the IntegrationTest tag excluded; the test JVM args (below) applied.
integrationTest taskRegistered (when the java plugin is present); runs only @Tag("IntegrationTest") tests, after test.

JVM args

ContextFlags
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

TaskGroupAvailable whenPurpose
runapplicationalways (from application)Runs the app with the preview JVM args.
shadowJarshadowalways (from shadow)Builds the runnable fat JAR (-all classifier, merged service files, Main-Class manifest).
integrationTestverificationthe java plugin is presentRuns JUnit Platform tests tagged IntegrationTest (Docker / Testcontainers). Runs after test.
copyStoatFlowEntrypoint(none)docker.enabled = trueStages the container-aware heap entrypoint into the Jib extra directory. All jib* tasks depend on it.
jib, jibDockerBuild, jibBuildTardocker.enabled = true (from Jib)Build the image. jibDockerBuild targets the local Docker daemon.
nativeDockerBuildbuildnativeImage.enabled = trueBuilds 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, nativeRunnativeImage.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:

AspectValue
Base imagebaseImage (default eclipse-temurin:25-jre-noble)
Platformlinux/arm64 on aarch64 hosts, otherwise linux/amd64
Target imageimageName (or project.name), tagged latest and project.version
creationTimeHEAD commit timestamp when reproducibleBuild = true (default), else wall-clock
Entrypoint/app/stoatflow-entrypoint.sh (bundled container-aware heap script)
Working directory/app
Exposed portport (default 8080)
Useruser (default 1000:1000)
JVM flags--enable-preview, --enable-native-access=ALL-UNNAMED, + docker { jvmFlags }
Env: STOATFLOW_STATE_DIRstateDir (default /data/state)
Env: STOATFLOW_ROCKSDB_MBrocksdbMb, or 256 when RocksDB is auto-detected on the runtime classpath (omitted otherwise)
Configuration cache. The plugin is configuration-cache clean for the plain and native paths. 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:

AspectValue
Toolchain detectionenabled
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-timeorg.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
--gcadded only when nativeImage { gc } is set
SOURCE_DATE_EPOCHHEAD 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:

ToolVersion
Gradle9.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 plugin2.4.0 (you bring your own; the plugin doesn't bundle it)
  • 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.