Comment dire à Maven d'utiliser la dernière version d'une dépendance?

788

Dans Maven, les dépendances sont généralement configurées comme suit:

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

Maintenant, si vous travaillez avec des bibliothèques qui ont des versions fréquentes, la mise à jour constante de la balise <version> peut être quelque peu ennuyeuse. Existe-t-il un moyen de dire à Maven de toujours utiliser la dernière version disponible (à partir du référentiel)?

Anders Sandvig
la source
@Martin Je connais la convention xyz-SNAPSHOT, mais je pensais aux bibliothèques qui sont publiées dans les versions finales dans le référentiel (c'est-à-dire en passant de dream-library-1.2.3.jar à dream-library-1.2.4.jar , etc).
Anders Sandvig
176
Je ne recommande vraiment pas cette pratique (ni l'utilisation de plages de versions) pour des raisons de reproductibilité de build. Une version qui commence soudainement à échouer pour une raison inconnue est bien plus ennuyeuse que la mise à jour manuelle d'un numéro de version.
Pascal Thivent
12
@PascalThivent La mise à jour manuelle d'un numéro de version dans un pom est pénible si vous effectuez des versions continues. J'utilise le plugin versions combiné avec le plugin scm pour dépasser cela (voir ma réponse).
Adam Gent
4
@PascalThivent Les deux sont ennuyeux, mais d'une manière différente. Je voudrais choisir entre les deux en fonction de ma situation et ne pas être obligé d'en utiliser un parce que quelqu'un d'autre a décidé que celui-ci serait mieux.
piegames

Réponses:

745

REMARQUE:

Cette réponse s'applique uniquement à Maven 2! Les métaversions mentionnées LATESTet ont été supprimées dans Maven 3 "pour des constructions reproductibles" , il y a plus de 6 ans. Veuillez vous référer à cette solution compatible Maven 3RELEASE .


Si vous souhaitez toujours utiliser la version la plus récente, Maven dispose de deux mots clés que vous pouvez utiliser comme alternative aux plages de versions. Vous devez utiliser ces options avec précaution car vous ne contrôlez plus les plugins / dépendances que vous utilisez.

Lorsque vous dépendez d'un plugin ou d'une dépendance, vous pouvez utiliser la valeur de version a LATEST ou RELEASE. LATEST fait référence à la dernière version publiée ou instantanée d'un artefact particulier, l'artefact le plus récemment déployé dans un référentiel particulier. RELEASE fait référence à la dernière version non instantanée dans le référentiel. En général, il n'est pas recommandé de concevoir un logiciel qui dépend d'une version non spécifique d'un artefact. Si vous développez un logiciel, vous souhaiterez peut-être utiliser RELEASE ou LATEST pour ne pas avoir à mettre à jour les numéros de version lorsqu'une nouvelle version d'une bibliothèque tierce est publiée. Lorsque vous publiez un logiciel, vous devez toujours vous assurer que votre projet dépend de versions spécifiques pour réduire les risques que votre build ou votre projet soit affecté par une version logicielle qui n'est pas sous votre contrôle.

Voir la section Syntaxe POM du livre Maven pour plus de détails. Ou consultez ce document sur les plages de versions des dépendances , où:

  • Un crochet ( [& ]) signifie "fermé" (inclus).
  • Une parenthèse ( (& )) signifie "ouvert" (exclusif).

Voici un exemple illustrant les différentes options. Dans le référentiel Maven, com.foo:my-foo contient les métadonnées suivantes:

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

Si une dépendance à cet artefact est requise, vous disposez des options suivantes (d'autres gammes de versions peuvent être spécifiées bien sûr, en affichant simplement celles pertinentes ici):

Déclarez une version exacte (sera toujours résolue en 1.0.1):

<version>[1.0.1]</version>

Déclarez une version explicite (sera toujours résolue en 1.0.1 sauf si une collision se produit, lorsque Maven sélectionnera une version correspondante):

<version>1.0.1</version>

Déclarez une plage de versions pour tous les 1.x (se résoudra actuellement en 1.1.1):

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

Déclarez une plage de versions ouverte (résoudra en 2.0.0):

<version>[1.0.0,)</version>

Déclarez la version comme DERNIÈRE (résoudra en 2.0.0) (supprimée de maven 3.x)

<version>LATEST</version>

Déclarez la version comme RELEASE (résoudra en 1.1.1) (supprimée de maven 3.x):

<version>RELEASE</version>

Notez que par défaut, vos propres déploiements mettront à jour la "dernière" entrée dans les métadonnées Maven, mais pour mettre à jour l'entrée "release", vous devez activer le "release-profile" à partir du super POM Maven . Vous pouvez le faire avec "-Prelease-profile" ou "-DperformRelease = true"


Il convient de souligner que toute approche qui permet à Maven de choisir les versions de dépendance (LATEST, RELEASE et plages de versions) peut vous laisser ouvert pour créer des problèmes de temps, car les versions ultérieures peuvent avoir un comportement différent (par exemple, le plug-in de dépendance a précédemment changé de valeur par défaut). valeur de vrai à faux, avec des résultats confus).

C'est donc généralement une bonne idée de définir des versions exactes dans les versions. Comme le souligne la réponse de Tim , le plugin maven-versions- est un outil pratique pour mettre à jour les versions de dépendance, en particulier les versions: use-latest-versions et versions: use-latest-releases objectives.

Vendeur riche
la source
76
Salut riche! Il semble que le RELEASE et DERNIÈRES marqueurs de version sont plus pris en charge dans 3.x Maven .
Pascal Thivent
16
Cette dépréciation semble s'appliquer uniquement aux plugins plutôt qu'aux dépendances normales si je comprends bien le document
Mond Raymond
9
@RichSeller hey Rich; J'ai passé un peu de temps à ce sujet avant de comprendre que ce n'est plus disponible dans Maven 3.0;) Envisageriez-vous de modifier la réponse pour qu'elle commence par une mise à jour indiquant la dépréciation de Maven 3.0? Merci beaucoup!
Miquel
6
Je crois qu'un bon équilibre serait de verrouiller la version principale mais d'obtenir la dernière version mineure (ou corrective) (celle qui est utilisée pour les corrections de bugs uniquement dans l'artifcat dont vous dépendez). Avec la syntaxe actuelle, cela ne semble possible qu'avec une plage comme (remarque: commence par des crochets et se termine par des parenthèses):[1.1,2.0)
Amr Mostafa
2
FWIW ... lien mis à jour vers les notes de compatibilité Maven3: cwiki.apache.org/confluence/display/MAVEN/…
dyodji
384

Maintenant, je sais que ce sujet est ancien, mais à la lecture de la question et de la réponse fournie par l'OP, il semble que le plugin Maven Versions aurait pu être une meilleure réponse à sa question:

En particulier, les objectifs suivants pourraient être utiles:

  • versions: use-latest-versions recherche dans le pom toutes les versions qui ont été une version plus récente et les remplace par la dernière version.
  • versions: use-latest-releases recherche dans le pom toutes les versions non SNAPSHOT qui ont été une version plus récente et les remplace par la dernière version.
  • versions: update-properties met à jour les propriétés définies dans un projet afin qu'elles correspondent à la dernière version disponible de dépendances spécifiques. Cela peut être utile si une suite de dépendances doit toutes être verrouillées sur une seule version.

Les autres objectifs suivants sont également fournis:

  • versions: display-dependency-updates analyse les dépendances d'un projet et produit un rapport de ces dépendances qui ont des versions plus récentes disponibles.
  • versions: display-plugin-updates scanne les plugins d'un projet et produit un rapport de ces plugins qui ont des versions plus récentes disponibles.
  • versions: update-parent met à jour la section parent d'un projet afin qu'il fasse référence à la dernière version disponible. Par exemple, si vous utilisez un POM racine d'entreprise, cet objectif peut être utile si vous devez vous assurer que vous utilisez la dernière version du POM racine d'entreprise.
  • versions: update-child-modules met à jour la section parent des modules enfants d'un projet afin que la version corresponde à la version du projet en cours. Par exemple, si vous avez un pom d'agrégateur qui est également le parent des projets qu'il agrège et que les versions enfants et parent sont désynchronisées, ce mojo peut aider à corriger les versions des modules enfants. (Notez que vous devrez peut-être invoquer Maven avec l'option -N afin d'exécuter cet objectif si votre projet est tellement endommagé qu'il ne peut pas être construit en raison d'une mauvaise correspondance de version).
  • versions: lock-snapshots recherche dans le pom toutes les versions -SNAPSHOT et les remplace par la version actuelle de l'horodatage de cette -SNAPSHOT, par exemple -20090327.172306-4
  • versions: unlock-snapshots recherche dans le pom toutes les versions de snapshot verrouillées par horodatage et les remplace par -SNAPSHOT.
  • versions: resolver-plages recherche les dépendances à l'aide des plages de versions et résout la plage à la version spécifique utilisée.
  • versions: use-releases recherche dans le pom toutes les versions -SNAPSHOT qui ont été publiées et les remplace par la version correspondante.
  • versions: use-next-releases recherche dans le pom toutes les versions non SNAPSHOT qui ont été une version plus récente et les remplace par la version suivante.
  • versions: use-next-versions recherche dans le pom toutes les versions qui ont été une version plus récente et les remplace par la version suivante.
  • versions: commit supprime les fichiers pom.xml.versionsBackup. Forme la moitié du "Poor Man's SCM" intégré.
  • versions: revert restaure les fichiers pom.xml à partir des fichiers pom.xml.versionsBackup. Forme la moitié du "Poor Man's SCM" intégré.

Je pensais juste l'inclure pour toute référence future.

Tim
la source
10
Dans ce contexte, quelle est la différence entre "version" et "version".
Ben Noland
1
@BenNoland, je crois que la différence dans ce cas est que la prochaine version peut ne pas être un artefact de version. Par exemple, étant donné un artefact versionné 1.0.0-SNAPSHOT, 1.0.0 et 1.0.1-SNAPSHOT, et une référence pom à 1.0.0-SNAPSHOT, versions: prochaines versions et versions: les prochaines versions seront résolues en 1.0.0 , tandis que les versions: dernières versions et versions: les dernières versions seront résolues en 1.0.1-SNAPSHOT et 1.0.0 en respectant.
Ryan Beesley
1
Vous pouvez résoudre certaines incertitudes entre les versions / versions / instantanés dans ce très joli tableau ici: goo.gl/iDq6PK
Ev0oD
1
L'impression de tous les objectifs possibles et indépendants n'est pas utile.
MariuszS
2
Je pense que les versions: use-latest-versions résout la plupart des problèmes de l'OP.
Alex R
172

Veuillez consulter cette page (section "Plages de versions des dépendances"). Ce que vous pourriez vouloir faire, c'est quelque chose comme

<version>[1.2.3,)</version>

Ces gammes de versions sont implémentées dans Maven2.

Martin Klinke
la source
Pour une raison quelconque, cette option n'a pas fonctionné pour moi, elle a choisi une version dans la gamme, mais pas la plus récente.
sorin
4
Vous voudrez peut-être regarder de plus près comment Maven compare les numéros de version - si vous n'êtes pas conforme à un modèle strict, Maven compare les chaînes et non les nombres.
Thorbjørn Ravn Andersen
Cette page est sur Codehaus, et se décrit comme des choses "qui n'ont pas encore été implémentées pour Maven 2.0" ... La documentation Maven elle-même ne dit rien sur les gammes de versions. Suis-je en train de manquer quelque chose? Quand les gammes de versions ont-elles été introduites? Où sont-ils décrits dans la documentation officielle?
Shannon
1
Vous vous trompez, la plage de versions signifie que toutes les versions sont correctes de 1.2.3 à plus. Ce n'est pas du tout la dernière version.
MariuszS
@sorin Aviez-vous peut-être d'autres dépendances dans votre projet qui dépendent également de l'artefact en question? Essayez mvn dependency:tree -Dverbosede comprendre cela. Cela pourrait expliquer la version inattendue.
Eugene Beresovsky
83

Contrairement à d'autres, je pense qu'il existe de nombreuses raisons pour lesquelles vous pouvez toujours vouloir la dernière version. Surtout si vous faites un déploiement continu (nous avons parfois comme 5 versions en une journée) et que vous ne voulez pas faire un projet multi-modules.

Ce que je fais, c'est que Hudson / Jenkins fasse ce qui suit pour chaque build:

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

C'est-à-dire que j'utilise le plugin versions et le plugin scm pour mettre à jour les dépendances, puis les archiver dans le contrôle de code source. Oui, je laisse mon CI effectuer des vérifications SCM (ce que vous devez faire de toute façon pour le plugin de libération maven).

Vous voudrez configurer le plugin des versions pour ne mettre à jour que ce que vous voulez:

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

J'utilise le plugin de version pour faire la version qui prend en charge -SNAPSHOT et valide qu'il existe une version de version de -SNAPSHOT (ce qui est important).

Si vous faites ce que je fais, vous obtiendrez la dernière version pour toutes les versions d'instantanés et la dernière version pour les versions. Vos versions seront également reproductibles.

Mise à jour

J'ai remarqué quelques commentaires demandant des détails sur ce flux de travail. Je dirai que nous n'utilisons plus cette méthode et la grande raison pour laquelle le plugin maven versions est bogué et en général est intrinsèquement défectueux.

Il est défectueux car pour exécuter le plug-in de versions afin d'ajuster les versions, toutes les versions existantes doivent exister pour que le pom fonctionne correctement. C'est-à-dire que le plugin de versions ne peut pas se mettre à jour vers la dernière version de quoi que ce soit s'il ne trouve pas la version référencée dans le pom. C'est en fait plutôt ennuyeux car nous nettoyons souvent les anciennes versions pour des raisons d'espace disque.

Vraiment, vous avez besoin d'un outil distinct de maven pour ajuster les versions (donc vous ne dépendez pas du fichier pom pour fonctionner correctement). J'ai écrit un tel outil dans le langage humble qu'est Bash. Le script mettra à jour les versions comme le plugin de version et vérifiera le pom dans le contrôle de source. Il fonctionne également 100 fois plus vite que le plugin des versions mvn. Malheureusement, il n'est pas écrit d'une manière publique, mais si les gens sont intéressés, je pourrais le faire et le mettre dans un gistub ou un github.

Revenons au workflow car certains commentaires ont demandé à ce sujet ce que nous faisons:

  1. Nous avons une vingtaine de projets dans leurs propres référentiels avec leurs propres emplois jenkins
  2. Lorsque nous libérons le plugin de libération maven est utilisé. Le flux de travail de cela est couvert dans la documentation du plugin. Le plugin de libération maven est en quelque sorte nul (et je suis gentil) mais cela fonctionne. Un jour, nous prévoyons de remplacer cette méthode par quelque chose de plus optimal.
  3. Lorsque l'un des projets est publié, jenkins exécute ensuite un travail spécial, nous appellerons le travail de mise à jour toutes les versions (comment jenkins sait qu'il s'agit d'une version est une manière compliquée en partie parce que le plugin de sortie maven jenkins est également assez merdique).
  4. Le travail de mise à jour toutes versions connaît les 20 projets. Il s'agit en fait d'un pom agrégateur pour être spécifique à tous les projets de la section modules dans l'ordre des dépendances. Jenkins exécute notre magie groovy / bash foo qui tirera tous les projets pour mettre à jour les versions au plus tard, puis archiver les poms (encore une fois dans l'ordre de dépendance basé sur la section des modules).
  5. Pour chaque projet, si le pom a changé (en raison d'un changement de version dans certaines dépendances), il est archivé, puis nous envoyons immédiatement une commande ping à jenkins pour exécuter le travail correspondant pour ce projet (c'est pour préserver l'ordre de dépendance de la construction, sinon vous êtes à la merci de l'ordonnanceur SCM Poll).

