Как я могу сказать Maven использовать последнюю версию зависимости?

788

В Maven зависимости обычно устанавливаются так:

<dependency>
  <groupId>wonderful-inc</groupId>
  <artifactId>dream-library</artifactId>
  <version>1.2.3</version>
</dependency>

Теперь, если вы работаете с библиотеками, которые имеют частые выпуски, постоянное обновление тега <version> может несколько раздражать. Есть ли способ сказать Maven, чтобы всегда использовать последнюю доступную версию (из хранилища)?

Андерс Сандвиг
источник
@Martin Мне известно о соглашении xyz-SNAPSHOT, но я думал о библиотеках, выпущенных в окончательных версиях для репозитория (т. Е. Переходе от dream-library-1.2.3.jar к dream-library-1.2.4.jar , и так далее).
Андерс Сандвиг
176
Я действительно не рекомендую эту практику (ни использование диапазонов версий) ради воспроизводимости сборки. Сборка, которая начинает неожиданно завершаться сбоем по неизвестной причине, намного раздражает, чем обновление номера версии вручную.
Паскаль Thivent
12
@PascalThivent Ручное обновление номера релиза в pom - это боль, если вы делаете непрерывные релизы. Я использую плагин версий в сочетании с плагином scm, чтобы обойти это (см. Мой ответ).
Адам Гент
4
@PascalThivent Оба раздражают, но по-разному. Я хотел бы выбрать между обоими в зависимости от моей ситуации и не быть вынужденным использовать один, потому что кто-то другой решил, что это будет лучше.
piegames

Ответы:

745

НОТА:

Этот ответ относится только к Maven 2! Упомянутые LATESTи RELEASEmetaversions было снято в Maven 3 «ради воспроизводимого строит» , более 6 лет назад. Пожалуйста, обратитесь к этому Maven 3-совместимому решению .


Если вы всегда хотите использовать новейшую версию, у Maven есть два ключевых слова, которые вы можете использовать в качестве альтернативы диапазонам версий. Вы должны использовать эти параметры с осторожностью, так как вы больше не контролируете используемые плагины / зависимости.

Когда вы зависите от плагина или зависимости, вы можете использовать значение версии LATEST или RELEASE. LATEST относится к последней выпущенной версии или версии моментального снимка определенного артефакта, самого последнего развернутого артефакта в определенном хранилище. RELEASE относится к последнему выпуску без снимка в хранилище. В общем случае, не рекомендуется разрабатывать программное обеспечение, которое зависит от неспецифической версии артефакта. Если вы разрабатываете программное обеспечение, вы можете использовать RELEASE или LATEST для удобства, чтобы вам не приходилось обновлять номера версий при выпуске нового выпуска сторонней библиотеки. Когда вы выпускаете программное обеспечение, вы всегда должны следить за тем, чтобы ваш проект зависел от конкретных версий, чтобы уменьшить шансы вашей сборки или проекта повлиять на выпуск программного обеспечения, который не находится под вашим контролем.

См. Раздел « Синтаксис POM» книги Maven для более подробной информации. Или посмотрите этот документ в зависимости от версии , где:

  • Квадратная скобка ( [& ]) означает «закрыто» (включительно).
  • Круглая скобка ( (& )) означает «открытый» (исключающий).

Вот пример, иллюстрирующий различные варианты. В репозитории Maven com.foo:my-foo имеет следующие метаданные:

<?xml version="1.0" encoding="UTF-8"?><metadata>
  <groupId>com.foo</groupId>
  <artifactId>my-foo</artifactId>
  <version>2.0.0</version>
  <versioning>
    <release>1.1.1</release>
    <versions>
      <version>1.0</version>
      <version>1.0.1</version>
      <version>1.1</version>
      <version>1.1.1</version>
      <version>2.0.0</version>
    </versions>
    <lastUpdated>20090722140000</lastUpdated>
  </versioning>
</metadata>

