Demos

Every feature below is a **self-contained project you can clone and run**. Each carries its own `build/jenesis/` sources, so `java build/jenesis/Make.java` from the demo folder builds it. A few that change the stock build or drive several builds ship a `build/Demo.java` to run instead; each demo's own README says which. They are numbered as a progression: the early ones establish the basics, the later ones go into specifics. Browse them on GitHub:

Getting started

The four project shapes, what a build costs to start, and the JDK it runs on - begin here.

Executables & packaging

Turning a build's output into something that runs on its own.

  • Executable (Maven) A runnable Maven project packaged with jpackage, plus bundle, launcher jar, and a container context.
  • Executable (modular) The same for a module: an app image, a .jmod and jlink runtime, a bundle, a launcher jar, and a Dockerfile.
  • Bundle Ship only the jars as a bundle.zip and run them on a stock JRE.
  • Multi-release JAR A multi-release jar that ships a Java 25 override of one class beside its Java 21 baseline.

Compiler control

Reaching past the compiler defaults.

Generated sources

Compiling a schema or a service contract into Java, as part of the build.

  • Data formats Three modules and three wire formats - XML Schema, protocol buffers and Avro - each compiled into Java by its own generator.
  • Service contracts A SOAP and a REST client generated from a WSDL and an OpenAPI document.
  • Parser from a grammar An ANTLR grammar compiled into a lexer, a parser and a visitor that the module uses.

Dependencies

Naming what a project depends on, and shaping the closure that arrives.

  • Exclusions Dropping an unwanted transitive, in a POM and with a tag.
  • Bills of materials Importing a Maven BOM and a local pin file, and publishing a BOM of the module's own closure.
  • Module alias Giving a plain jar a module name, then rewriting the closure into named modules so jlink accepts it.
  • Pure modular layout A strictly modular layout that resolves by module name and emits no POM.
  • Module override Reading a shaded API under its own module name, so a modular library and Tomcat Embed share a module path.
  • Module layers Keeping a dependency private, so two versions of one library run in one JVM with no package relocated.
  • Module layers over a legacy tree Isolating a library whose jars name themselves nowhere, by naming only the one the code calls.
  • Platform guard Pinning a classified variant, and guarding which one each platform gets.
  • Platform guard (Maven) The same guards in a Maven layout.

Supply chain & security

Which bytes arrived, who produced them, and what they carry.

  • Pinning A version and a checksum in your own sources, the two ways a build refuses what does not match, and an offline rebuild from what the first build stored.
  • OpenPGP signatures Declaring the key that signs a dependency, checked against the signature its project published.
  • Sigstore identities Declaring the workflow that released a dependency, verified from the bundle beside it with no key at all.
  • SBOM Generating a software bill of materials.
  • Dependency licensing Checking dependency licences against policy.
  • Vulnerabilities Scanning dependencies for known vulnerabilities.

Quality & testing

The gates a build can hold its own output to.

  • Code quality Formatting and static analysis for Java.
  • Test frameworks Tests whose module requires no engine: the framework they are written against is worked out and its engines resolved.
  • Code coverage Measuring test coverage.
  • Test selection Running only the tests a change can affect.
  • Mutation testing Mutation testing with PIT, switched on by its configuration file.
  • Benchmarks A JMH benchmark the build generates, compiles and runs, printing its result table.
  • API compatibility japicmp compares the built jar's byte code against a released one, so a breaking change shows up before you publish it.

JVM languages

The same build, for Kotlin, Scala and Groovy.

Running the build

How a build is configured, cached, confined and instrumented.

  • Build profiles Switching a set of settings on with a named profile, and writing a whole run into an argument file.
  • Build cache Sharing build outputs through a cache.
  • Docker isolation Confining the build and the launched program in a throwaway container.
  • Java agents Attaching agents to the test run and to the application run.
  • Native access Naming the module that needs native access, and granting it again in every module that runs it.
  • Native access in a layer Granting a library native access, which it passes on to the modules it keeps in its layer.
  • A modular jar on the class path META-INF/services files written from module-info, so one jar finds its services on either path.

Extending the build

Wrapping the template, adding build modules, or replacing it entirely.

  • Custom assembler Wrapping the stock assembler so sources are preprocessed before they compile.
  • jlink & jpackage A custom .jmod carrying extra content, linked into a runtime and packaged into an app.
  • Internal build module A plugin named in jenesis.plugins.properties, compiled from local source and configured by its own properties file.
  • External build module The same plugin resolved by its module name from a repository.
  • Project plugins Plugins hooked into the build of the whole project: a licence check before anything compiles, a notice attached to every module and checked before staging, a distribution zip beside the stock packages, checksums added to the staged trees and checked before export, an exporter that delivers them, and a line count run on demand without a build.
  • Custom Maven build Driving a multi-module Maven-layout build from your own entry point with the convenience factory.
  • Custom modular build The same for a modular project.
  • Custom build A code-generating build graph wired entirely by hand.
  • Running a build in-process A build, and the program it produced, run inside another program's JVM through java.util.spi.ToolProvider.

Delivery

Publishing what a build produced, and running what somebody else published.

  • Code signing The produced jar signed with jarsigner, with the key named by the machine rather than by the project.
  • Exporting to the local repositories A module exported into the local repositories and required from a second project by name, with both repositories in a temporary folder.
  • Publishing A Maven Central ready bundle - POM metadata, sources and javadoc jars - resolved back to prove it.
  • Your own module repository Modules published to a plain Maven repository and resolved back by module name, with no registry to keep in sync.
  • Module discovery A module resolved from what its domain's .well-known file says - the jar straight from a GitHub release, without a module repository or Maven.
  • Maven discovery A Maven dependency resolved from the location its group's domain names, beside the Maven remotes.
  • Reproducible builds A jar checked against a SHA-256 recorded in the demo, on Linux, macOS and Windows in CI.
  • Native image A GraalVM native binary built end to end, with reachability metadata captured from the tests.
  • Running a released program jpx installs and launches a published tool - named as a module and as a coordinate, pinned and hash-verified.
Cloning the whole repository gives you all of them at once, plus Jenesis itself as the largest worked example. See Getting started to install the tool first.