Разработка → Maven, где мои артефакты? Еще одна статья про управление зависимостями

из песочницы
Heruvimka 11 октября в 23:52 3,5k
Легко жить с maven, когда есть доступ к центральному репозиторию, или у компании есть один корпоративный репозиторий. Все меняется, если работаешь в закрытом контуре, а количество репозиториев ближе к сотне. Под катом история о том, где искать потерявшийся артефакт и как для этого приготовить maven.

Что будет?

В статье будут примеры настройки settings, pom, описание поиска в репозиториях. Не будет настройки nexus\artifactory, проблем связанных с ними.

Начнем с простого


Добавим зависимость на spring в своем pom.

<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-webmvc</artifactId>
    <version>5.0.0.RELEASE</version>
</dependency>

pom.xml
<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

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?
В нем можно настроить репозитории, зеркала, прокси, переменные среды и т.д. Прописать один раз и использовать во всех проектах (в идеальном мире)
Подробнее про 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

global-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>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>


user-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>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>


pom.xml
<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
Проголосовать:
+15
Сохранить: