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.

Reply via email to