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.

StoatFlow gives Maven projects the same build conventions as the Gradle plugin, through three published artifacts under io.stoatflow. This page enumerates them; for the setup walkthrough see Project setup.

The three artifacts

ArtifactWhat it is
io.stoatflow:stoatflow-bomA Maven BOM (<dependencyManagement> import) that aligns the StoatFlow modules with their tested kafka-clients / rocksdbjni / micrometer versions and imports the JUnit BOM.
io.stoatflow:stoatflow-parentThe convention parent POM — JDK 25 + --enable-preview, kotlin-maven jvmTarget 25, the shade fat JAR, the surefire/failsafe IntegrationTest tag-split, exec:exec run, and the stoatflow-docker / stoatflow-native profiles. Imports the BOM for you.
io.stoatflow:stoatflow-maven-pluginFour goals (prefix stoatflow) for the things XML can't express: RocksDB auto-detection, the staged native docker build, and the forked preview-flag run.

Set up

Inherit from the parent and declare your dependency (its version comes from the BOM the parent imports — so you omit it):

<!-- pom.xml -->
<parent>
  <groupId>io.stoatflow</groupId>
  <artifactId>stoatflow-parent</artifactId>
  <version>REPLACE-WITH-CURRENT-RELEASE</version>   <!-- literal — Maven can't resolve a property in <parent> -->
  <relativePath/>
</parent>

<properties>
  <stoatflow.mainClass>com.example.Main</stoatflow.mainClass>
</properties>

<dependencies>
  <dependency>
    <groupId>io.stoatflow</groupId>
    <artifactId>stoatflow-runtime</artifactId>
    <!-- version managed by the imported stoatflow-bom -->
  </dependency>
  <dependency>
    <groupId>io.stoatflow</groupId>
    <artifactId>stoatflow-test-utils</artifactId>
    <scope>test</scope>
  </dependency>
</dependencies>

The current release is 1.0.0-alpha.16 — substitute it for the REPLACE-WITH-CURRENT-RELEASE placeholder (the <parent> version must be a literal; Maven does not interpolate properties in parent coordinates). For a Kotlin project, point Maven at src/main/kotlin, add the kotlin-stdlib (version ${kotlin.version}, from the parent), and use the …Kt main class — the parent already configures kotlin-maven-plugin (jvmTarget 25) and binds its compile/test-compile phases.

Short goal prefix (mvn stoatflow:…). To call the plugin's standalone goals by their short prefix, add io.stoatflow to <pluginGroups> in your ~/.m2/settings.xml:
<pluginGroups>
  <pluginGroup>io.stoatflow</pluginGroup>
</pluginGroups>
Without it, use full coordinates — e.g. mvn io.stoatflow:stoatflow-maven-plugin:run.

What the parent configures