À ce stade, je suis d'avis que c'est une bonne chose d'avoir de toute façon la version et la version automatique un outil distinct de votre version générale.

Maintenant, vous pourriez penser que maven est un peu nul à cause des problèmes répertoriés ci-dessus, mais cela serait en fait assez difficile avec un outil de construction qui n'a pas de syntaxe extensible déclarative facile à analyser (aka XML).

En fait, nous ajoutons des attributs XML personnalisés via des espaces de noms pour aider à suggérer les scripts bash / groovy (par exemple, ne mettez pas à jour cette version).

Adam Gent
la source
5
Merci d'avoir inclus une motivation (déploiement continu) dans votre réponse.
David J.Liszewski
10
Je pense que le point important ici, c'est que les builds sont reproductibles avec cette méthode, alors que, lorsque vous utilisez des plages de versions ou -LATEST, elles ne le sont pas!
marc.guenther
Je voudrais seconder la solution en utilisant un outil externe apportant des modifications au projet pom avant d'exécuter la construction. Nous utilisons également cette approche car le plugin de plage de versions est intrinsèquement buggé, par exemple en tenant compte des dates et pas seulement des versions.
Daniel Hajduk
37

La syntaxe des dépendances se trouve dans la documentation de spécification des exigences de version des dépendances . Le voici pour être complet:

