计划执行与检查节点
executing-plans
按既定实施计划完成工作,保持过程检查和反馈。
maven-build-system【效率与协作】Implements Apache Maven build configurations (POM structure, dependency management, profiles, multi-module builds, plugin configuration) for Java and Kotlin projects.
独立 GitHub 快照 · 自动分类 · 以原作者文档为准
name: maven-build-system description: Implements Apache Maven build configurations (POM structure, dependency management, profiles, multi-module builds, plugin configuration) for Java and Kotlin projects. license: MIT compatibility: opencode metadata: version: "1.0.0" domain: coding triggers: maven, pom.xml, mvn command, java build tool, dependency management, maven central, plugin management, BOM archetypes: [tactical, generation] anti_triggers: [brainstorming, vague ideation, code golf, over-engineering] response_profile: verbosity: low directive_strength: high abstraction_level: operational role: implementation scope: implementation output-format: code content-types: [code, guidance, do-dont, examples, config] related-skills: gradle-build-system
Implements Apache Maven build configurations for Java and Kotlin projects — managing multi-module reactor builds, centralized dependency versioning with BOMs, plugin management, profile activation, and production-grade diagnostic workflows. When loaded, the model acts as a senior build engineer producing correct pom.xml files, resolving dependency conflicts, and diagnosing build issues using Maven's built-in diagnostics.
<dependencyManagement> and <pluginManagement> for all multi-module projectspom) to centralize third-party dependency versions${project.version} instead of hardcoded version numbers in child POMsmvn help:effective-pom and mvn dependency:tree -Dincludes=groupId:artifactId to diagnose issues<scope>test</scope> on all test-scoped dependencies; never leave runtime deps as test scope<exclusions> to resolve transitive dependency conflicts at the point of declarationUse this skill when:
dependencyManagementeffective-pom, dependency:tree, and enforcer rulesAvoid this skill for:
gradle-build-system for Gradle-based builds insteadDefine Reactor Structure — Create a root pom.xml with <packaging>pom</packaging>, declare child modules via <modules>, and set the parent groupId/artifactId/version. Every child module must inherit these through a <parent> reference with <relativePath>../pom.xml</relativePath>.
Checkpoint: Run mvn help:evaluate -Dexpression=project.modules -q -DforceStdout to verify all modules are discovered. No child POM should declare its own groupId or version when inheriting from parent.
Configure Dependency Management — In the parent POM, place all project dependency coordinates inside <dependencyManagement>. For shared third-party libraries (SLF4J, JUnit, Jackson), create a separate BOM module with pom packaging that centralizes versions. Child modules reference dependencies without version numbers — Maven resolves them from the parent's management section.
Checkpoint: Run mvn dependency:tree -Dincludes=com.fasterxml.jackson.core from the root. All modules must show exactly one Jackson version with no conflict warnings.
Centralize Plugin Management — Declare plugin versions inside <build><pluginManagement> in the parent POM. Apply plugins to individual modules by listing them under each module's <build><plugins> section without specifying versions (they inherit from pluginManagement).
Checkpoint: Run mvn help:effective-pom -pl :my-service and verify that maven-compiler-plugin version matches your declared value. Maven must not emit "Plugin management" warnings about unmanaged plugins.
Enforce Build Policies — Add the maven-enforcer-plugin with at least three rules: enforceJavaVersion, enforceMavenVersion, and banDuplicatePomDependencies. Configure failure behavior to stop the build on violations.
Checkpoint: Run mvn enforcer:enforce from the root in a clean checkout — it must pass. Then intentionally inject a duplicate dependency in one module and verify it fails with a clear error message naming the duplicate artifacts.
Verify Reactor Build — Execute mvn clean verify from the reactor root. Review the output for version convergence warnings, plugin conflicts, or missing dependencies. The build exit code must be 0.
Checkpoint: Confirm that all modules compile, all tests pass, and no module shows [WARNING] Found dependency conflict. Check that inter-module dependencies resolve correctly (e.g., my-api depends on my-core, my-service depends on my-api).
Diagnostic Resolution — When builds fail or behave unexpectedly, use Maven's diagnostic commands: mvn help:effective-pom to see the resolved POM after interpolation and inheritance, mvn dependency:tree -Dverbose for full transitive resolution details, and mvn help:evaluate -Dexpression=propertyName to inspect property values.
Checkpoint: Every dependency conflict must have an explicit <exclusion> in the module that introduces it, accompanied by a comment explaining why.
A parent POM defines shared configuration while child modules inherit and specialize. The reactor build processes all modules in declaration order, resolving inter-module dependencies automatically.
<!-- Root pom.xml — Maven multi-module parent (Maven 3.9+) -->
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.example</groupId>
<artifactId>my-platform</artifactId>
<version>1.0.0-SNAPSHOT</version>
<packaging>pom</packaging>
<name>My Platform Parent</name>
<description>Parent POM for the My Platform multi-module project</description>
<modules>
<module>my-core</module>
<module>my-api</module>
<module>my-service</module>
<module>my-web</module>
<module>my-bom</module>
</modules>
<!-- Centralized dependency versions -->
<dependencyManagement>
<dependencies>
<!-- Internal modules — no version needed in children (inherit from parent) -->
<dependency>
<groupId>com.example</groupId>
<artifactId>my-core</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>com.example</groupId>
<artifactId>my-api</artifactId>
<version>${project.version}</version>
</dependency>
<!-- Third-party dependencies with centralized versions -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>2.0.16</version>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.5.7</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.18.2</version>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
<version>5.11.4</version>
<scope>test</scope>
</dependency>
</dependencies>
</dependencyManagement>
<!-- Plugin versions centralized here -->
<build>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.13.0</version>
<configuration>
<release>21</release>
<parameters>true</parameters>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>3.5.2</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-enforcer-plugin</artifactId>
<version>3.5.0</version>
</plugin>
</plugins>
</pluginManagement>
</build>
<!-- Properties for version management -->
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.release>21</maven.compiler.release>
</properties>
</project>
Child modules inherit everything from the parent. They only declare their own specific dependencies and plugin executions, never specifying versions for managed dependencies.
<!-- my-service/pom.xml — A child module -->
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<!-- Inherits groupId, version, and all management sections from parent -->
<parent>
<groupId>com.example</groupId>
<artifactId>my-platform</artifactId>
<version>1.0.0-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<artifactId>my-service</artifactId>
<name>My Service Module</name>
<description>Core business logic for the service layer</description>
<!-- Dependencies: version omitted — resolved from parent's dependencyManagement -->
<dependencies>
<dependency>
<groupId>com.example</groupId>
<artifactId>my-api</artifactId>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
</dependency>
<!-- Exclude Log4j-over-SLF4j — causes classloader conflicts in Spring Boot -->
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-to-slf4j</artifactId>
<version>2.24.3</version>
<exclusions>
<exclusion>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- Test dependencies -->
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<version>2.3.232</version>
<scope>test</scope>
</dependency>
</dependencies>
<!-- Apply enforcer plugin execution to this module -->
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-enforcer-plugin</artifactId>
<executions>
<execution>
<id>enforce-rules</id>
<goals><goal>enforce</goal></goals>
<configuration>
<rules>
<requireUpperBoundDeps/>
</rules>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
A dedicated BOM module allows the organization to manage third-party dependency versions in a single place. Child projects import it with <scope>import</scope> in their own dependencyManagement section. This is the Maven equivalent of Gradle's platform BOM.
<!-- my-bom/pom.xml — Centralized third-party version management -->
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.example</groupId>
<artifactId>my-platform</artifactId>
<version>1.0.0-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<artifactId>my-bom</artifactId>
<packaging>pom</packaging>
<name>My Platform BOM — Third-Party Dependency Versions</name>
<description>Import this BOM to use centralized third-party versions. Do not depend on this module as a library.</description>
<!-- This section becomes the BOM content when imported with scope=import -->
<dependencyManagement>
<dependencies>
<dependency>
<groupId>io.github.classgraph</groupId>
<artifactId>classgraph</artifactId>
<version>4.8.179</version>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>33.3.1-jre</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.17.0</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.18.2</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.36</version>
<scope>provided</scope>
</dependency>
</dependencies>
</dependencyManagement>
</project>
Child projects import the BOM:
<dependencyManagement>
<dependencies>
<!-- Import the organization's BOM — scope=import makes it act as dependencyManagement -->
<dependency>
<groupId>com.example</groupId>
<artifactId>my-bom</artifactId>
<version>${project.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
The enforcer plugin prevents dangerous or inconsistent builds by enforcing policies at build time. Configure it in the parent POM's <pluginManagement> with execution bindings that run during the verify phase.
<!-- Enforcer configuration — parent POM's pluginManagement -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-enforcer-plugin</artifactId>
<executions>
<execution>
<id>enforce-java-version</id>
<goals><goal>enforce</goal></goals>
<configuration>
<rules>
<requireJavaVersion>
<version>[17,)</version>
<message>Java 17 or higher is required for this project.</message>
</requireJavaVersion>
<requireMavenVersion>
<version>[3.9.0,)</version>
<message>Maven 3.9+ is required for modern dependency resolution.</message>
</requireMavenVersion>
</rules>
</configuration>
</execution>
<execution>
<id>enforce-dependency-convergence</id>
<goals><goal>enforce</goal></goals>
<configuration>
<rules>
<requireUpperBoundDeps/>
</rules>
</configuration>
</execution>
</executions>
</plugin>
Profiles activate conditionally based on OS, properties, or default settings. Use profiles to manage environment-specific configurations such as repository URLs, profiled code paths, and build flags.
<!-- Parent POM — Profile definitions -->
<profiles>
<!-- Development profile: activated by default for local work -->
<profile>
<id>dev</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<properties>
<environment.type>development</environment.type>
<!-- Enable debug logging in dev builds -->
<log.level>DEBUG</log.level>
<!-- Skip integration tests during rapid dev cycles -->
<skipITs>true</skipITs>
</properties>
</profile>
<!-- Production profile: activated via -Pprod or CI environment variable -->
<profile>
<id>prod</id>
<activation>
<property><name>env</name><value>prod</value></property>
</activation>
<properties>
<environment.type>production</environment.type>
<log.level>WARN</log.level>
</properties>
<!-- Can override dependencies for production (e.g., different DB driver) -->
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<configuration>
<archive>
<manifestEntries>
<Environment>${environment.type}</Environment>
</manifestEntries>
</archive>
</configuration>
</plugin>
</plugins>
</build>
</profile>
<!-- Profile for running integration tests with Maven Toolchains -->
<profile>
<id>integration-test</id>
<activation>
<property><name>skipITs</name><value>false</value></property>
</activation>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-failsafe-plugin</artifactId>
<version>3.5.2</version>
<executions>
<execution>
<goals>
<goal>integration-test</goal>
<goal>verify</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
</profiles>
When builds fail or behave unexpectedly, these commands diagnose the root cause:
| Command | Purpose |
|---|---|
mvn help:effective-pom | Show the fully resolved POM after inheritance, interpolation, and profile activation |
mvn help:effective-pom -pl :my-service | Effective POM for a specific module |
mvn dependency:tree | Display the full dependency tree with transitive dependencies |
mvn dependency:tree -Dincludes=com.fasterxml.jackson.core | Filter the dependency tree to specific artifacts |
mvn dependency:tree -Dverbose | Show why each dependency was selected (path length, conflicts) |
mvn help:evaluate -Dexpression=project.version -q -DforceStdout | Print a single property value directly to stdout |
mvn enforcer:enforce | Run enforcer rules and report violations |
mvn dependency:analyze | Report used/declared and unused declared dependencies |
mvn -N help:effective-pom | Show the effective POM of the reactor root (use -N for non-recursive) |
<!-- ❌ BAD — Child declares version directly; easy to drift across modules -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>2.0.16</version> <!-- Hardcoded — if another module uses 2.0.9, conflict! -->
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.17.0</version> <!-- Different version from my-api module → runtime failure -->
</dependency>
<!-- ✅ GOOD — Version declared once in parent; children omit version entirely -->
<!-- Parent pom.xml -->
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>2.0.16</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.18.2</version>
</dependency>
</dependencies>
</dependencyManagement>
<!-- Child pom.xml — no version needed -->
<dependencies>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
</dependency>
</dependencies>
<source> and <target> instead of <release><!-- ❌ BAD — source/target split compilation into two phases; does not set bootstrap classpath -->
<configuration>
<source>21</source>
<target>21</target>
</configuration>
release flag (Java 9+)<!-- ✅ GOOD — Single flag, sets all three aspects correctly for modern Java -->
<configuration>
<release>21</release>
</configuration>
<dependencyManagement> and <pluginManagement> for multi-module projectspom packaging) for third-party dependency version alignment; child modules import it with <scope>import</scope>${project.version} in all child POMs instead of hardcoded version numbers to keep releases synchronizedrequireJavaVersion, requireMavenVersion, and requireUpperBoundDeps rules<scope>test</scope> explicitly on all test-scoped dependencies — never rely on default scope (compile) for tests<exclusions> to resolve transitive dependency conflicts at the point of declaration, with a comment explaining whymvn clean verify from the reactor root as the standard build command before committing changesdependencyManagement section exists — this creates silent version drift<relativePath> from <parent> declarations — Maven falls back to the repository, which is slower and may resolve the wrong version<source> and <target> instead of <release> for Java compilation — use the unified release flag introduced in Java 9<scope>system</scope> for dependencies — it breaks portability and CI builds; always use Maven Central or a private repository| Skill | Purpose |
|---|---|
gradle-build-system | Alternative build system using Gradle Kotlin DSL, version catalogs, and convention plugins for projects that prefer Gradle over Maven |
Authoritative documentation links for this skill's domain. The model follows markdown links at load time to resolve external references and inline content.