Если требуется зависимость от этого артефакта, у вас есть следующие параметры ( конечно, можно указать другие диапазоны версий , просто показывая соответствующие):

Объявите точную версию (всегда разрешите до 1.0.1):

<version>[1.0.1]</version>

Объявите явную версию (всегда разрешается до 1.0.1, если не происходит коллизия, когда Maven выберет подходящую версию):

<version>1.0.1</version>

Объявите диапазон версий для всех 1.x (в настоящее время разрешается до 1.1.1):

<version>[1.0.0,2.0.0)</version>

Объявите диапазон открытых версий (разрешится до 2.0.0):

<version>[1.0.0,)</version>

Объявите версию как ПОСЛЕДНЮЮ (разрешается до 2.0.0) (удалено из maven 3.x)

<version>LATEST</version>

Объявите версию как RELEASE (преобразуется в 1.1.1) (удалена из maven 3.x):

<version>RELEASE</version>

Обратите внимание, что по умолчанию ваши собственные развертывания будут обновлять «последнюю» запись в метаданных Maven, но для обновления записи «release» необходимо активировать «release-profile» из Maven super POM . Вы можете сделать это с помощью -Prelease-profile или -DperformRelease = true.


Стоит подчеркнуть, что любой подход, который позволяет Maven выбирать версии зависимостей (LATEST, RELEASE и диапазоны версий), может оставить вас открытыми для решения проблем со временем, поскольку более поздние версии могут вести себя по-разному (например, плагин для зависимостей ранее переключал значение по умолчанию). значение от истинного до ложного, с ошибочными результатами).

Поэтому, как правило, рекомендуется определять точные версии в выпусках. Как указывает ответ Тима, плагин maven-version-plugin - это удобный инструмент для обновления версий зависимостей, в частности версий: use-latest-version и version: use-latest-Releases .

Богатый продавец
источник
76
Привет Рич! Он появляется RELEASE и НОВЕЙШИЕ маркеры версии не больше не поддерживаются в Maven 3.x .
Паскаль Тивент
16
Похоже, что это осуждение относится только к плагинам, а не к обычным зависимостям, если я правильно понимаю документ
Mond Raymond
9
@RichSeller эй Рич; Я потратил немного времени на это, прежде чем выяснил, что это больше не доступно в Maven 3.0;) Не могли бы вы отредактировать ответ, чтобы он начался с обновления, в котором указывалось на изъятие Maven 3.0? Огромное спасибо!
Микель
6
Я считаю, что хорошим балансом было бы заблокировать основную версию, но получить последнюю минорную (или патчевую) версию (в зависимости от того, что используется для исправления ошибок только в артефакте, от которого вы зависите). С текущим синтаксисом это представляется возможным только с таким диапазоном (примечание: начинается с скобок и заканчивается паренами):[1.1,2.0)
Амр Мостафа,
2
FWIW ... обновлена ​​ссылка на заметки о совместимости с Maven3: cwiki.apache.org/confluence/display/MAVEN/…
dyodji
384

Теперь я знаю, что эта тема старая, но, читая вопрос и предоставленный ОП ответ, кажется, что плагин Maven Versions мог бы быть лучшим ответом на его вопрос:

В частности, могут быть полезны следующие цели:

  • версии: use-latest- version ищет в pom все версии, которые были более новой версией, и заменяет их последней версией.
  • версии: use-latest-release ищет в pom все версии, отличные от SNAPSHOT, которые были более новой версией, и заменяет их последней версией выпуска.
  • версии: update-properties обновляет свойства, определенные в проекте, чтобы они соответствовали последней доступной версии определенных зависимостей. Это может быть полезно, если набор зависимостей должен быть привязан к одной версии.

