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 <[email protected]>
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.