ConventionDetail
Compiler--release 25 + --enable-preview (javac).
Kotlinkotlin-maven-plugin jvmTarget 25 (no preview flag — that's javac-only).
Fat JARmaven-shade-plugin produces a <finalName>-all.jar with the Main-Class manifest + merged service files.
Unit testsmaven-surefire-plugin on JUnit Platform with the preview/native-access JVM args; excludes @Tag("IntegrationTest").
Integration testsmaven-failsafe-plugin runs only @Tag("IntegrationTest"), bound to integration-test / verify.
Runexec-maven-plugin configured for exec:exec — a forked JVM so --enable-preview applies (exec:java runs in Maven's own JVM and can't).
Profilesstoatflow-docker (Jib image at package), stoatflow-native (native compile at package), and host-arch selection.

Properties reference

Set these in your <properties>. Defaults come from the parent.

PropertyDefaultDescription
stoatflow.mainClass(required)Application entry point. stoatflow:configure fails the build if unset.
stoatflow.docker.imageName${project.artifactId}Image name. Tagged latest + <version>.
stoatflow.docker.port8080Exposed container port.
stoatflow.docker.user1000:1000Non-root run-as user.
stoatflow.docker.baseImageeclipse-temurin:25-jre-nobleJVM base image.
stoatflow.docker.stateDir/data/stateRocksDB state dir → STOATFLOW_STATE_DIR.
stoatflow.docker.rocksdbMbempty = auto-detectOff-heap RocksDB MiB → STOATFLOW_ROCKSDB_MB. Empty = 256 if RocksDB on the classpath, else omitted; set a value to force; 0 omits.
stoatflow.docker.reproducibleBuildtruePin creationTime to the HEAD commit.
stoatflow.docker.jvmFlags-XX:+UseG1GCContainer GC flag (preview/native-access always added).
stoatflow.nativeImage.gcempty--gc value for the native docker build (e.g. G1; needs Oracle GraalVM).
stoatflow.nativeImage.runtimeTargetruntimeDocker target stage for native-docker-build (runtime or runtime-lean).
stoatflow.nativeImage.removeInitializeAtRunTimeemptyComma-separated --initialize-at-run-time entries to drop from the curated base.
docker.rocksdbMb, creationTime, and the docker executable carry no <properties> default. Maven's model interpolator bakes <properties> into the plugin <configuration>before any Mojo runs, which would override the auto-detection — so these stay undefined and resolve live from stoatflow:configure. To add native flags (the counterpart of Gradle's additionalInitializeAtRunTime), extend the native-maven-plugin<buildArgs> in your POM, or ship reachability metadata with your value classes (see Native image → Custom serde metadata).

Goals

GoalBound toPurpose
stoatflow:configureinitialize (both profiles)Auto-detects RocksDB → STOATFLOW_ROCKSDB_MB, probes the docker executable (macOS), computes the reproducible creationTime, stages the effective native argfile, and validates mainClass.
stoatflow:copy-entrypointprepare-package (docker profile)Stages the container-aware heap entrypoint into target/jib-extra/app/.
stoatflow:native-docker-buildstandaloneStages the native build context (prebuilt JAR + argfile + Dockerfile.native + entrypoint) and runs the host-arch docker build.
stoatflow:runstandaloneForks a JVM with the preview flags + your runtime classpath + mainClass.

Build commands

CommandResult
mvn packageCompiles + the fat JAR target/<name>-<version>-all.jar.
mvn -Pstoatflow-docker packageFat JAR and a Jib image to your local Docker daemon — one command.
mvn -Pstoatflow-native packageA GraalVM native binary via native-maven-plugin (host toolchain).
mvn stoatflow:native-docker-buildA native image built inside Docker from the prebuilt fat JAR (run mvn package first).
mvn stoatflow:runThe app in a forked JVM with --enable-preview.
Profiles are activated with -P, not POM <properties>. Maven <activation> reads system/user properties, not your project's <properties> — so a <stoatflow.docker.enabled> flag does not turn the build on. Activate with mvn -Pstoatflow-docker … (or -Dstoatflow.docker.enabled=true). The stoatflow-docker profile binds the Jib dockerBuild goal to package, which is why mvn -Pstoatflow-docker package is the whole image build.

Using just the BOM

If you don't want the parent POM (you already have a corporate parent, say), import the BOM directly for version alignment and configure the toolchain + flags yourself — the DIY path is in Installation → Option B:

<properties>
  <stoatflow.version>REPLACE-WITH-CURRENT-RELEASE</stoatflow.version>
</properties>

<dependencyManagement>
  <dependencies>
    <dependency>
      <groupId>io.stoatflow</groupId>
      <artifactId>stoatflow-bom</artifactId>
      <version>${stoatflow.version}</version>
      <type>pom</type>
      <scope>import</scope>
    </dependency>
  </dependencies>
</dependencyManagement>

Version compatibility

The parent pins the build plugins it uses. As of 1.0.0-alpha.16 the pins are:

PluginVersion
Maven3.8+ (3.9.x recommended)
jib-maven-plugin3.5.1
native-maven-plugin1.1.0
maven-shade-plugin3.6.0
kotlin-maven-plugin2.4.0
surefire / failsafe3.5.2
jib-maven-plugin (3.5.1) trails the jib-gradle-plugin (3.5.2) — that's their independent release cadence, not a defect; both produce equivalent images.