Следующие другие цели также предусмотрены:

  • версии: display-dependency-updates сканирует зависимости проекта и создает отчет о тех зависимостях, для которых доступны более новые версии.
  • версии: display-plugin-updates сканирует плагины проекта и выдает отчет о тех плагинах, для которых доступны более новые версии.
  • версии: update-parent обновляет родительский раздел проекта, чтобы он ссылался на самую новую доступную версию. Например, если вы используете корпоративное корневое POM, эта цель может оказаться полезной, если вам необходимо убедиться, что вы используете последнюю версию корпоративного корневого POM.
  • версии: update-child-modules обновляет родительский раздел дочерних модулей проекта, чтобы версия соответствовала версии текущего проекта. Например, если у вас есть агрегатор pom, который также является родительским для проектов, которые он агрегирует, а дочерняя и родительская версии не синхронизированы, это mojo может помочь исправить версии дочерних модулей. (Обратите внимание, что вам может потребоваться вызвать Maven с опцией -N, чтобы выполнить эту цель, если ваш проект сломан настолько сильно, что не может быть собран из-за несовпадения версий).
  • версии: lock-snapshots ищет в pom все версии -SNAPSHOT и заменяет их текущей версией временной метки -SNAPSHOT, например -20090327.172306-4
  • версии: unlock-snapshots ищет в pom все заблокированные версии моментальных снимков с метками времени и заменяет их на -SNAPSHOT.
  • версии: resol- range находит зависимости, используя диапазоны версий, и разрешает диапазон для конкретной используемой версии.
  • версии: use- release ищет в pom все версии -SNAPSHOT, которые были выпущены, и заменяет их соответствующей версией выпуска.
  • версии: use-next-release ищет в pom все версии, отличные от SNAPSHOT, которые были более новой версией, и заменяет их следующей версией выпуска.
  • версии: use-next- version ищет в pom все версии, которые были более новой версией, и заменяет их следующей версией.
  • версии: commit удаляет файлы pom.xml.versionsBackup. Формирует половину встроенного «Бедного человека СКМ».
  • Версии: revert восстанавливает файлы pom.xml из файлов pom.xml.versionsBackup. Формирует половину встроенного «Бедного человека СКМ».

Просто подумал, что включу это для любой будущей ссылки.

Тим
источник
10
В этом контексте какая разница между «релизом» и «версией».
Бен Ноланд
1
@BenNoland, я считаю, что разница в этом случае заключается в том, что в следующей версии может не быть артефакт релиза. Например, передаются артефакт версии 1.0.0-SNAPSHOT, 1.0.0 и 1.0.1-SNAPSHOT и ссылка pom на 1.0.0-SNAPSHOT, версии: следующие версии и версии: следующие выпуски будут разрешаться до 1.0.0 тогда как версии: последние версии и версии: последние выпуски будут преобразовываться в 1.0.1-SNAPSHOT и 1.0.0 соответственно.
Райан Бизли
1
Вы можете устранить некоторые неопределенности между версиями / выпусками / снимками в этой очень хорошей таблице здесь: goo.gl/iDq6PK
Ev0oD
1
Печать всех возможных и не связанных целей не помогает.
MariuszS
2
Я думаю, что версии: использование последних версий решает большинство проблем ОП.
Алекс Р
172

Пожалуйста, взгляните на эту страницу (раздел «Диапазоны версий зависимостей»). То, что вы можете сделать, это что-то вроде

<version>[1.2.3,)</version>

Эти диапазоны версий реализованы в Maven2.

Мартин Клинке
источник
По какой-то причине этот вариант не работал для меня, он выбрал версию внутри диапазона, но не самую новую.
Сорин
4
Возможно, вы захотите поближе взглянуть на то, как Maven сравнивает номера версий - если вы не соответствуете строгому шаблону, Maven сравнивает как строки, а не числа.
Торбьерн Равн Андерсен
Эта страница находится на Codehaus и описывает себя как вещи, «которые еще не были реализованы для Maven 2.0» ... Сама документация Maven ничего не говорит о диапазонах версий. Я что-то пропустил? Когда были введены диапазоны версий? Где они описаны в официальной документации?
Шеннон
1
Вы не правы, диапазон версий означает, что все версии в порядке от 1.2.3 и выше. Это не самая последняя версия.
MariuszS
@sorin Возможно, у вас были другие зависимости в вашем проекте, которые также зависят от рассматриваемого артефакта? Попробуй mvn dependency:tree -Dverboseпонять это. Это может объяснить неожиданную версию.
Евгений Бересовский
83

