You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@maven.apache.org by el...@apache.org on 2025/02/19 14:06:54 UTC

(maven-site) branch artifacts created (now a96cb7dc)

This is an automated email from the ASF dual-hosted git repository.

elharo pushed a change to branch artifacts
in repository https://gitbox.apache.org/repos/asf/maven-site.git


      at a96cb7dc Clarify types, extensions, and classifiers

This branch includes the following new commits:

     new a96cb7dc Clarify types, extensions, and classifiers

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-site) 01/01: Clarify types, extensions, and classifiers

Posted by el...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

elharo pushed a commit to branch artifacts
in repository https://gitbox.apache.org/repos/asf/maven-site.git

commit a96cb7dc283f0d2495b50e85fa0e878e75aa39d0
Author: Elliotte Rusty Harold <el...@ibiblio.org>
AuthorDate: Wed Feb 19 09:06:38 2025 -0500

    Clarify types, extensions, and classifiers
---
 content/markdown/repositories/artifacts.md | 107 +++++++++++++++--------------
 1 file changed, 57 insertions(+), 50 deletions(-)

diff --git a/content/markdown/repositories/artifacts.md b/content/markdown/repositories/artifacts.md
index 4ddced3e..0daa75bf 100644
--- a/content/markdown/repositories/artifacts.md
+++ b/content/markdown/repositories/artifacts.md
@@ -55,48 +55,45 @@ 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?
+## But where do I set the artifact extension?
 
-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.
+In short, nowhere. Or maybe "you rarely have to". The Maven POM
+derives artifact extensions from dependency elements with some extra logic.
 
-In case of "project" and "parent project" POMs (after the POM is made into an effective POM, that is, parent values have been inherited):
+In the case of "project" and "parent project" POMs
+(after the POM is made into an effective POM, that is, parent values have been inherited):
 
-| 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 Property | Project POM (pom.xml) |  Property Value   |
+|-------------------|-----------------------|-------------------|
+| groupId           | `project/groupId`     | -> group ID       |
+| artifactId        | `project/artifactId`  | -> artifact ID    |
+| version           | `project/version`     | -> version string |
+| classifier        | -                     | "" (always)       |
+| extension         | -                     | `pom` (always)    |
 
 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 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)         |
+| Artifact Property |           Plugin in Project POM           |  Property 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) |
 
-And finally, in the case of "dependencies", this is the mapping (no, scope is NOT part of artifact coordinates):
+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 |
+| Artifact Property |          Dependency in Project POM           |              Property 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 |
 
-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.
+Here, we need to make a short detour to explain how "dependency type"
+provides an artifact extension and classifier.
 
 Out of the box, Maven Core defines the [following "types" (handled by the same named `ArtifactHandler` components)](/ref/current/maven-core/artifact-handlers.html):
 
@@ -115,16 +112,22 @@ 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` ands 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 also 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.
+
+<!-- TODO what if an explicit classifier element conflicts with the
+classifier inferred from the type? Which wins? -->
 
-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 +149,20 @@ 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.
+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 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.
+Note: In this case, the first way is somewhat "explicit", and is
+recommended. Not so for the cases when type handler carries important
+extra information (such as custom packaging), where 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.
 
 ## 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.
+In short, this is how various Maven bits like "project", "parent
+project", "plugin", "extension", and "dependency" derive artifact
+coordinates from POM elements.