Что будет?
В статье будут примеры настройки settings, pom, описание поиска в репозиториях. Не будет настройки nexus\artifactory, проблем связанных с ними.
Начнем с простого
Добавим зависимость на spring в своем pom.
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.0.0.RELEASE</version>
</dependency>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>test</groupId>
<artifactId>dependency-testing</artifactId>
<version>1.0.0</version>
<name>Dependency test</name>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.0.0.RELEASE</version>
</dependency>
</dependencies>
</project>
Предположим, что мы только установили maven и не меняли никаких настроек. После инициализации поиска зависимостей через сборку maven, или через ide, maven сначала проверит наличие артефакта в локальном репозитории в директории
${user.home}/.m2/repository/
.Если в локальном репозитории артефакта нет, то запрос пойдет в репозиторий central.
Мы не указывали этот репозиторий, но он всегда добавляется мавеном при сборке.
Сконфигурируем settings.xml
<?xml version="1.0" encoding="UTF-8"?>
<settings xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0 http://maven.apache.org/xsd/settings-1.0.0.xsd"
xmlns="http://maven.apache.org/SETTINGS/1.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<profiles>
<profile>
<repositories>
<repository>
<id>nexus-corp</id>
<name>nexus-corp-repo</name>
<url>http://nexus.mycompany.com:8081/nexus/central/</url>
</repository>
</repositories>
<id>nexus</id>
</profile>
</profiles>
<activeProfiles>
<activeProfile>nexus</activeProfile>
</activeProfiles>
</settings>
Подробнее про settings.xml
С такой конфигурацией порядок поиска будет аналогичен варианту с конфигурацией по умолчанию, но появится дополнительный шаг. Перед тем как пойти в central, мавен попытается скачать артефакт из репозитория nexus-corp.
Зеркало
Добавим зеркало для репозитория nexus-corp.
<mirror>
<id>nexus-corp-mirror</id>
<name>nexus-corp-mirror</name>
<url>http://nexus.mirror.mycompany.com:8081/nexus/central/</url>
<mirrorOf>nexus-corp</mirrorOf>
</mirror>
- недоступен внешний репозиторий
- для экономии внешнего трафика
- чтобы переопределить репозиторий из settings\pom
Подробнее про зеркала
Когда maven дойдет до шага поиска в репозитории nexus-corp, то вместо него попытается найти артефакт в репозитории nexus-corp-mirror.
При этом если он не найдет его в nexus-corp-mirror, то запроса в nexus-corp не будет.
А если добавить зеркало с wildcard, то все запросы будут направлены на него, если не указаны другие зеркала.
<mirror>
<id>all</id>
<name>nexus-corp-mirror</name>
<url>http://nexus.mirror.mycompany.com:8081/nexus/central/</url>
<mirrorOf>*</mirrorOf>
</mirror>
Порядок поиска
В общем случае схема поиска будет такой:
1. Поиск в локальном репо
2. Поиск в репозиториях в порядке объявления с учетом приоритета (либо в их зеркалах)
В конце добавляется central. Он всегда последний, если не был перезаписан.
Merge конфигураций
Перед выполнением сборки maven «склеивает» конфиги:
- глобальный —
${maven.home}/conf/settings.xml
- пользовательский —
${user.home}/.m2/settings.xml
- проектный —
pom.xml
С приоритетом конфигурацией у меня случился небольшой конфуз. В документации написано:
The former settings.xml are also called global settings, the latter settings.xml are referred to as user settings. If both files exists, their contents gets merged, with the user-specific settings.xml being dominant.По факту, если при склеивании не возникло конфликтов, то приоритет репозиториев следующий, в порядке уменьшения:
- глобальный
- пользовательский
- pom.xml
Из примеров ниже порядок будет следующий:
- repo-global-setting1
- repo-user-setting1
- repo-user-setting2
- repo-pom1
- central
<?xml version="1.0" encoding="UTF-8"?>
<settings xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0 http://maven.apache.org/xsd/settings-1.0.0.xsd"
xmlns="http://maven.apache.org/SETTINGS/1.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<profiles>
<profile>
<repositories>
<repository>
<id>repo-global-setting1</id>
<url>http://nexus.mycompany.com:8081/nexus/repo-global-setting1-url/</url>
</repository>
</repositories>
<id>g-nexus</id>
</profile>
</profiles>
<activeProfiles>
<activeProfile>g-nexus</activeProfile>
</activeProfiles>
</settings>
<?xml version="1.0" encoding="UTF-8"?>
<settings xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0 http://maven.apache.org/xsd/settings-1.0.0.xsd"
xmlns="http://maven.apache.org/SETTINGS/1.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<profiles>
<profile>
<repositories>
<repository>
<id>repo-user-setting1</id>
<url>http://nexus.mycompany.com:8081/nexus/repo-user-setting1-url/</url>
</repository>
<repository>
<id>repo-user-setting2</id>
<url>http://nexus.mycompany.com:8081/nexus/repo-user-setting2-url/</url>
</repository>
</repositories>
<id>nexus</id>
</profile>
</profiles>
<activeProfiles>
<activeProfile>nexus</activeProfile>
</activeProfiles>
</settings>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>test</groupId>
<artifactId>dependency-testing</artifactId>
<version>1.0.0</version>
<name>Dependency test</name>
<repositories>
<repository>
<id>repo-pom1</id>
<url>http://nexus.mycompany.com:8081/nexus/repo-pom1-url/</url>
</repository>
</repositories>
<dependencies>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.25</version>
</dependency>
</dependencies>
</project>
С разрешением конфликтов появилось еще большее непонимание. Если объявить репозиторий с одним id в разных профилях, то приоритет имеет глобальный конфиг, но если объявить профили с одинаковым id, то приоритет имеет пользовательский. Дальше экспериментировать уже не стал.
Поиск пропавших
Так что делать с ошибкой
Could not resolve dependencies for project myproject:jar:1.0.0: Failed to collect dependencies at com.someproject:artifact-name:jar:1.0.0
?1. Проверить правильность имени и версии артефакта.
2. Посмотреть какие репозитории\зеркала указаны в ваших settings\pom.
3. Проверить наличие артефакта в этих репозиторииях
Обычно проблема решается на втором шаге, но кроме этих пунктов встречаются проблемы из-за прокси, также бывает, что скаченный jar поврежден(хотя сам я сталкивался с таким всего один раз).
Для snapshot версий полезна команда -U — принудительное обновление snapshot зависимостей. По умолчанию maven обновляет их только после истечения таймаута раз в день(параметр updatePolicy)
В ролях
maven 3.5.0
jdk 1.8
debug логи maven
Комментарии (8)
Heruvimka Автор
12.10.2017 12:481. Под недоступен внешний репозиторий я подразумевал, что недоступен, например, maven central, если разработка ведется в сети без доступа в интернет. Во внутренней сети можно поднять зеркало, которое будет проксировать запросы к central.
Как вы экономите внешний трафик?
Подразумевается экономия внешнего трафика. Если вы поставите зеркало для central, то артефакт будет скачан один раз и закеширован в локальном nexus, если зеркала не будет, то артефакт будет скачиваться из central при обращении каждого нового пользователя.
2. Ответил выше?lokkersp
12.10.2017 16:122 не ответили. Artifact Cache — не фича mirror, это фича Nexus (cache proxy), вам Nexus трафик экономит, а не «зеркало».
Beholder
12.10.2017 16:08А можно ли сделать так, что если точно известно, что некий артефакт лежит в конкретном стороннем репозитории, то не лазить за ним в центральный и другие?
lokkersp
12.10.2017 16:31Если скажем вы имеете репозитории [А, В, С]- то в таком натуральном порядке и они будут опрашиваться. То есть теоретически, если вы смухлюете с порядком репозиториев, то получите свой артефакт чуть быстрее, но мне не кажется это хорошей практикой. Цель — получить в конечном счете все артефакты, а не один единственный.
Beholder
12.10.2017 21:53Ситуация такова, что некий продукт (библиотека, возможно даже не open-source) распространяется сторонней фирмой, либо в виде обычной загрузки, либо доступом к их собственному репозиторию. На Maven central или ещё где-либо этот артифакт, собственно, никогда не появится, и искать его там бессмысленно.
Heruvimka Автор
12.10.2017 22:10Поднять локальный репозиторий рассматривали? Проксировать запросы к стороннему репозиторию, или просто подложить руками нужный артефакт в локальный репо и установить его как прокси к центральному.
… не в ту ветку
lokkersp
Не совсем понял утверждения про Mirror
Не могли бы вы пояснить?
1. В вашем случае, вы имеете 2 инстанса Nexus в своей сети, и получается что вам зеркало нужно на случай падения основного инстанса, не внешнего(Central репозитория). Или говоря «внешний», вы имеете ввиду условный Nexus/artifactory?
Как вы экономите внешний трафик?
2. Насколько помню, по дефолту всякие central репозитории имеют тип proxy, что значит мы получаем этакий кеширующий прокси артефактов. При переключении на зеркало зависимости выкачиваются заново, если они никак не кешированы(что вряд ли).
Или вы держите кеш и на дополнительном инстансе?