В отличие от других, я думаю, что есть много причин, почему вы всегда можете хотеть последнюю версию. Особенно, если вы делаете непрерывное развертывание (у нас иногда бывает около 5 выпусков в день) и вы не хотите делать многомодульный проект.

Что я делаю, так это заставляю Хадсона / Дженкинса делать следующее для каждой сборки:

mvn clean versions:use-latest-versions scm:checkin deploy -Dmessage="update versions" -DperformRelease=true

То есть я использую плагин версий и плагин scm для обновления зависимостей, а затем возвращаю его в систему контроля версий. Да, я позволил моему CI выполнять проверки SCM (что вы должны сделать в любом случае для плагина релиза maven).

Вы захотите настроить плагин версий для обновления только того, что вы хотите:

<plugin>
    <groupId>org.codehaus.mojo</groupId>
    <artifactId>versions-maven-plugin</artifactId>
    <version>1.2</version>
    <configuration>
        <includesList>com.snaphop</includesList>
        <generateBackupPoms>false</generateBackupPoms>
        <allowSnapshots>true</allowSnapshots>
    </configuration>
</plugin>

Я использую плагин релиза, чтобы сделать релиз, который заботится о -SNAPSHOT и проверяет, существует ли релизная версия -SNAPSHOT (что важно).

Если вы сделаете то, что я делаю, вы получите самую последнюю версию для всех сборок снимков и последнюю версию выпуска для сборок выпуска. Ваши сборки также будут воспроизводимы.

Обновить

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

Он имеет недостатки, потому что для запуска плагина версий для настройки версий все существующие версии должны существовать для правильной работы pom. То есть плагин версий не может обновиться до последней версии чего-либо, если он не может найти версию, на которую ссылается pom. Это на самом деле довольно раздражает, так как мы часто очищаем старые версии по соображениям дискового пространства.

На самом деле вам нужен отдельный инструмент от maven для настройки версий (чтобы вы не зависели от правильности работы pom-файла). Я написал такой инструмент на простом языке Bash. Сценарий обновит версии, такие как плагин версии, и вернет pom обратно в систему контроля версий. Он также работает примерно в 100 раз быстрее, чем плагин версий mvn. К сожалению, это не написано для публичного использования, но если бы люди заинтересовались, я мог бы сделать это и поместить его в gist или github.

Возвращаясь к рабочему процессу, когда некоторые комментарии спрашивали о том, что мы делаем:

  1. У нас есть около 20 проектов в собственных репозиториях со своими рабочими местами в Jenkins
  2. Когда мы выпускаем плагин Maven Release используется. Рабочий процесс описан в документации к плагину. Плагин Maven Release вроде отстой (и я добрый), но он работает. Однажды мы планируем заменить этот метод на что-то более оптимальное.
  3. Когда один из проектов будет выпущен, jenkins затем запустит специальную работу, и мы назовем задачу update all version (то, как jenkins узнает, что релиз - сложная вещь, отчасти потому, что плагин релиза maven jenkins тоже довольно дурацкий).
  4. Работа обновления всех версий знает обо всех 20 проектах. На самом деле это pom-агрегатор, чтобы быть конкретным со всеми проектами в разделе модулей в порядке зависимости. Дженкинс запускает нашу волшебную команду groovy / bash foo, которая будет вытягивать все проекты, обновлять версии до последних и затем регистрировать poms (снова это делается в порядке зависимости на основе раздела модулей).
  5. Для каждого проекта, если pom изменился (из-за изменения версии в некоторой зависимости), он регистрируется, и затем мы немедленно отправляем эхо-запрос jenkins, чтобы запустить соответствующее задание для этого проекта (чтобы сохранить порядок зависимостей сборки, в противном случае вы попали в зависимость планировщика опроса SCM).

