You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@maven.apache.org by gn...@apache.org on 2026/10/10 00:04:40 UTC
(maven-install-plugin) branch fix/module-source-hierarchy created (now 8722da0)
This is an automated email from the ASF dual-hosted git repository.
gnodet pushed a change to branch fix/module-source-hierarchy
in repository https://gitbox.apache.org/repos/asf/maven-install-plugin.git
at 8722da0 Auto-detect module source hierarchy and skip main artifact at install
This branch includes the following new commits:
new 8722da0 Auto-detect module source hierarchy and skip main artifact at install
The 1 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails. The revisions
listed as "add" were already present in the repository and have only
been added to this reference.
(maven-install-plugin) 01/01: Auto-detect module source hierarchy and skip main artifact at install
Posted by gn...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
gnodet pushed a commit to branch fix/module-source-hierarchy
in repository https://gitbox.apache.org/repos/asf/maven-install-plugin.git
commit 8722da09a6b9ed33747cdeca65cc06788e744b66
Author: Guillaume Nodet <gn...@gmail.com>
AuthorDate: Sat Oct 10 02:04:28 2026 +0200
Auto-detect module source hierarchy and skip main artifact at install
When a project uses module source hierarchy (<source><module>…), the
JAR plugin produces one JAR per JPMS module as attached artifacts and
never assigns a file to the main artifact. The install plugin then
fails because the main artifact path is a directory.
Auto-detect this case by checking whether any source root declares a
module (via ProjectManager.getSourceRoots() / SourceRoot.module()),
and skip the main artifact from the install request — installing only
the POM and the per-module JARs.
This is a workaround for Maven 4.0. The proper fix is tracked in
apache/maven#13396 (Packaging.producesMainArtifact() API for 4.1.0).
Co-Authored-By: Claude Opus 4.6 (1M context) <no...@anthropic.com>
---
.../apache/maven/plugins/install/InstallMojo.java | 34 +++++++++++++---------
.../maven/plugins/install/InstallMojoTest.java | 30 +++++++++++++++++++
2 files changed, 51 insertions(+), 13 deletions(-)
diff --git a/src/main/java/org/apache/maven/plugins/install/InstallMojo.java b/src/main/java/org/apache/maven/plugins/install/InstallMojo.java
index 1eda589..9120c35 100644
--- a/src/main/java/org/apache/maven/plugins/install/InstallMojo.java
+++ b/src/main/java/org/apache/maven/plugins/install/InstallMojo.java
@@ -249,6 +249,7 @@ public class InstallMojo implements org.apache.maven.api.plugin.Mojo {
ProjectManager projectManager = getProjectManager();
Collection<ProducedArtifact> installables = projectManager.getAllArtifacts(project);
Collection<ProducedArtifact> attachedArtifacts = projectManager.getAttachedArtifacts(project);
+ List<ProducedArtifact> toInstall = new ArrayList<>(installables);
getArtifactManager().setPath(project.getPomArtifact(), project.getPomPath());
@@ -258,19 +259,21 @@ public class InstallMojo implements org.apache.maven.api.plugin.Mojo {
if (attachedArtifacts.isEmpty()) {
throw new MojoException(
"The packaging for this project did not assign a file to the build artifact");
+ } else if (usesModuleSourceHierarchy(project, projectManager)) {
+ getLog().info("Module source hierarchy: no main artifact produced;"
+ + " installing POM and per-module artifacts only.");
+ toInstall.remove(installable);
+ } else if (allowIncompleteProjects) {
+ getLog().warn("");
+ getLog().warn("The packaging plugin for this project did not assign");
+ getLog().warn("a main file to the project but it has attachments. Change packaging to 'pom'.");
+ getLog().warn("");
+ getLog().warn("Incomplete projects like this will fail in future Maven versions!");
+ getLog().warn("");
+ toInstall.remove(installable);
} else {
- if (allowIncompleteProjects) {
- getLog().warn("");
- getLog().warn("The packaging plugin for this project did not assign");
- getLog().warn(
- "a main file to the project but it has attachments. Change packaging to 'pom'.");
- getLog().warn("");
- getLog().warn("Incomplete projects like this will fail in future Maven versions!");
- getLog().warn("");
- } else {
- throw new MojoException("The packaging plugin for this project did not assign "
- + "a main file to the project but it has attachments. Change packaging to 'pom'.");
- }
+ throw new MojoException("The packaging plugin for this project did not assign "
+ + "a main file to the project but it has attachments. Change packaging to 'pom'.");
}
} else {
throw new MojoException("The packaging for this project did not assign "
@@ -279,13 +282,18 @@ public class InstallMojo implements org.apache.maven.api.plugin.Mojo {
}
}
- return ArtifactInstallerRequest.build(session, installables);
+ return ArtifactInstallerRequest.build(session, toInstall);
}
private boolean isValidPath(Artifact a) {
return getArtifactManager().getPath(a).filter(Files::isRegularFile).isPresent();
}
+ private static boolean usesModuleSourceHierarchy(Project project, ProjectManager projectManager) {
+ return projectManager.getSourceRoots(project).stream()
+ .anyMatch(sr -> sr.module().isPresent());
+ }
+
void setSkip(boolean skip) {
this.skip = skip;
}
diff --git a/src/test/java/org/apache/maven/plugins/install/InstallMojoTest.java b/src/test/java/org/apache/maven/plugins/install/InstallMojoTest.java
index df6a474..85cc253 100644
--- a/src/test/java/org/apache/maven/plugins/install/InstallMojoTest.java
+++ b/src/test/java/org/apache/maven/plugins/install/InstallMojoTest.java
@@ -27,12 +27,14 @@ import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
+import java.util.Optional;
import java.util.concurrent.atomic.AtomicReference;
import org.apache.maven.api.Artifact;
import org.apache.maven.api.MojoExecution;
import org.apache.maven.api.ProducedArtifact;
import org.apache.maven.api.Project;
+import org.apache.maven.api.SourceRoot;
import org.apache.maven.api.di.Inject;
import org.apache.maven.api.di.Named;
import org.apache.maven.api.di.Priority;
@@ -154,6 +156,34 @@ class InstallMojoTest {
artifacts.stream().map(Artifact::key).toList());
}
+ @Test
+ @InjectMojo(goal = "install")
+ @MojoParameter(name = "installAtEnd", value = "false")
+ void moduleSourceHierarchySkipsMainArtifact(InstallMojo mojo) throws Exception {
+ assertNotNull(mojo);
+ Project project = (Project) getVariableValueFromObject(mojo, "project");
+
+ SourceRoot moduleRoot = mock(SourceRoot.class);
+ when(moduleRoot.module()).thenReturn(Optional.of("org.example.module"));
+ when(projectManager.getSourceRoots(project)).thenReturn(List.of(moduleRoot));
+
+ projectManager.attachArtifact(
+ project,
+ new ProducedArtifactStub("org.apache.maven.test", "org.example.module", "", "1.0-SNAPSHOT", "jar"),
+ Paths.get(getBasedir(), "target/test-classes/unit/attached-artifact-test-1.0-SNAPSHOT.jar"));
+ artifactManager.setPath(project.getMainArtifact().get(), Paths.get(getBasedir(), "target/test-classes/unit"));
+
+ ArtifactInstallerRequest request = execute(mojo);
+
+ assertNotNull(request);
+ Collection<ProducedArtifact> artifacts = request.getArtifacts();
+ assertEquals(
+ Arrays.asList(
+ "org.apache.maven.test:maven-install-test:pom:1.0-SNAPSHOT",
+ "org.apache.maven.test:org.example.module:jar:1.0-SNAPSHOT"),
+ artifacts.stream().map(Artifact::key).toList());
+ }
+
@Test
@InjectMojo(goal = "install")
void installIfArtifactFileIsNull(InstallMojo mojo) throws Exception {