This is an automated email from the ASF dual-hosted git repository. elharo pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/maven-site.git
The following commit(s) were added to refs/heads/master by this push: new 3035c940 Clarify types, extensions, and classifiers (#695) 3035c940 is described below commit 3035c940d094e5fafe173e40d2f36ca6d4dbf4e6 Author: Elliotte Rusty Harold <elh...@users.noreply.github.com> AuthorDate: Mon Mar 3 13:16:55 2025 +0000 Clarify types, extensions, and classifiers (#695) * Clarify types, extensions, and classifiers --- content/markdown/repositories/artifacts.md | 159 ++++++++++++++++++----------- 1 file changed, 101 insertions(+), 58 deletions(-) diff --git a/content/markdown/repositories/artifacts.md b/content/markdown/repositories/artifacts.md index 4ddced3e..00395ac2 100644 --- a/content/markdown/repositories/artifacts.md +++ b/content/markdown/repositories/artifacts.md @@ -37,7 +37,7 @@ issues without you noticing it. In short, these cases should be avoided. ## Artifact Properties -The artifacts that Maven uses internally have the following properties: +The artifacts that Maven uses have the following coordinate properties: | Name | Description | |-------------|-------------------------------------------------| @@ -55,50 +55,34 @@ snapshot version "1.0-20220119.164608-1" has the `baseVersion` "1.0-SNAPSHOT". So, `version` and `baseVersion` are linked, derived from each other, but **they have different values only in the case of snapshots**. -## But where do I set the Artifact extension? +Maven pom.xml files identify artifacts via coordinates in four different ways, depending +on what the artifact is and how it will be used. -In short, nowhere. Or maybe "you rarely have to". The Maven POM (where you declare your project, parent project, -dependencies, plugins and other items), maps those elements onto artifact extensions with some extra logic. +* A dependency of the project, often though not always a jar archive, is referenced by + a `dependency` element in either the `dependencies` or `dependenciesManagement` section. +* The pom.xml file itself has coordinates given by the top-level `groupId`, + `artifactId`, and `version` elements. +* A build plugin is referenced by a `plugin` element in the `plugins` section. +* A build extension is referenced by an `extension` element in the `extensions` section. -In case of "project" and "parent project" POMs (after the POM is made into an effective POM, that is, parent values have been inherited): +### Coordinates of Dependencies -| Artifact Property | Project POM (pom.xml) | POM Artifact | -|-------------------|-----------------------|----------------| -| groupId | `project/groupId` | -> groupId | -| artifactId | `project/artifactId` | -> artifactId | -| version | `project/version` | -> version | -| classifier | - | "" (always) | -| extension | - | `pom` (always) | +Artifact coordinates for dependencies are calculated from a `dependency` element: -In the case of "build plugins" and "build extensions", as they are JARs, this is how corresponding elements are mapped -(for build extension change the XML path prefix to `project/build/extensions/extension[x]`): +| Artifact Coordinate | POM element | Coordinate Value | +|---------------------|----------------------------------------------|-------------------------------------------| +| groupId | `project/dependencies/dependency/groupId` | -> group ID | +| artifactId | `project/dependencies/dependency/artifactId` | -> artifact ID | +| version | `project/dependencies/dependency/version` | -> version string | +| classifier | `project/dependencies/dependency/classifier` | -> classifier, or type handler provided | +| extension | `project/dependencies/dependency/type` | -> type handler provided, or same as type | -| Artifact Property | Plugin in Project POM | Plugin/Extension Artifact | -|-------------------|----------------------------------------------|---------------------------| -| groupId | `project/build/plugins/plugin[x]/groupId` | -> groupId | -| artifactId | `project/build/plugins/plugin[x]/artifactId` | -> artifactId | -| version | `project/build/plugins/plugin[x]/version` | -> version | -| classifier | - | -> "" (always) | -| extension | - | -> `jar` (always) | +This also applies when the `dependency` element is a child of a `dependencyManagement` element. -And finally, in the case of "dependencies", this is the mapping (no, scope is NOT part of artifact coordinates): - -| Artifact Property | Dependency in Project POM | Dependency Artifact | -|-------------------|-------------------------------------------------|-------------------------------------------| -| groupId | `project/dependencies/dependency[x]/groupId` | -> groupId | -| artifactId | `project/dependencies/dependency[x]/artifactId` | -> artifactId | -| version | `project/dependencies/dependency[x]/version` | -> version | -| classifier | `project/dependencies/dependency[x]/classifier` | -> classifier | -| extension | `project/dependencies/dependency[x]/type` | -> type handler provided, or same as type | - -Here, we need to make a short detour to explain "dependency type" and how it becomes an artifact extension. - -A dependency type determines how the artifact referenced by the dependency is used. -For example, should it be added to comple-time classpath, the test classpath, or both? -Plugins and extensions may define new types. This is usually required for plugins introducing -a "packaging" (lifecycle mapping) by providing `ArtifactHandler` components with a name corresponding to type name. - -Out of the box, Maven Core defines the [following "types" (handled by the same named `ArtifactHandler` components)](/ref/current/maven-core/artifact-handlers.html): +Notice that the `dependency` element does not have an `extension` element. +Instead it has a `type` element which is +used to derive the extension and sometimes the classifier. +Out of the box, Maven Core defines 11 "types" [(handled by the same named `ArtifactHandler` components)](/ref/current/maven-core/artifact-handlers.html): | Type Name | Extension | Classifier | |--------------|-----------|--------------| @@ -115,16 +99,19 @@ Out of the box, Maven Core defines the [following "types" (handled by the same n | war | `war` | | | **any** | any | | -From the table above, we can see that if we define the dependency type as "war", we will hit the "war" handler. That will -result in using the `war` extension (which may not be obvious, as the type and extension we end up with are the same, but internally this -indirection does happen). The "test-jar" is more obvious, as it translates to the `jar` extension. Finally, the **any** -last row will be used if none of the above match. Hence in that case the "type" is used as the "extension". For example. -if the dependency type is `<type>tar.gz</type>`, the extension will also be `tar.gz`. -This table may be extended by plugins and extensions used in the build. +From the table above, you can see that if the dependency type is "war", +the extension is also `war` and the classifier is the value of the +`classifier` element (if present) or the empty string if the `classifier` element +is not present. If the type is "test-jar", the extension is +"jar" and the classifier is "tests". If the type is not one of these 11 names, then the +value of the "type" is used as the extension. For example, if the `type` element +is `<type>tar.gz</type>`, the extension will be `tar.gz`, and the classifier will +be set by the `classifier` element. This +table may be extended by plugins and extensions used in the build. -Also, this has "interesting" consequences. Consider the artifact -`org.project:reusable-test-support:1.0:tests:jar`. With the type handlers above, maybe surprisingly, the dependency to -this very same artifact can be described in two ways: +This has "interesting" consequences. Consider the artifact +`org.project:reusable-test-support:1.0:tests:jar`. Maybe surprisingly, +a dependency on this artifact can be described in two ways: ```xml <dependency> @@ -146,16 +133,72 @@ and the equivalent dependency would be: </dependency> ``` -The obvious difference is presence of `classifier` in first case, while in second lack of it but presence of `type` "test-jar", -that in the other hand, implies a classifier of "tests". In both cases, the extension is "jar". The first it uses the default value for this property, while the second type defines it. - -Note: In this very case, the first way is somewhat "explicit", and is recommended. Not so for the -cases when type handler carries some important extra information (like some custom packaging), where using `type` -is more appropriate. Simply put, in this case the type "test-jar" is like an alias for ordinary JARs with the "tests" -classifier. +The obvious difference is that the first example has the `<classifier>tests</classifier>`, +while the second has the `<type>test-jar</type>`. The `type` "test-jar" +implies a classifier of "tests". In both cases, the extension is "jar". +The first uses the default value for the extension, while the second +derives it from the type. + +Note: In this case, the first way is somewhat "explicit", and is +recommended. When the type handler carries important +extra information such as custom packaging, using `type` is more +appropriate. Simply put, in this example the type "test-jar" is like an +alias for ordinary JARs with the "tests" classifier. + +### Coordinates of POM Files + +The coordinates of a POM artifact that contain a project's pom.xml file are +derived from the top-level `groupId`, `artifactId`, and `version` +elements in that pom.xml file: + +| Artifact Coordinate | POM element | Coordinate Value | +|---------------------|----------------------|-------------------| +| groupId | `project/groupId` | -> group ID | +| artifactId | `project/artifactId` | -> artifact ID | +| version | `project/version` | -> version string | +| classifier | - | "" (always) | +| extension | - | "pom" (always) | + +Coordinate values are computed after the POM is made into an effective POM; +that is, after parent values have been inherited. + +### Coordinates of Build Plugins and Build Extensions + +Build plugin and build extension artifacts are JARs. For build plugins, +this is how the corresponding coordinates are computed from a `plugin` element: + +| Artifact Coordinate | POM element | Coordinate Value | +|---------------------|-------------------------------------------|-------------------| +| groupId | `project/build/plugins/plugin/groupId` | -> group ID | +| artifactId | `project/build/plugins/plugin/artifactId` | -> artifact ID | +| version | `project/build/plugins/plugin/version` | -> version string | +| classifier | - | -> "" (always) | +| extension | - | -> "jar" (always) | + +This also applies when the `plugin` element is a child of a `pluginManagement` element. + +Build extensions are similarly computed from an `extension` element (which is not the +same as and should not be confused with the extension artifact coordinate): + +| Artifact Coordinate | POM element | Coordinate Value | +|---------------------|-------------------------------------------------|-------------------| +| groupId | `project/build/extensions/extension/groupId` | -> group ID | +| artifactId | `project/build/extensions/extension/artifactId` | -> artifact ID | +| version | `project/build/extensions/extension/version` | -> version string | +| classifier | - | -> "" (always) | +| extension | - | -> "jar" (always) | + +Note: The *extension artifact coordinate* and a *Maven build extension* are two completely different +things that unfortunately share the name "extension". A +[Maven build extension](https://maven.apache.org/guides/mini/guide-using-extensions.html) is +a JAR archive that is added to the project class loader's classpath. +It is referenced by an `extension` element in pom.xml. An extension coordinate +is usually the filename extension of an artifact's JAR file such as jar, zip, or txt. +This extension is most often set to an implicit default value, +but can be changed by the `type` child of a `dependency` element. ## Summary -In short, this is how various Maven bits like "project", "parent project", "plugin", "extension" and "dependency" -have artifact coordinates mapped from POM elements. Using this knowledge, we can always deduce the artifact coordinate -of these POM elements. +This is how various Maven bits like "project", "parent +project", "plugin", "extension", and "dependency" derive artifact +coordinates from POM elements.