The pom-scijava-base project is a Maven POM that serves as the base for all
Maven-based SciJava software, including:
Fiji
ImageJ2
ImgLib2
KNIME
LOCI
SCIFIO
SciJava
FLIMLib
Virtual Cell
|
|
|
|
|
|
|
|
|
pom-scijava-base vs. pom-scijava
It is encouraged that you not extend this POM directly, and instead
use pom-scijava as parent.
pom-scijava-base
pom-scijava
| "Low level" base POM, without dependency version management. Extend pom-scijava-base only if you are a Maven expert, and have good reasons for doing so. |
Friendly base POM for SciJava software, including dependency version management. Extend pom-scijava to inherit the unified SciJava Bill of Materials: component versions which have been tested to work together. |
See these examples for guidance:
Enforcer rules declared in this parent
The pom-scijava-base parent POM declares several
enforcer rules which
we believe make SciJava-based projects more reproducible and more consistent:
-
Plugin versions. Out of the box, Maven does not require plugins used to
declare a version. But plugin versions must be declared to ensure
reproducible builds. Otherwise, the version of Maven core you use at build
time will determine which plugin versions are used, and the behavior might
differ between builds.
-
No duplicate classes. If two dependencies define the same class, then
it introduces the possibility of serious class-loading issues. Which version
of the class should be chosen? In some scenarios, classes from one part of a
certain library may be loaded from dependency foo, but classes from a
different part of that same library at a different version may be loaded
from dependency bar. When this happens, difficult-to-understand compiler
errors, or even runtime errors, may occur. Best practice is to ensure that
all classes come onto the classpath from exactly one source.
-
No too-new dependencies. When a project is compiled for Java version X,
then it may not use any dependencies which require a version newer than X.
Otherwise, your project is lying about needing only version X.
-
No circular dependencies. Actually, this is a central rule of Maven. But
we configure the Enforcer to explicitly check for it, just to be safe. It is
always possible to avoid circular dependencies; if you feel like you need
one, you should instead solve it in one of the following ways, depending on
how much code is co-dependent:
- Combine the co-dependent artifacts into a single artifact.
- Introduce a third artifact to house the co-dependent code, which depends
on the other two artifacts.
- If all else fails, write to the
SciJava list for help.
-
Reproducible builds. This rule means no SNAPSHOT dependencies, no
SNAPSHOT parents, and no SNAPSHOT plugin versions. A snapshot version is
not immutable, which means that code which depends on a snapshot may build
today, but not build tomorrow, if the snapshot is later changed. The best way
to avoid this conundrum is to never depend on SNAPSHOT versions. Snapshot
are best used for testing only; they can be used transiently, but their use
should never make it onto the main integration branch
(e.g., main or master) of a project. See also
Using snapshot couplings during development.
-
Developer roles. SciJava-based projects define developers and
contributors with roles matching the
SciJava team roles. Doing this is vital for
consistency, and for communicating expectations to the community. By being
careful about which developers are pledging which sorts of responsibility,
the social status of each project becomes much clearer, and which social
actions to take in various circumstances becomes a more tractable problem.
We have
automated tooling
which can populates a statbox sidebar for any component built on SciJava,
including all components of the
ImageJ2 software stack;
this tooling requires SciJava developer roles to be present for sensible
results.
-
Required metadata. Every SciJava-based project must override key pieces
of metadata, including the name, description, url, inceptionYear,
organization, licenses, developers, contributors, mailingLists,
scm, issueManagement and ciManagement elements, as well as the
license.licenseName and license.copyrightOwners properties.
There are several reasons for requiring these overrides:
- Avoid inadvertent inheritance. The pom-scijava-base POM itself
declares all of this metadata for itself (e.g., its <scm> block defines
where the pom-scijava-base source code is managed, and this information
is necessary for the tooling which cuts releases of the
pom-scijava-base POM itself). For better and worse, when extending
pom-scijava-base, the child POM inherits all of these elements (except
for <name>, but that is the sole exception in the above list). If the
child POM does not override each and every one of these elements, then it
will inadvertently inherit the incorrect values from the
pom-scijava-base parent. Furthermore, due to a quirk/limitation in
Maven, if you specify an empty block (e.g., <contributors />), then the
non-empty value from the ancestor will take precedence in the
interpolated POM. Hence, we enforce that all of these fields are
overridden with non-empty values. See below for advice on how to best
override specific metadata fields.
- Present the project's metadata simply and clearly. For humans, being
able to look at a project POM and clearly see the metadata is very
helpful for understanding the project. Whereas when inheritance is
involved, the human must be patient enough to dig through the ancestor
POMs manually looking for the information, or else knowledgeable enough
to know that they should actually use mvn help:effective-pom and check
the metadata there instead, to know the actual values.
- Make the metadata easier for tooling to consume. Maven-based tooling
which uses the interpolated POM will be able to extract the correct
inherited metadata from a POM, sure. But in many cases, it is much
simpler and more natural, especially for Maven non-experts, to code
tooling using shell scripts and similar approaches. In those cases, it is
much easier if the tooling can simply extract the metadata from the child
POM itself and be guaranteed that the values there are the correct ones,
without needing to recurse into parent POMs whose contents may be less
trivial to inspect.
- Make it easier to maintain license headers in the sources. Putting a
license blurb at the top of each source file is legal best practice, but
it is undeniably a hassle, which is one reason many projects do not
bother. But with the license-maven-plugin, generating and maintaining
these license headers becomes very easy—as long as the inceptionYear,
license.projectLicense and license.copyrightOwners values are
provided in the POM. At that point, you can just invoke mvn license:update-file-header license:update-project-license and your work
is done.
- Encourage responsible metadata curation. As a project maintainer,
you are responsible for your project's metadata. Yes, it is a hassle to
specify it. But regardless, you need to understand where (if anywhere)
your project lives in SCM, which (if any) system is being used to
automatically build it, and so on. You have legal and social obligations
to clearly communicate the project license, to clearly document community
expectations, to give credit where credit is due, etc.
The full set of Enforcer rules as of pom-scijava-base version 14.0.0 can be
seen here.
How to override a field with an "empty" value
For some projects, you may have "empty" metadata fields, and you may be unsure
how best to override those values accordingly. The most common scenarios are:
- If your project has no contributors, write:
<contributors>
<!--
NB: Need at least one element to override the parent.
See: https://issues.apache.org/jira/browse/MNG-5220
-->
<contributor>
<name>None</name>
</contributor>
</contributors>
- If your project has no discussion forum or mailing list, write:
<mailingLists>
<mailingList>
<name>None</name>
</mailingList>
</mailingLists>
But you are warmly welcome to use the
Image.sc Forum for discussing your project,
so instead it is better to write:
<mailingLists>
<mailingList>
<name>Image.sc Forum</name>
<archive>https://forum.image.sc/tag/your-tag</archive>
</mailingList>
</mailingLists>
Where your-tag is the tag you want to
be used when discussing your project.
- If your project has no CI, write:
<ciManagement>
<system>None</system>
</ciManagement>
- If your project has no issue tracker, write:
<issueManagement>
<system>None</system>
</issueManagement>
- If your project does not live in SCM, then write:
<scm>
<system>None</system>
<url>None</url>
</scm>
But as an aside, in this case, we strongly encourage you to adopt an SCM;
check yourself before you wreck yourself.
For more information about Maven, see: