maven-assembly-plugin: как использовать appendAssemblyId
У меня есть многомодульный проект Maven, и в одном модуле я хочу создать два артефакта во время сборки:
- Основной артефакт - это библиотека jar, от которой будут зависеть некоторые другие модули.
- Исполняемый файл JAR, который выполняет некоторые вспомогательные функции. Никакие другие модули не зависят от этого и предназначены только для пользователя, чтобы запускать его вручную в определенных ситуациях.
Вот код, который я использую для настройки maven-assembly-plugin
плагин:
<plugin>
<artifactId>
maven-assembly-plugin
</artifactId>
<version>2.4</version>
<executions>
<execution>
<id>dist-assembly</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
<configuration>
<finalName>bso</finalName>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
<finalName>helper-${project.version}</finalName>
<appendAssemblyId>false</appendAssemblyId>
<archive>
<manifest>
<mainClass>HelperMain<mainClass>
</manifest>
</archive>
</configuration>
</execution>
</executions>
</plugin>
Я устанавливаю appendAssemblyId
в false
потому что иначе -jar-with-dependencies
будет добавлен к окончательному названию, и я не вижу необходимости в этом. Отказ от этого дает более чистое и простое в использовании имя файла.
Когда я бегу mvn integration-test
тогда я получаю следующие предупреждения:
[ПРЕДУПРЕЖДЕНИЕ] Параметры конфигурации: для 'appendAssemblyId' установлено значение false, а для 'классификатора' отсутствует. Вместо прикрепления файла сборки: [...]/target/helper-5.0.0-SNAPSHOT.jar, он станет файлом для основного артефакта проекта.
ПРИМЕЧАНИЕ. Если для этого проекта предусмотрено несколько дескрипторов или форматов дескрипторов, значение этого файла будет недетерминированным!
[ПРЕДУПРЕЖДЕНИЕ] Замена существующего файла основного артефакта проекта: [...]/target/my.module-5.0.0-SNAPSHOT.jar файлом сборки: [...] / target / helper-5.0.0- SNAPSHOT.jar
Есть две вещи, которые меня раздражают:
Несмотря на то, что в предупреждении утверждается, что он заменит my.module-5.0.0-SNAPSHOT.jar на helper-5.0.0-SNAPSHOT.jar, на самом деле это не так, и после завершения сборки оба файла по-прежнему имеют разные размеры.
Почему вообще появляется предупреждение о замене артефакта?
Кажется, что
classifier
не рекомендуется, почему предупреждение просит меня использовать его?
2 ответа
Это потому, что вы неправильно интерпретируете предупреждения.
Давайте подведем итоги. Проект Maven, который не является типом pom
по умолчанию всегда производит то, что называется главным артефактом. Для JAR этот артефакт является результатом упаковки скомпилированных источников в JAR; для WAR это результат построения веб-приложения.
Важно помнить, что этот артефакт прикреплен к проекту: эта терминология полезна при установке проекта (с mvn install
), развернуто (с mvn deploy
) или выпущен (с maven-release-plugin
). Присоединенный означает, что этот артефакт будет установлен / развернут / выпущен, когда проект будет. Не все файлы, созданные во время сборки Maven (в основном, все под target
папка) есть; только файлы, которые были прикреплены. Таким образом, вы можете очень хорошо создавать много файлов под target
но есть один установленный артефакт.
Наряду с этим основным артефактом вы можете захотеть, чтобы ваша сборка производила другие артефакты для установки или развертывания. Это концепция дополнительных или вторичных прикрепленных артефактов. Основными примерами являются Javadoc или источники: обычно, когда проект выпускается, его Javadoc и его источники также являются. И вот где понятие classifier
пинает.
В репозитории Maven каждый файл должен соответствовать одному и тому же соглашению об именах:artifactId-version(-classifier).type
, У каждого вторичного артефакта будет тот же GAV (идентификатор группы, идентификатор артефакта, версия), что и у основного артефакта, поэтому, если вы хотите поместить в репозиторий Maven репозиторий 1 основной артефакт и 1 прикрепленный артефакт (как это было бы в случае с основным JAR вдоль с его JAR Javadoc и JAR источниками), вам нужен какой-то способ их различить. Что есть то, чтоclassifier
для: отличить вторичные артефакты от основного артефакта.
Давайте вернемся к вашему примеру сейчас. Ваш проект Maven, который имеет jar
упаковка, по умолчанию создаст основной JAR-артефакт my.module-5.0.0-SNAPSHOT.jar
; по умолчанию этот основной JAR-файл подключен к проекту (и готов к установке / развертыванию). Теперь вы настраиваете maven-assembly-plugin
создать новый артефакт JAR (называетсяhelper-5.0.0-SNAPSHOT.jar
но это действительно не имеет значения). Модуль сборки по умолчанию присоединяет к проекту артефакт, который он создает. Таким образом, вы получите 2 прикрепленных артефакта
- с таким же идентификатором артефакта
my.module
; тот факт, что файл на диске внутриtarget
папка называетсяhelper
для одного не имеет значения, имеют значение только координаты GAV - имея ту же версию
5.0.0-SNAPSHOT
- имея одинаковую упаковку JAR
и нет классификатора, чтобы различать их. Это то, что вызывает предупреждение: в конечном итоге вы присоединяете к проекту вторичный артефакт, который эффективно заменяет основной, просто потому, что он имеет те же координаты. Итак, результат:
- Оба файла имеют разные имена на диске внутри
target
, но это не имеет значения, потому что - Оба имеют одинаковые координаты, поэтому выживет только 1.
Это тот, что создан плагином Assembly, который выиграет конфликт и заменит прикрепленный основной артефакт.
Если хочешь убедить себя во всем этом, бегиmvn clean install
на проекте и проверьте свой локальный репо. Вы заметите, что толькоjar-with-dependencies
Артефакт будет установлен. Другой (главный артефакт) испортился.
Вы также можете настроить<distributionManagement>
:
<distributionManagement>
<repository>
<id>local-repo-test</id>
<url>file://...</url>
</repository>
</distributionManagement>
и вызватьmvn clean deploy
, Затем вы можете проверить, что единственным развернутым артефактом будетjar-with-dependencies
,
Конечная нота: да,classifier
Параметр плагина сборки устарел, потому что вы просто должны использовать идентификатор сборки в качестве классификатора.
Если вы хотите использовать предопределенный дескрипторjar-with-dependencies
но если у вас есть классификатор, отличный от «jar-with-dependents», вы можете просто скопировать формат «jar-with-dependents» в свой собственный файл сборки и переименовать идентификатор в любой классификатор, который вам нужен.
Вот предопределенный формат дескриптора (источник: https://maven.apache.org/plugins/maven-assembly-plugin/descriptor-refs.html#jar-with-dependentities ):
<assembly xmlns="http://maven.apache.org/ASSEMBLY/2.2.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/ASSEMBLY/2.2.0 https://maven.apache.org/xsd/assembly-2.2.0.xsd">
<!-- TODO: a jarjar format would be better -->
<id>jar-with-dependencies</id>
<formats>
<format>jar</format>
</formats>
<includeBaseDirectory>false</includeBaseDirectory>
<dependencySets>
<dependencySet>
<outputDirectory>/</outputDirectory>
<useProjectArtifact>true</useProjectArtifact>
<unpack>true</unpack>
<scope>runtime</scope>
</dependencySet>
</dependencySets>
</assembly>
Скопируйте это в свой сборочный.xml и переименуйте идентификатор:
<assembly xmlns="http://maven.apache.org/ASSEMBLY/2.2.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/ASSEMBLY/2.2.0 https://maven.apache.org/xsd/assembly-2.2.0.xsd">
<!-- TODO: a jarjar format would be better -->
<id>my-classifier</id>
<formats>
<format>jar</format>
</formats>
<includeBaseDirectory>false</includeBaseDirectory>
<dependencySets>
<dependencySet>
<outputDirectory>/</outputDirectory>
<useProjectArtifact>true</useProjectArtifact>
<unpack>true</unpack>
<scope>runtime</scope>
</dependencySet>
</dependencySets>
</assembly>
Теперь, если вы установите<appendAssemblyId>
до true, вы получите тот же jar, что и раньше, но с собственным классификатором.