Configuration
Earlier chapters flipped knobs with -Djenesis. flags on the command line. That is fine for a one-off, but
you do not want to type the same flags on every build, and different builds (development versus release)
need different sets. This chapter shows where configuration lives so a project carries its own defaults: the
jenesis. file, the folders that hold each tool's configuration, profiles that switch a named
set of both at once, and the precedence rule that decides who wins.
System properties, in a file
Every knob you have met is a system property. jenesis., jenesis.,
jenesis. - anything you can pass with -D. The same properties can live in a
jenesis. file at the project root, so the project carries its own defaults without a wrapper
script:
# jenesis.properties (project root)
jenesis.project.layout=modular_to_maven
jenesis.project.sources=true
The file is read before the build is configured, so it drives everything the command line does: layout,
target, pinning, every later decision. The file is optional. An explicit -D on the command line always
overrides a file entry, so you can still override the project's baseline for a single run:
java -Djenesis.project.sources=false build/jenesis/Make.java
jenesis. belongs on the command line only, because the root is what locates the file in the first
place. Setting it in a file is reported as an error.
A project may name the repositories it resolves from, with jenesis., jenesis. and
jenesis.. A token never follows it there: jenesis. and jenesis. go
only to a repository named in the environment, on the command line or in your user-global file. A folder a
project's file names, such as jenesis., must lie inside the project, because the build writes
to it and may wipe it. On the command line it can name any folder.
The same goes for the few keys that describe your own environment rather than the project. They would make no sense in a project's file anyway, and a rogue project could use them to reach beyond its own build. The project's file and its profiles refuse them; the command line and your user-global file, described below, accept them.
Keys fall into namespaces, each grouping one concern: jenesis. for tests, jenesis. and
jenesis. for the two kinds of repository, and so on. jenesis. covers starting a build:
where the project is, which profiles to layer, where the user-global file lives, and how the engine itself is
compiled and reused. jenesis. covers the project as a whole, such as its version and where its
output goes. The reference lists every namespace and its keys.
-Djenesis.test.skip, or a bare jenesis.test.skip= in a file - is
true; =true and =false mean what they say. Any other value is
refused, naming the key and what would have been valid, so a typo stops the build instead of quietly
reading as off.
A whole run, in a file
A jenesis. file carries what every build of the project should do. A run that is not every build
- a release, a nightly, the one incantation nobody remembers - can be written down as well, as an argument
file the command line names with
@:
# release.args
-Djenesis.project.version=1.0.0
-Djenesis.make.profiles=release
stage
java build/jenesis/Make.java @release.args
@<file> stands for the arguments the file holds, settings and selectors alike, one or more per line. A #
starts a comment that runs to the end of the line, quotes hold what would otherwise split on whitespace, and
@@<text> is an argument that begins with an @ rather than a file. A file names no further file, so what
you read is what runs. This is the argument file the JDK's own tools read, and jpx and the jenesis and
jenesis-exec commands read it the same way.
Settings in such a file are command-line settings: they win over jenesis. and over a profile,
exactly as a typed -D does. That is possible because a setting may also follow the main class, ahead of
the selectors:
java build/jenesis/Make.java -Djenesis.project.version=1.0.0 build
Only jenesis. settings may be written there; any other -D is refused, naming what would be valid,
because a JVM option has to reach the JVM and therefore belongs before the main class.
Where tool configuration lives
System properties are the small knobs. A tool like Checkstyle or jpackage needs its own configuration file,
and those live in dedicated folders. A tool activates on the presence of its file: drop a checkstyle.
in and static analysis turns on; leave it out and it stays off. The folder is both the switch and the
settings.
Every lookup walks one ordered list of folders and the first folder that carries the file wins. The list runs from the most specific per-module location to the project-wide fallback:
| Location | Layout | Scope |
|---|---|---|
META-INF/ under a module's sources |
modular, modular_ |
that one module |
src/ or src/ under the pom root |
maven |
the pom's main or test module alone |
build. next to the pom. |
maven |
both of the pom's modules |
the jenesis. folders (default build. at the project root) |
all | project-wide |
What these folders can hold - presence activates, contents configure:
- Code quality:
checkstyle.,xml pmd.,xml spotbugs-exclude.,xml detekt.,yml codenarc.,xml scalastyle-config.,xml errorprone..properties - Generated sources:
xjc.,properties protoc.,properties avro.,properties wsimport.,properties openapi.,properties antlr..properties - Formatting:
javaformat.,properties .,editorconfig ..scalafmt. conf - Packaging and output:
packaging.,properties modules.,properties sbom.,properties bom..properties - Compliance:
licensing.,properties vulnerability.,properties spdx..properties - Tests:
test., naming the engine a module's tests run on.properties - Test observability:
jacoco.,properties graal.,properties pitest..properties - API compatibility:
japicmp..properties - Forked-tool arguments:
process-<command>.- extra flags forproperties javac,kotlinc,jar, and the like (see Building & running). - Forked-program environment:
environment-<command>.- variables for the test run, a forked JVM, PIT orproperties native-image(see Building & running).
Each of these is the subject of a later chapter; here the point is only where they go and that a file's mere presence switches its feature on.
.editorconfig, a checkstyle.xml
for the IDE - must not silently change the build. Configuration activates only from an explicit
build.jenesis/ folder (or a folder you opt into via jenesis.project.configuration).
Profiles
A profile is a named set of configuration you switch on in one move - the development-versus-release split,
without repeating long -D lists. There is no registry and no plugin: a profile is just a name.
Select profiles with the jenesis. property - a comma-separated list of names. Each name
<name> designates two things, both optional:
- a
jenesis-<name>.file at the project root, whose entries feed the sameproperties jenesis.system properties, and* - a
<name>/subfolder inside each configuration folder, searched ahead of the folder itself - so a profile can carry its owncheckstyle.,xml packaging., and so on.properties
pin-<name>.properties bill of materials is not searched for in a profile subfolder. It
is looked up only in the locations jenesis.project.boms names, which default to the
configuration folders themselves, so a project's pinned versions stay where the project put them.
Profiles chain: any loaded file may itself set jenesis. to pull in more, transitively.
The profiles demo ships a release
profile that turns on source jars and chains to a supply-chain profile that enforces strict pinning:
# jenesis-release.properties
jenesis.project.sources=true
jenesis.make.profiles=supply-chain
# jenesis-supply-chain.properties
jenesis.dependency.pin=strict
Selecting release therefore also applies supply-chain - one name switches on both:
java -Djenesis.make.profiles=release build/jenesis/Make.java stage
A missing jenesis-<name>. is skipped, not an error, so a profile may contribute only a
configuration folder, only a properties file, or both.
Precedence
With several layers in play, the rule is fixed. Configuration resolves in five tiers, highest first:
| Tier | Source |
|---|---|
| 1 | an explicit -D on the command line |
| 2 | the profiles selected by your user-global file (below) |
| 3 | your user-global jenesis. |
| 4 | the profiles selected for the project |
| 5 | the project jenesis. |
So -Djenesis. on a release build switches the source jar back off (the command line
always wins), selecting the release profile overrides whatever the project's base jenesis. set,
and a line in your own file overrides both, because what your machine settles applies to every project it
builds. The folder search follows the same spirit: a profile's <name>/ folder beats a plain folder, and a
module-local folder beats a project-wide one.
When you are unsure what the layers add up to, ask the build. The properties selector prints every
effective jenesis. property, sorted by key:
java -Djenesis.make.profiles=release build/jenesis/Make.java properties
User-global defaults
A user-global jenesis., read from ~/ and applied to every project, settles how
this machine builds. It outranks what a project sets, so a jenesis. there holds
for every project you build, and only a -D overrides it. It is optional and ignored when absent, and it may
declare its own profiles, resolved relative to its . folder.
The jenesis. property names the base folder (default $HOME) whose . subfolder
holds that file. Set to an empty string, it switches the user-global layer off entirely. It is set on the
command line only: a project's jenesis., a profile or the user-global file that sets it is refused,
so a project can never put a file of its own in the place of your personal defaults.