L' versionélément des dépendances définit les exigences de version, utilisées pour calculer la version de dépendance efficace. Les exigences de version ont la syntaxe suivante:

  • 1.0: Exigence "douce" sur 1.0 (juste une recommandation, si elle correspond à toutes les autres plages pour la dépendance)
  • [1.0]: Exigence "difficile" sur 1.0
  • (,1.0]: x <= 1,0
  • [1.2,1.3]: 1,2 <= x <= 1,3
  • [1.0,2.0): 1,0 <= x <2,0
  • [1.5,): x> = 1,5
  • (,1.0],[1.2,): x <= 1,0 ou x> = 1,2; plusieurs ensembles sont séparés par des virgules
  • (,1.1),(1.1,): ceci exclut 1.1 (par exemple s'il est connu qu'il ne fonctionne pas en combinaison avec cette bibliothèque)

Dans votre cas, vous pourriez faire quelque chose comme <version>[1.2.3,)</version>

mkobit
la source
15

Dépendez-vous éventuellement de versions de développement qui changent évidemment beaucoup au cours du développement?

Au lieu d'incrémenter la version des versions de développement, vous pouvez simplement utiliser une version d'instantané que vous remplacez si nécessaire, ce qui signifie que vous n'aurez pas à modifier la balise de version à chaque modification mineure. Quelque chose comme 1.0-INSTANTANÉ ...

