#java #maven #maven-metadata
#java #maven #maven-метаданные
Вопрос:
Я проводил некоторое тестирование с использованием Maven и понял, что могу выполнить findbugs
цель плагина Findbugs без добавления плагина в POM-файл. С другой стороны, когда мне нужно было выполнить run
цель плагина Jetty, я был вынужден добавить плагин в файл POM или сборка завершилась неудачно.
- Почему Jetty требовалась настройка в POM, а Findbugs — нет?
- Как Maven узнает, какие Findbugs выполнять (предположим, у нас есть плагины с тем же именем, но с другим идентификатором группы)?
Когда я запускаю первую команду, сборка выполняется успешно без каких-либо изменений в файле POM:
mvn findbugs:findbugs
[INFO] Scanning for projects...
[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] Building module-mytest 1.0
[INFO] ------------------------------------------------------------------------
[INFO]
[INFO] --- findbugs-maven-plugin:3.0.4:findbugs (default-cli) @ module-mytest ---
[INFO] Fork Value is true
[java] Warnings generated: 6
[INFO] Done FindBugs Analysis....
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 24.165s
[INFO] Finished at: Sun Oct 23 18:40:26 WEST 2016
[INFO] Final Memory: 21M/111M
[INFO] -----------------------------------------------------------------------
Но когда я запускаю второй, я получаю это:
mvn jetty:run
[INFO] Scanning for projects...
Downloading: http://repo.maven.apache.org/maven2/org/codehaus/mojo/maven-metadata.xml
Downloading: http://repo.maven.apache.org/maven2/org/apache/maven/plugins/maven-metadata.xml
Downloaded: http://repo.maven.apache.org/maven2/org/apache/maven/plugins/maven-metadata.xml (13 KB at 30.0 KB/sec)
Downloaded: http://repo.maven.apache.org/maven2/org/codehaus/mojo/maven-metadata.xml (20 KB at 41.0 KB/sec)
[INFO] ------------------------------------------------------------------------
[INFO] BUILD FAILURE
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 1.129s
[INFO] Finished at: Sun Oct 23 18:43:27 WEST 2016
[INFO] Final Memory: 12M/104M
[INFO] ------------------------------------------------------------------------
[ERROR] No plugin found for prefix 'jetty' in the current project and in the plugin groups [org.apache.maven.plugins, org.codehaus.mojo] available from the repositories [local (/home/hp-pc/.m2/repository), central (http://repo.maven.apache.org/maven2)] -> [Help 1]
[ERROR]
[ERROR] To see the full stack trace of the errors, re-run Maven with the -e switch.
[ERROR] Re-run Maven using the -X switch to enable full debug logging.
[ERROR]
[ERROR] For more information about the errors and possible solutions, please read the following articles:
[ERROR] [Help 1] http://cwiki.apache.org/confluence/display/MAVEN/NoPluginFoundForPrefixException
Итак, чтобы передать сборку, мне нужно было добавить следующее в файл pom:
<plugin>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-maven-plugin</artifactId>
<version>9.2.11.v20150529</version>
</plugin>
Ответ №1:
Что такое префикс и зачем он нам нужен?
Вы только что столкнулись с разрешением префикса плагина Maven. Это функция, которая позволяет пользователю вызывать цели конкретного плагина Maven, используя его префикс. При непосредственном вызове цели в командной строке вы могли бы использовать полнофункциональную форму:
mvn my.plugin.groupId:foo-maven-plugin:1.0.0:bar
Это вызвало бы цель bar
плагина Foo Maven, имеющего координаты my.plugin.groupId:foo-maven-plugin:1.0.0
(в форме groupId:artifactId:version
). Это работает хорошо, но немного многословно. Было бы неплохо вызвать эту цель более простым способом, без указания всех этих координат. Maven делает это возможным, назначая префиксы плагинам, чтобы вы могли ссылаться на этот префикс вместо целых координат с помощью:
mvn foo:bar
^^^ ^^^
| |
prefix |
|
goal
Как определяется этот префикс?
Вы можете определить префикс для каждого плагина Maven. Это соответствует простому имени, используемому для его идентификации:
Обычные форматы идентификаторов артефактов для использования являются:
maven-${prefix}-plugin
— для официальных плагинов, поддерживаемых самой командой Apache Maven (вы не должны использовать этот шаблон именования для своего плагина, смотрите Эту заметку для получения дополнительной информации)${prefix}-maven-plugin
— для плагинов из других источниковЕсли artifactId вашего плагина соответствует этому шаблону, Maven автоматически сопоставит ваш плагин с правильным префиксом в метаданных, хранящихся в пути groupId вашего плагина в репозитории.
Другими словами, если идентификатор артефакта вашего плагина назван foo-maven-plugin
, Maven автоматически присвоит ему префикс foo
. Если вам не нужно это назначение по умолчанию, вы все равно можете настроить свое собственное с помощью maven-plugin-plugin
и его goalPrefix
параметра.
Как Maven сопоставляет префиксы плагинам?
В команде
mvn foo:bar
У Maven должен быть способ определить, что foo
на самом деле означает my.plugin.groupId:foo-maven-plugin
. В settings.xml
файле вы можете добавить группы плагинов в виде:
<pluginGroups>
<pluginGroup>org.mortbay.jetty</pluginGroup>
</pluginGroups>
Что это делает, так это сообщает Maven, какой идентификатор группы он должен учитывать, когда вы используете префикс в команде. По умолчанию, и в дополнение к группам, указанным в настройках, Maven также выполняет поиск по идентификаторам групп org.apache.maven.plugins
и org.codehaus.mojo
. Он выполняет поиск по умолчанию после тех, которые вы настроили в настройках. Следовательно, с описанной выше конфигурацией и командой mvn foo:bar
Maven будет искать плагин, имеющий префикс foo
внутри идентификатора группы org.mortbay.jetty
, org.apache.maven.plugins
и org.codehaus.mojo
.
Второй шаг заключается в том, как на самом деле выполняется этот поиск. Maven загрузит файлы метаданных (или просмотрит их в вашем локальном репозитории, если они уже загружены), вызываемые maven-metadata.xml
, из каждого удаленного репозитория с этими идентификаторами групп. Если мы возьмем пример, где единственным удаленным репозиторием, который у нас есть, является Maven Central, Maven сначала загрузит http://repo1.maven.org/maven2/org/mortbay/jetty/maven-metadata.xml
и посмотрит внутри этого файла, есть ли у нас что-то сопоставляющее foo
. Обратите внимание, как идентификатор группы был преобразован в структуру каталогов в удаленном репозитории. Структура этого файла метаданных такова:
<metadata>
<plugins>
<plugin>
<name>Some Awesome Maven Plugin</name>
<prefix>somePrefix</prefix>
<artifactId>some-maven-plugin</artifactId>
</plugin>
</plugins>
</metadata>
Если ни один из <plugin>
разделов не содержит a <prefix>
, равного указанному нами ( foo
), Maven продолжит работу со следующим идентификатором группы, нажав http://repo1.maven.org/maven2/org/codehaus/mojo/maven-metadata.xml
. Опять же, если ничего не найдено, Maven, наконец, нажмет http://repo1.maven.org/maven2/org/apache/maven/plugins/maven-metadata.xml
(обратите внимание на Downloading:
журналы в вашей mvn jetty:run
команде, точно извлекающие эти последние два файла). Если ни один из них по-прежнему не найден, Maven больше ничего не может для вас сделать, и это приведет к ошибке:
[ОШИБКА] Плагин не найден для префикса ‘foo’ в текущем проекте и в группах плагинов [org.mortbay.jetty, org.apache.maven.plugins, org.codehaus.mojo] доступны из репозиториев [local (…/.m2 / repository), central (http://repo.maven.apache.org/maven2 )] -> [Справка 1]
Это ошибка, с которой вы столкнулись здесь. Однако, если во время этого поиска было найдено одно совпадение, то Maven может вывести <artifactId>
для использования.
Теперь это означает, что у него есть идентификатор группы и идентификатор артефакта. Последняя часть головоломки — это версия
Какая версия будет использоваться?
Maven выберет последний доступный, если он явно не настроен в POM (см. Следующий раздел). Все возможные версии извлекаются путем извлечения другого файла метаданных, который по-прежнему называется maven-metadata.xml
, но на этот раз находится рядом с папкой artifact id в репозитории (в отличие от приведенных выше, где он был рядом с идентификатором группы). На примере плагина Maven Clean (идентификатор группы которого и идентификатор артефакта были бы найдены с помощью вышеупомянутого механизма и команды mvn clean:clean
), maven-metadata.xml
выглядит следующим образом:
<metadata>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-clean-plugin</artifactId>
<versioning>
<latest>3.0.0</latest>
<release>3.0.0</release>
<versions>
<version>2.0-beta-1</version>
<version>2.0-rc1</version>
<version>2.0</version>
<version>2.1</version>
<!-- more versions -->
<version>3.0.0</version>
</versions>
<lastUpdated>20151022205339</lastUpdated>
</versioning>
</metadata>
Maven выберет в качестве версии <release>
версию, которая представляет последнюю версию плагина. Если этого тега там нет, он выберет <latest>
, которые представляют последнюю версию плагина, релиз или снимок. Может случиться так, что оба тега отсутствуют, и в этом случае Maven выберет первый выпуск или первый снимок из-за отсутствия выпуска из списка <version>
элементов.
Если это по-прежнему не удается, Maven больше ничего не может для вас сделать, версия не может быть выведена и выдает ошибки. Хотя это маловероятно. Теперь мы собрали идентификатор группы, идентификатор артефакта и версию; время, наконец, вызвать bar
цель нашего плагина.
В чем проблема с моей конфигурацией?
Как сказано выше, Maven просматривает определенные предопределенные идентификаторы групп внутри активных удаленных репозиториев для поиска совпадений с заданным префиксом. С помощью команды
mvn findbugs:findbugs
Maven начинает поиск с findbugs
префикса. Поскольку в нашей конфигурации их нет <pluginGroup>
в наших настройках, Maven проверяет org.codehaus.mojo
и org.apache.maven.plugins
идентификатор группы на соответствие префикса.
И он находит один: плагин Findbugs Maven опубликован под org.codehaus.mojo
идентификатором группы; действительно, вы можете найти его в maven-metadata.xml
:
<plugin>
<name>FindBugs Maven Plugin</name>
<prefix>findbugs</prefix>
<artifactId>findbugs-maven-plugin</artifactId>
</plugin>
И вы также можете найти версию, которая будет использоваться, заглянув в maven-metadata.xml
файл под findbugs-maven-plugin
только что выведенным (3.0.4 на момент написания этой статьи; и обратите внимание, насколько она точно соответствует версии в mvn findbugs:findbugs
журналах вашего вопроса). Итак, разрешение выполнено успешно, и затем Maven может продолжить вызывать findbugs
цель этого плагина.
Второй пример — команда
mvn jetty:run
Как и раньше, выполняются те же шаги разрешения, но в этом случае вы обнаружите, что префикс <jetty>
не отображается ни в одном из maven-metadata.xml
для идентификаторов групп org.codehaus.mojo
и org.apache.maven.plugins
. Итак, разрешение не выполняется, и Maven возвращает ошибку, которая у вас есть.
Но мы видели, как заставить это работать! Мы можем добавить <pluginGroup>
в наши настройки, чтобы этот идентификатор группы также можно было искать во время разрешения. Плагин Jetty Maven опубликован под идентификатором группы org.eclipse.jetty
, и если мы заглянем в соответствующий maven-metadata.xml
раздел в Maven Central, вы увидите, что <prefix>jetty</prefix>
он там есть. Итак, исправление простое: просто определите этот новый идентификатор группы для поиска в настройках:
<pluginGroups>
<pluginGroup>org.eclipse.jetty</pluginGroup>
</pluginGroups>
Теперь Maven также проверит этот идентификатор группы и успешно сопоставит jetty
префикс с org.eclipse.jetty:jetty-maven-plugin
.
Как я могу использовать определенную версию? Или я не хочу изменять свои настройки!
Конечно, все это разрешение можно обойти стороной, если вы явно определяете плагин в своем POM, что является другим решением, которое вы нашли:
<plugin>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-maven-plugin</artifactId>
<version>9.2.11.v20150529</version>
</plugin>
и используйте
mvn jetty:run
Если вы настроите плагин непосредственно в POM, разрешение префикса все равно произойдет, но оно немного замаскировано: Maven загрузит плагин из настроенных удаленных репозиториев и по пути загрузит и установит все файлы метаданных, включая maven-metadata.xml
содержащий сопоставление для префикса jetty
. Итак, поскольку он загружает его автоматически, поиск всегда выполняется успешно.
Обратите также внимание, что, поскольку плагин был определен в POM, вам не понадобились бы никакие <pluginGroup>
настройки: идентификатор группы был записан в POM. Кроме того, он гарантирует, что будет использоваться версия 9.2.11.v20150529, а не последняя.
Комментарии:
1. Это было исчерпывающее объяснение, именно то, что я искал. Спасибо.