From 629881ddf2eebba0069da726b5222cf289139dfa Mon Sep 17 00:00:00 2001 From: Guillaume Nodet Date: Tue, 23 Jun 2026 07:25:56 +0000 Subject: [PATCH 1/2] Forward-port #11985: remove redundant required MDO attrs + add extension coordinate validation (#11979) - Remove true from 13 metadata/defaulted fields in maven.mdo (forward-port of PR #11985 from maven-3.10.x) - Update Model.name description to document artifactId fallback - Add WARNING-level validation for missing extension groupId/artifactId - Add unit tests for extension coordinate validation and minimal POM validation --- api/maven-api-model/src/main/mdo/maven.mdo | 15 +-------- .../validation/DefaultModelValidatorTest.java | 12 +++++++ .../raw-model/minimal-with-parent.xml | 33 +++++++++++++++++++ .../raw-model/minimal-without-parent.xml | 29 ++++++++++++++++ .../apache/maven/project/MavenProject.java | 1 - .../impl/model/DefaultModelValidator.java | 19 +++++++++++ .../impl/model/DefaultModelValidatorTest.java | 22 +++++++++++++ .../missing-extension-coordinates.xml | 33 +++++++++++++++++++ .../raw-model/minimal-with-parent.xml | 33 +++++++++++++++++++ .../raw-model/minimal-without-parent.xml | 29 ++++++++++++++++ 10 files changed, 211 insertions(+), 15 deletions(-) create mode 100644 compat/maven-model-builder/src/test/resources/poms/validation/raw-model/minimal-with-parent.xml create mode 100644 compat/maven-model-builder/src/test/resources/poms/validation/raw-model/minimal-without-parent.xml create mode 100644 impl/maven-impl/src/test/resources/poms/validation/missing-extension-coordinates.xml create mode 100644 impl/maven-impl/src/test/resources/poms/validation/raw-model/minimal-with-parent.xml create mode 100644 impl/maven-impl/src/test/resources/poms/validation/raw-model/minimal-without-parent.xml diff --git a/api/maven-api-model/src/main/mdo/maven.mdo b/api/maven-api-model/src/main/mdo/maven.mdo index eb5618d9af02..681859de81c7 100644 --- a/api/maven-api-model/src/main/mdo/maven.mdo +++ b/api/maven-api-model/src/main/mdo/maven.mdo @@ -133,7 +133,6 @@ groupId 3.0.0+ - true A universally unique identifier for a project. It is normal to use a fully-qualified package name to distinguish it from other @@ -154,7 +153,6 @@ version 4.0.0+ - true The current version of the artifact produced by this project. String @@ -181,8 +179,7 @@ name 3.0.0+ - true - The full name of the project. + The full name of the project. If not specified, the artifactId will be used. String @@ -247,7 +244,6 @@ inceptionYear 3.0.0+ - true The year of the project's inception, specified with 4 digits. This value is used when generating copyright notices as well as being informational. String @@ -369,7 +365,6 @@ build 3.0.0+ - true Information required to build the project. Build @@ -906,7 +901,6 @@ sourceDirectory 3.0.0+ - true This element specifies a directory containing the source of the project. The generated build system will compile the sources from this directory when the project is @@ -923,7 +917,6 @@ scriptSourceDirectory 4.0.0+ - true This element specifies a directory containing the script sources of the project. This directory is meant to be different from the sourceDirectory, in that its @@ -943,7 +936,6 @@ testSourceDirectory 4.0.0+ - true This element specifies a directory containing the unit test source of the project. The generated build system will compile these directories when the project is @@ -2969,7 +2961,6 @@ id - true 4.0.0+ String default @@ -2989,7 +2980,6 @@ build 4.0.0+ - true Information required to build the project. BuildBase @@ -3328,7 +3318,6 @@ groupId 4.0.0+ String - true org.apache.maven.plugins The group ID of the reporting plugin in the repository. @@ -3422,7 +3411,6 @@ id String - true The unique id for this report set, to be used during POM inheritance and profile injection for merging of report sets. @@ -3431,7 +3419,6 @@ reports 4.0.0+ - true The list of reports from this plugin which should be generated from this set. String diff --git a/compat/maven-model-builder/src/test/java/org/apache/maven/model/validation/DefaultModelValidatorTest.java b/compat/maven-model-builder/src/test/java/org/apache/maven/model/validation/DefaultModelValidatorTest.java index 08536d3d87f8..28fb582a3f0b 100644 --- a/compat/maven-model-builder/src/test/java/org/apache/maven/model/validation/DefaultModelValidatorTest.java +++ b/compat/maven-model-builder/src/test/java/org/apache/maven/model/validation/DefaultModelValidatorTest.java @@ -966,4 +966,16 @@ void testConcurrentValidation() throws Exception { "Concurrent validation failed: " + failure.get().getMessage(), failure.get()); } } + + @Test + void testMinimalWithParent() throws Exception { + SimpleProblemCollector result = validateRaw("raw-model/minimal-with-parent.xml"); + assertViolations(result, 0, 0, 0); + } + + @Test + void testMinimalWithoutParent() throws Exception { + SimpleProblemCollector result = validateRaw("raw-model/minimal-without-parent.xml"); + assertViolations(result, 0, 0, 0); + } } diff --git a/compat/maven-model-builder/src/test/resources/poms/validation/raw-model/minimal-with-parent.xml b/compat/maven-model-builder/src/test/resources/poms/validation/raw-model/minimal-with-parent.xml new file mode 100644 index 000000000000..b373d50722d9 --- /dev/null +++ b/compat/maven-model-builder/src/test/resources/poms/validation/raw-model/minimal-with-parent.xml @@ -0,0 +1,33 @@ + + + + 4.0.0 + + + org.apache.maven.validation + parent + 1 + + + project + + diff --git a/compat/maven-model-builder/src/test/resources/poms/validation/raw-model/minimal-without-parent.xml b/compat/maven-model-builder/src/test/resources/poms/validation/raw-model/minimal-without-parent.xml new file mode 100644 index 000000000000..274a34d2a087 --- /dev/null +++ b/compat/maven-model-builder/src/test/resources/poms/validation/raw-model/minimal-without-parent.xml @@ -0,0 +1,29 @@ + + + + 4.0.0 + + groupId + project + project + + diff --git a/impl/maven-core/src/main/java/org/apache/maven/project/MavenProject.java b/impl/maven-core/src/main/java/org/apache/maven/project/MavenProject.java index e6c2c05acbf0..e0f7d1c6e65c 100644 --- a/impl/maven-core/src/main/java/org/apache/maven/project/MavenProject.java +++ b/impl/maven-core/src/main/java/org/apache/maven/project/MavenProject.java @@ -632,7 +632,6 @@ public void setName(String name) { } public String getName() { - // TODO this should not be allowed to be null. if (getModel().getName() != null) { return getModel().getName(); } else { diff --git a/impl/maven-impl/src/main/java/org/apache/maven/impl/model/DefaultModelValidator.java b/impl/maven-impl/src/main/java/org/apache/maven/impl/model/DefaultModelValidator.java index 8cc8cb3459b3..c040fbbc7546 100644 --- a/impl/maven-impl/src/main/java/org/apache/maven/impl/model/DefaultModelValidator.java +++ b/impl/maven-impl/src/main/java/org/apache/maven/impl/model/DefaultModelValidator.java @@ -55,6 +55,7 @@ import org.apache.maven.api.model.DependencyManagement; import org.apache.maven.api.model.DistributionManagement; import org.apache.maven.api.model.Exclusion; +import org.apache.maven.api.model.Extension; import org.apache.maven.api.model.InputLocation; import org.apache.maven.api.model.InputLocationTracker; import org.apache.maven.api.model.Model; @@ -1068,6 +1069,24 @@ public void validateEffectiveModel( validate20EffectivePluginDependencies(problems, plugin, validationLevel); } + for (Extension extension : build.getExtensions()) { + validateStringNotEmpty( + "build.extensions.extension.groupId", + problems, + Severity.WARNING, + Version.V20, + extension.getGroupId(), + extension); + + validateStringNotEmpty( + "build.extensions.extension.artifactId", + problems, + Severity.WARNING, + Version.V20, + extension.getArtifactId(), + extension); + } + validate20RawResources(problems, build.getResources(), "build.resources.resource.", validationLevel); validate20RawResources( diff --git a/impl/maven-impl/src/test/java/org/apache/maven/impl/model/DefaultModelValidatorTest.java b/impl/maven-impl/src/test/java/org/apache/maven/impl/model/DefaultModelValidatorTest.java index 591191e8920f..5b0cdd15acc7 100644 --- a/impl/maven-impl/src/test/java/org/apache/maven/impl/model/DefaultModelValidatorTest.java +++ b/impl/maven-impl/src/test/java/org/apache/maven/impl/model/DefaultModelValidatorTest.java @@ -1022,4 +1022,26 @@ void profileActivationConditionWithBasedirExpression() throws Exception { "raw-model/profile-activation-condition-with-basedir.xml", ModelValidator.VALIDATION_LEVEL_STRICT); assertViolations(result, 0, 0, 0); } + + @Test + void testMissingExtensionCoordinates() throws Exception { + SimpleProblemCollector result = validate("missing-extension-coordinates.xml"); + + assertViolations(result, 0, 0, 2); + + assertContains(result.getWarnings().get(0), "'build.extensions.extension.groupId' is missing."); + assertContains(result.getWarnings().get(1), "'build.extensions.extension.artifactId' is missing."); + } + + @Test + void minimalWithParent() throws Exception { + SimpleProblemCollector result = validateRaw("raw-model/minimal-with-parent.xml"); + assertViolations(result, 0, 0, 0); + } + + @Test + void minimalWithoutParent() throws Exception { + SimpleProblemCollector result = validateRaw("raw-model/minimal-without-parent.xml"); + assertViolations(result, 0, 0, 0); + } } diff --git a/impl/maven-impl/src/test/resources/poms/validation/missing-extension-coordinates.xml b/impl/maven-impl/src/test/resources/poms/validation/missing-extension-coordinates.xml new file mode 100644 index 000000000000..78c99289b293 --- /dev/null +++ b/impl/maven-impl/src/test/resources/poms/validation/missing-extension-coordinates.xml @@ -0,0 +1,33 @@ + + + + 4.0.0 + foo + foo + 99.44 + jar + + + + 1.0 + + + + diff --git a/impl/maven-impl/src/test/resources/poms/validation/raw-model/minimal-with-parent.xml b/impl/maven-impl/src/test/resources/poms/validation/raw-model/minimal-with-parent.xml new file mode 100644 index 000000000000..b373d50722d9 --- /dev/null +++ b/impl/maven-impl/src/test/resources/poms/validation/raw-model/minimal-with-parent.xml @@ -0,0 +1,33 @@ + + + + 4.0.0 + + + org.apache.maven.validation + parent + 1 + + + project + + diff --git a/impl/maven-impl/src/test/resources/poms/validation/raw-model/minimal-without-parent.xml b/impl/maven-impl/src/test/resources/poms/validation/raw-model/minimal-without-parent.xml new file mode 100644 index 000000000000..274a34d2a087 --- /dev/null +++ b/impl/maven-impl/src/test/resources/poms/validation/raw-model/minimal-without-parent.xml @@ -0,0 +1,29 @@ + + + + 4.0.0 + + groupId + project + project + + From d9ae70ae36bd35027e7902f12e8ca4abab595761 Mon Sep 17 00:00:00 2001 From: Guillaume Nodet Date: Thu, 25 Jun 2026 04:25:29 +0000 Subject: [PATCH 2/2] Address Copilot review comments (port from #12347) - Fix field description in maven.mdo to not claim the model field defaults to artifactId (the fallback is a runtime behavior in MavenProject#getName(), not a model-level default) Note: unlike the 4.0.x branch, the test POM resources minimal-with-parent.xml and minimal-without-parent.xml are actually referenced by tests in impl/maven-impl on master, so they are kept. Co-Authored-By: Claude Opus 4.6 --- api/maven-api-model/src/main/mdo/maven.mdo | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api/maven-api-model/src/main/mdo/maven.mdo b/api/maven-api-model/src/main/mdo/maven.mdo index 681859de81c7..c5057ade7c1f 100644 --- a/api/maven-api-model/src/main/mdo/maven.mdo +++ b/api/maven-api-model/src/main/mdo/maven.mdo @@ -179,7 +179,7 @@ name 3.0.0+ - The full name of the project. If not specified, the artifactId will be used. + The full name of the project. String