Mais peut-être que vous essayez de réaliser autre chose;)

Martin Klinke
la source
7

Si vous utilisez LATEST, assurez-vous d'avoir -U sinon le dernier instantané ne sera pas tiré.

mvn -U dependency:copy -Dartifact=com.foo:my-foo:LATEST
// pull the latest snapshot for my-foo from all repositories
trung
la source
même en utilisant le -UI je reçoisCouldn't download artifact: Failed to resolve version for com.app:common:jar:LATEST
Robert
7

Au moment où cette question a été posée, il y avait quelques problèmes avec les plages de versions dans maven, mais ceux-ci ont été résolus dans les nouvelles versions de maven. Cet article capture très bien le fonctionnement des plages de versions et les meilleures pratiques pour mieux comprendre comment maven comprend les versions: https://docs.oracle.com/middleware/1212/core/MAVEN/maven_version.htm#MAVEN8855

bclarance
la source
2
Bien que cela puisse théoriquement répondre à la question, il serait préférable d'inclure ici les parties essentielles de la réponse et de fournir le lien de référence.
Karl Richter
6

La vérité est que même en 3.x cela fonctionne toujours, étonnamment les projets se construisent et se déploient. Mais le mot-clé LATEST / RELEASE provoquant des problèmes dans m2e et éclipse partout, les projets ALSO dépendent de la dépendance qui a été déployée via le LATEST / RELEASE ne reconnaît pas la version.

