[Из песочницы] Maven, где мои артефакты? Еще одна статья про управление зависимостями

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

Что будет?

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

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


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


    org.springframework
    spring-webmvc
    5.0.0.RELEASE


pom.xml

    4.0.0

    test
    dependency-testing
    1.0.0
    Dependency test

    
        
            org.springframework
            spring-webmvc
            5.0.0.RELEASE
        
    



Предположим, что мы только установили maven и не меняли никаких настроек. После инициализации поиска зависимостей через сборку maven, или через ide, maven сначала проверит наличие артефакта в локальном репозитории в директории ${user.home}/.m2/repository/.

Если в локальном репозитории артефакта нет, то запрос пойдет в репозиторий central.

59d766a76229b020059817.png


Мы не указывали этот репозиторий, но он всегда добавляется мавеном при сборке.

Сконфигурируем settings.xml

settings.xml


    
        
            
                
                    nexus-corp
                    nexus-corp-repo
                    http://nexus.mycompany.com:8081/nexus/central/
                
            
            nexus
        
    
    
        nexus
    


Зачем мне settings.xml?
В нем можно настроить репозитории, зеркала, прокси, переменные среды и т.д. Прописать один раз и использовать во всех проектах (в идеальном мире)
Подробнее про settings.xml


С такой конфигурацией порядок поиска будет аналогичен варианту с конфигурацией по умолчанию, но появится дополнительный шаг. Перед тем как пойти в central, мавен попытается скачать артефакт из репозитория nexus-corp.

59d766a75a32d249597273.png


Зеркало


Добавим зеркало для репозитория nexus-corp.


    nexus-corp-mirror
    nexus-corp-mirror
    http://nexus.mirror.mycompany.com:8081/nexus/central/
    nexus-corp


Когда нужно зеркало?
  • недоступен внешний репозиторий
  • для экономии внешнего трафика
  • чтобы переопределить репозиторий из settings\pom

Подробнее про зеркала


Когда maven дойдет до шага поиска в репозитории nexus-corp, то вместо него попытается найти артефакт в репозитории nexus-corp-mirror.

При этом если он не найдет его в nexus-corp-mirror, то запроса в nexus-corp не будет.

59d766a77f365030516424.png


А если добавить зеркало с wildcard, то все запросы будут направлены на него, если не указаны другие зеркала.


    all
    nexus-corp-mirror
    http://nexus.mirror.mycompany.com:8081/nexus/central/
    *


Порядок поиска


В общем случае схема поиска будет такой:

1. Поиск в локальном репо
2. Поиск в репозиториях в порядке объявления с учетом приоритета (либо в их зеркалах)

В конце добавляется central. Он всегда последний, если не был перезаписан.

59d761cc478af917197327.png


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



    
        
            
                
                    repo-global-setting1
                    http://nexus.mycompany.com:8081/nexus/repo-global-setting1-url/
                
            
            g-nexus
        
    
    
        g-nexus
    



user-settings.xml


    
        
            
                
                    repo-user-setting1
                    http://nexus.mycompany.com:8081/nexus/repo-user-setting1-url/
                
                
                    repo-user-setting2
                    http://nexus.mycompany.com:8081/nexus/repo-user-setting2-url/
                
            
            nexus
        
    
    
        nexus
    



pom.xml

    4.0.0

    test
    dependency-testing
    1.0.0
    Dependency test

    
        
            repo-pom1
            http://nexus.mycompany.com:8081/nexus/repo-pom1-url/
        
    
    
    
        
            org.slf4j
            slf4j-api
            1.7.25
        
    




С разрешением конфликтов появилось еще большее непонимание. Если объявить репозиторий с одним 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

© Habrahabr.ru