На данный момент я считаю, что было бы хорошо, если бы релиз и автоматическая версия были отдельным инструментом от вашей общей сборки.

Теперь вы можете подумать, что maven вроде отстой из-за проблем, перечисленных выше, но на самом деле это было бы довольно сложно с инструментом сборки, который не имеет декларативного легко разбираемого расширяемого синтаксиса (иначе XML).

Фактически мы добавляем пользовательские атрибуты XML через пространства имен, чтобы помочь подсказкам сценариев bash / groovy (например, не обновлять эту версию).

Адам Гент
источник
5
Спасибо за включение мотивации (непрерывного развертывания) в ваш ответ.
David J. Liszewski
10
Я думаю, что здесь важно то, что сборки воспроизводимы этим методом, тогда как при использовании диапазонов версий или -LATEST это не так!
marc.guenther
Я хотел бы поддержать решение с помощью внешнего инструмента, вносящего изменения в проект pom, прежде чем запускать сборку. Мы также используем этот подход, так как плагин version-range-plugin изначально ошибочен, например, принимая во внимание даты, а не только версии.
Даниэль Хайдук
37

Синтаксис зависимостей находится в документации спецификации требований к версии зависимостей . Вот для полноты картины:

versionЭлемент Dependencies определяет требования к версии, используемые для вычисления эффективной версии зависимости. Требования к версии имеют следующий синтаксис:

  • 1.0: «Мягкое» требование к 1.0 (просто рекомендация, если оно соответствует всем другим диапазонам для зависимости)
  • [1.0]: Жесткое требование на 1.0
  • (,1.0]: х <= 1,0
  • [1.2,1.3]: 1,2 <= х <= 1,3
  • [1.0,2.0): 1,0 <= х <2,0
  • [1.5,): x> = 1,5
  • (,1.0],[1.2,): х <= 1,0 или х> = 1,2; несколько наборов разделены запятыми
  • (,1.1),(1.1,): это исключает 1.1 (например, если известно, что он не работает в сочетании с этой библиотекой)

В вашем случае вы могли бы сделать что-то вроде <version>[1.2.3,)</version>

mkobit
источник
15

Возможно, вы зависите от версий для разработки, которые сильно меняются в процессе разработки?

Вместо того, чтобы увеличивать версию разрабатываемых выпусков, вы можете просто использовать версию моментального снимка, которую вы перезаписываете при необходимости, что означает, что вам не придется менять тег версии при каждом незначительном изменении. Что-то вроде 1.0-SNAPSHOT ...

Но, может быть, вы пытаетесь достичь чего-то другого;)

Мартин Клинке
источник
7

Кто когда-либо использовал ПОСЛЕДНЮЮ, пожалуйста, убедитесь, что у вас есть -U, иначе последний снимок не будет получен.

mvn -U dependency:copy -Dartifact=com.foo:my-foo:LATEST
// pull the latest snapshot for my-foo from all repositories
Чунг
источник
даже используя -UI получаюCouldn't download artifact: Failed to resolve version for com.app:common:jar:LATEST
Роберт
7

К тому времени, когда этот вопрос был задан, в maven было несколько изломов с диапазонами версий, но они были решены в более новых версиях maven. В этой статье очень хорошо показано, как работают диапазоны версий и передовые практики, чтобы лучше понять, как maven понимает версии: https://docs.oracle.com/middleware/1212/core/MAVEN/maven_version.htm#MAVEN8855

bclarance
источник
2
Хотя это может теоретически ответить на вопрос, было бы предпочтительным включить сюда основные части ответа и предоставить ссылку для справки.
Карл Рихтер
6