Cela causera également des problèmes si vous essayez de définir la version en tant que propriété et de la référencer ailleurs.

Donc, la conclusion est d'utiliser le plugin versions-maven si vous le pouvez.

Junchen Liu
la source
5

Parfois, vous ne voulez pas utiliser les plages de versions, car il semble qu'elles soient "lentes" pour résoudre vos dépendances, surtout quand il y a une livraison continue en place et qu'il y a des tonnes de versions - principalement pendant un développement lourd.

Une solution de contournement serait d'utiliser le plugin versions-maven . Par exemple, vous pouvez déclarer une propriété:

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

et ajoutez le plugin versions-maven à votre fichier 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>

Ensuite, pour mettre à jour la dépendance, vous devez exécuter les objectifs:

mvn versions:update-properties validate

S'il existe une version plus récente que 1.1.1, elle vous indiquera:

[INFO] Updated ${myname.version} from 1.1.1 to 1.3.2
Markon
la source
3

Si vous voulez que Maven utilise la dernière version d'une dépendance, alors vous pouvez utiliser le plugin Versions Maven et comment utiliser ce plugin, Tim a déjà donné une bonne réponse, suivez sa réponse .

Mais en tant que développeur, je ne recommanderai pas ce type de pratiques. POURQUOI?

réponse à pourquoi est déjà donnée par Pascal Thivent dans le commentaire de la question

Je ne recommande vraiment pas cette pratique (ni l'utilisation de plages de versions) pour des raisons de reproductibilité de build. Une version qui commence soudainement à échouer pour une raison inconnue est bien plus ennuyeuse que la mise à jour manuelle d'un numéro de version.

Je recommanderai ce type de pratique:

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

il est facile à entretenir et à déboguer. Vous pouvez mettre à jour votre POM en un rien de temps.

Arayan Singh
la source
si vous utilisez le plugin versions-maven, la version est toujours reproductible. La mise à jour de la version de maven peut être effectuée dans un commit séparé (comme vous pouvez le voir dans ma réponse, vous devez spécifier un objectif distinct, cela ne se produit tout simplement pas comme par magie dans la build).
Markon
1

Ma solution dans maven 3.5.4, utilisez nexus, dans eclipse:

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

puis dans éclipse:, atl + F5et choisissez leforce update of snapshots/release

ça marche pour moi.

yilin
la source
Ne fonctionnera pas sur la ligne de commande mais pour les raisons indiquées ci-dessus dans divers messages. Beaucoup d'entre nous doivent se conformer aux versions automatisées et donc nos POM doivent fonctionner lorsqu'ils sont exécutés en ligne de commande, pas seulement dans Eclipse.
bigbadmouse
J'utilise maven 3.5.4 et j'ai obtenu ceci lors de l'utilisation de `` latest '': est soit DERNIER ou RELEASE (les deux sont obsolètes) @ ligne 154, colonne 13
Leonardo Leonardo