The most minimal parent pom is liftwizard-minimal-parent . If you are able to accept more opinionated defaults, continue to profile-parent liftwizard-profile-parent . The minimal parent is meant to contain uncontroversial best practices that are applicable to all projects.Inherit from liftwizard-minimal-parent in your project's pom.xml: xml <parent> <groupId>io.liftwizard</groupId> <artifactId>liftwizard-minimal-parent</artifactId> <version>${liftwizard.version}</version> </parent>
The following sections describe the best practices that are enforced by liftwizard-minimal-parent . You will not need to configure these in your project's pom.xml if you inherit from liftwizard-minimal-parent .
If you encounter a warning like: [WARNING] Using platform encoding (UTF-8 actually) to copy filtered resources, i.e. build is platform dependent! this is because the project does not https://maven.apache.org/plugins/maven-resources-plugin/examples/encoding.html#specifying-a-character-encoding-scheme specify a character encoding scheme to configure maven-resources-plugin . liftwizard-minimal-parent specifies the character encoding scheme in the properties section of the pom.xml. <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> This will become unnecessary starting with maven 4.x.
https://reproducible-builds.org/ Reproducible builds are a set of software development practices that create an independently-verifiable path from source to binary code. A build is reproducible if given the same source code, build environment and build instructions, any party can recreate bit-by-bit identical copies of all specified artifacts.You can https://maven.apache.org/guides/mini/guide-reproducible-builds.html#how-do-i-configure-my-maven-build enable Reproducible Builds mode for plugins by specifying locking down the outputTimestamp property. <project.build.outputTimestamp>2024-08-27T01:58:38Z</project.build.outputTimestamp> You will also need to run mvn artifact:check-buildplan and mvn verify artifact:compare as described in the guide to validate that builds are truly reproducible.
You can specify the default goal to run when you run mvn without any arguments. <defaultGoal>verify</defaultGoal> verify is a better choice than install in the presence of concurrent builds that may write to .m2/repository simultaneously. verify is a better choice than clean verify because developers may build up state like test files and test databases under target/ and may not expect them to be deleted by default. It's easy to run mvn clean when you need it.
Plugins which are bound and enabled by default
Maven builds are configured by binding plugins to https://maven.apache.org/guides/introduction/introduction-to-the-lifecycle.html#default-lifecycle lifecycle phases. Even if you don't declare any plugins in your pom.xml, maven will still bind https://maven.apache.org/ref/3.9.6/maven-core/default-bindings.html#plugin-bindings-for-jar-packaging some plugins to the https://maven.apache.org/guides/introduction/introduction-to-the-lifecycle.html#packaging "main" phases.All versions of maven bind the https://maven.apache.org/ref/3.9.6/maven-core/default-bindings.html#plugin-bindings-for-jar-packaging same plugins, but newer versions of maven bind newer versions of the plugins. If you don't specify the versions of the plugins, different members of the team could be using different versions, leading to different build results on different machines.It's becoming more common to lock down the version of maven itself, but this wasn't always the case. If you haven't specified the versions of these plugins, https://maven.apache.org/enforcer/enforcer-rules/requirePluginVersions.html maven-enforcer-plugin will log an error like: [ERROR] Rule 3: org.apache.maven.enforcer.rules.RequirePluginVersions failed with message: Some plugins are missing valid versions or depend on Maven 3.9.5 defaults (LATEST, RELEASE as plugin version are not allowed) org.apache.maven.plugins:maven-compiler-plugin. The version currently in use is 3.11.0 via default lifecycle bindings org.apache.maven.plugins:maven-surefire-plugin. The version currently in use is 3.1.2 via default lifecycle bindings org.apache.maven.plugins:maven-jar-plugin. The version currently in use is 3.3.0 via default lifecycle bindings org.apache.maven.plugins:maven-clean-plugin. The version currently in use is 3.2.0 via default lifecycle bindings org.apache.maven.plugins:maven-install-plugin. The version currently in use is 3.1.1 via default lifecycle bindings org.apache.maven.plugins:maven-site-plugin. The version currently in use is 3.12.1 via default lifecycle bindings org.apache.maven.plugins:maven-resources-plugin. The version currently in use is 3.3.1 via default lifecycle bindings org.apache.maven.plugins:maven-deploy-plugin. The version currently in use is 3.1.1 via default lifecycle bindings To avoid this, we specify versions of the plugins in the parent pom. <!-- These plugins are bound and enabled by default --> <!-- But the default version of these plugins changes with the version of maven running --> <!--region Phase 0: clean--> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-clean-plugin</artifactId> <version>3.4.0</version> </plugin> <!--endregion Phase 0: clean--> <!--region Phase 6: process-resources--> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-resources-plugin</artifactId> <version>3.3.1</version> </plugin> <!--endregion Phase 6: process-resources--> <!--region Phase 7: compile--> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>3.13.0</version> <configuration> <!-- https://maven.apache.org/plugins-archives/maven-compiler-plugin-3.8.1/compile-mojo.html#parameters --> <!-- https://stackoverflow.com/a/44075684/ --> <!-- https://docs.oracle.com/javase/9/tools/javac.htm --> <!-- Generates metadata for reflection on method parameters. Stores formal parameter names of constructors and methods in the generated class file so that the method java.lang.reflect.Executable.getParameters from the Reflection API can retrieve them. --> <parameters>true</parameters> </configuration> </plugin> <!--endregion Phase 7: compile--> <!--region Phase 15: test--> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-surefire-plugin</artifactId> <version>3.5.0</version> <!-- In maven 3.9.6 and 4.x, maven is able to auto-detect JUnit and these dependencies are not required --> <!-- In maven 3.9.5, there is an internal exception inside surefire without these declared --> <!-- Even with newer versions of maven, it is advantageous to keep these declarations --> <!-- Without them, maven may only run JUnit 5 tests, in a project with both JUnit 4 and 5 --> <dependencies> <dependency> <groupId>org.junit.jupiter</groupId> <artifactId>junit-jupiter-engine</artifactId> <version>5.10.3</version> </dependency> <dependency> <groupId>org.junit.platform</groupId> <artifactId>junit-platform-engine</artifactId> <version>1.10.3</version> </dependency> <dependency> <groupId>org.junit.vintage</groupId> <artifactId>junit-vintage-engine</artifactId> <version>5.10.3</version> </dependency> </dependencies> <configuration> <!-- The compiler in the server VM now provides correct stack backtraces for all "cold" built-in exceptions. For performance purposes, when such an exception is thrown a few times, the method may be recompiled. After recompilation, the compiler may choose a faster tactic using preallocated exceptions that do not provide a stack trace. To disable completely the use of preallocated exceptions, use this new flag: -XX:-OmitStackTraceInFastThrow. --> <!-- https://stackoverflow.com/a/4659279/ --> <!-- The compiler in the server VM now provides correct stack backtraces for all "cold" built-in exceptions. For performance purposes, when such an exception is thrown a few times, the method may be recompiled. After recompilation, the compiler may choose a faster tactic using preallocated exceptions that do not provide a stack trace. To disable completely the use of preallocated exceptions, use this new flag: -XX:-OmitStackTraceInFastThrow. --> <!-- https://stackoverflow.com/a/4659279/ --> <!-- Add argLine to allow the Jacoco plugin to append without overriding the setting --> <!-- https://stackoverflow.com/a/39818768/ --> <argLine>-XX:-OmitStackTraceInFastThrow @{argLine}</argLine> <runOrder>random</runOrder> <trimStackTrace>false</trimStackTrace> </configuration> </plugin> <!--endregion Phase 15: test--> <!--region Phase 17: package--> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-jar-plugin</artifactId> <version>3.4.2</version> </plugin> <!--endregion Phase 17: package--> <!--region Phase 22: install--> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-install-plugin</artifactId> <version>3.1.3</version> </plugin> <!--endregion Phase 22: install--> <!--region Phase 23: deploy--> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-deploy-plugin</artifactId> <version>3.1.3</version> </plugin> <!--endregion Phase 23: deploy-->
The are a number of maven plugins with goals that are designed to be run interactively, rather than being bound to a phase in the pom.xml. For example, mvn dependency:tree prints a visual representation of the dependencies of the project, and mvn versions:set updates the versions of dependencies in the pom.xml.Any maven plugin can be run from the command line with mvn groupId:artifactId:version:goal , and configured using command line arguments, without it appearing in the pom.xml. For example, we can run the https://www.mojohaus.org/buildplan-maven-plugin/ buildplan-maven-plugin to list the plugins bound to each phase with this command: shell mvn org.codehaus.mojo:buildplan-maven-plugin:2.2.2:list If we configure the plugin in the pom.xml, we can run it with the syntax mvn phase:goal and add any configuration that would otherwise be specified with -D flags. shell mvn buildplan:list We configure several plugins in the parent pom.xml that are not bound to any phase. <!--mvn versions:display-dependency-updates--> <!--mvn versions:display-plugin-updates--> <!--mvn versions:display-property-updates--> <plugin> <groupId>org.codehaus.mojo</groupId> <artifactId>versions-maven-plugin</artifactId> <version>2.17.1</version> <configuration> <!-- Don't create pom.xml.versionsBackup files --> <generateBackupPoms>false</generateBackupPoms> <!-- Process all modules in a multi-module build, even aggregator modules without a parent-child relationship --> <!-- https://stackoverflow.com/a/49246337/23572 --> <processAllModules>true</processAllModules> </configuration> </plugin> <!--mvn dependency:tree--> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-dependency-plugin</artifactId> <version>3.8.0</version> </plugin> <!--mvn buildplan:list--> <!--mvn buildplan:list-phase--> <!--mvn buildplan:list-plugin--> <plugin> <groupId>org.codehaus.mojo</groupId> <artifactId>buildplan-maven-plugin</artifactId> <version>2.2.2</version> <configuration> <!-- Default value is: deploy --> <tasks> <task>clean</task> <task>deploy</task> </tasks> <!-- print all phases, even if no mapping to an execution is available --> <showAllPhases>true</showAllPhases> </configuration> </plugin> <!--mvn rewrite:run--> <!--mvn rewrite:dryRun--> <plugin> <groupId>org.openrewrite.maven</groupId> <artifactId>rewrite-maven-plugin</artifactId> <version>5.39.2</version> <dependencies> <dependency> <groupId>org.openrewrite.recipe</groupId> <artifactId>rewrite-static-analysis</artifactId> <version>1.15.0</version> </dependency> <dependency> <groupId>org.openrewrite.recipe</groupId> <artifactId>rewrite-migrate-java</artifactId> <version>2.23.0</version> </dependency> <dependency> <groupId>org.openrewrite.recipe</groupId> <artifactId>rewrite-testing-frameworks</artifactId> <version>2.17.1</version> </dependency> <dependency> <groupId>org.openrewrite.recipe</groupId> <artifactId>rewrite-logging-frameworks</artifactId> <version>2.12.2</version> </dependency> <dependency> <groupId>org.openrewrite.recipe</groupId> <artifactId>rewrite-apache</artifactId> <version>1.5.1</version> </dependency> </dependencies> </plugin> <!--mvnw wrapper:wrapper -Dmaven=4.0.0-alpha-7--> <plugin> <artifactId>maven-wrapper-plugin</artifactId> <version>3.3.2</version> </plugin> <!--mvn clean release:clean release:prepare -DdevelopmentVersion=1.2.3-SNAPSHOT--> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-release-plugin</artifactId> <version>3.1.1</version> <configuration> <!-- Default value is: invoker --> <mavenExecutorId>forked-path</mavenExecutorId> <!-- Automatically assign submodules the parent version --> <autoVersionSubmodules>true</autoVersionSubmodules> <!-- Do not `git push` changes to the upstream repository --> <pushChanges>false</pushChanges> <!-- Format to use when generating the tag name --> <!-- Default value is: @{project.artifactId}-@{project.version} --> <tagNameFormat>@{project.version}</tagNameFormat> </configuration> </plugin>