Правда даже в 3.х он все еще работает, на удивление проекты строятся и разворачиваются. Но ключевое слово LATEST / RELEASE, вызывающее проблемы в m2e и затмение повсеместно, ALSO проектов зависит от зависимости, которая развернута через LATEST / RELEASE, не может распознать версию.

Это также вызовет проблему, если вы попытаетесь определить версию как свойство и ссылаться на нее где-либо еще.

Таким образом, вывод заключается в том, что вы можете использовать version-maven-plugin .

Юнчен Лю
источник
5

Иногда вы не хотите использовать диапазоны версий, потому что кажется, что они "медленные" для разрешения ваших зависимостей, особенно когда есть постоянная доставка на месте и есть тонны версий - в основном во время интенсивной разработки.

Одним из способов решения этой проблемы было бы использование version-maven-plugin . Например, вы можете объявить свойство:

<properties>
    <myname.version>1.1.1</myname.version>
</properties>

и добавьте version-maven-plugin в ваш файл pom:

<build>
    <plugins>
        <plugin>
            <groupId>org.codehaus.mojo</groupId>
            <artifactId>versions-maven-plugin</artifactId>
            <version>2.3</version>
            <configuration>
                <properties>
                    <property>
                        <name>myname.version</name>
                        <dependencies>
                            <dependency>
                                <groupId>group-id</groupId>
                                <artifactId>artifact-id</artifactId>
                                <version>latest</version>
                            </dependency>
                        </dependencies>
                    </property>
                </properties>
            </configuration>
        </plugin>
    </plugins>
</build>

Затем, чтобы обновить зависимость, вы должны выполнить цели:

mvn versions:update-properties validate

Если есть версия новее, чем 1.1.1, она скажет вам:

[INFO] Updated ${myname.version} from 1.1.1 to 1.3.2
Маркон
источник
3

Если вы хотите, чтобы Maven использовал последнюю версию зависимости, то вы можете использовать плагин Versions Maven, и как использовать этот плагин, Тим уже дал хороший ответ, следуйте его ответу .

Но, как разработчик, я не буду рекомендовать этот тип практики. ПОЧЕМУ?

Ответ на вопрос, который уже дан Паскалем Тивентом в комментарии к вопросу

Я действительно не рекомендую эту практику (ни использование диапазонов версий) ради воспроизводимости сборки. Сборка, которая начинает неожиданно завершаться сбоем по неизвестной причине, намного раздражает, чем обновление номера версии вручную.

Я буду рекомендовать этот тип практики:

<properties>
    <spring.version>3.1.2.RELEASE</spring.version>
</properties>

<dependencies>

    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-core</artifactId>
        <version>${spring.version}</version>
    </dependency>

    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context</artifactId>
        <version>${spring.version}</version>
    </dependency>

</dependencies>

это легко поддерживать и легко отлаживать. Вы можете обновить свой POM в кратчайшие сроки.

Арайан Сингх
источник
если вы используете version-maven-plugin, сборка будет воспроизводимой. Обновление maven версии может быть выполнено в отдельном коммите (как вы можете видеть из моего ответа, вы должны указать отдельную цель, это просто не происходит волшебным образом в сборке).
Маркон
1

МОЕ решение в maven 3.5.4, используйте nexus, в затмении:

<dependency>
    <groupId>yilin.sheng</groupId>
    <artifactId>webspherecore</artifactId>
    <version>LATEST</version> 
</dependency>

затем в затмении: atl + F5и выберитеforce update of snapshots/release

меня устраивает.

Yilin
источник
Не будет работать в командной строке, хотя по причинам, изложенным выше в различных сообщениях. Многие из нас должны соответствовать автоматизированным сборкам, поэтому наши POM должны работать при запуске из командной строки, а не только в Eclipse.
bigbadmouse
Я использую maven 3.5.4 и получил это при использовании 'latest': либо LATEST, либо RELEASE (оба они устарели) @ строка 154, столбец 13
Леонардо Леонардо