java - tutorial - tutoriel maven eclipse




Comment puis-je dire à Maven d'utiliser la dernière version d'une dépendance? (8)

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

<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, mettre à jour constamment la balise <version> peut être un peu ennuyeux. Est-il possible de dire à Maven de toujours utiliser la dernière version disponible (à partir du référentiel)?


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


Contrairement à d'autres, je pense qu'il y a plusieurs raisons pour lesquelles vous pourriez toujours vouloir la dernière version. Surtout si vous effectuez un déploiement continu (nous avons parfois 5 versions par jour) et ne voulez pas faire un projet multi-module.

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 et ensuite le vérifier dans le contrôle source. Oui, je laisse mon CI faire des checkins SCM (ce que vous devez faire de toute façon pour le plugin Maven Release).

Vous devrez configurer le plugin versions pour mettre à jour seulement 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 release pour faire la release qui prend en charge -SNAPSHOT et valide qu'il existe une version release de -SNAPSHOT (ce qui est important).

Si vous faites ce que je fais, vous obtiendrez la dernière version pour toutes les générations de snapshots et la dernière version pour les versions de versions. Vos builds seront également reproductibles.

Mettre à jour

J'ai remarqué quelques commentaires demandant quelques détails sur ce workflow. 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 erroné.

Il est défectueux car pour exécuter le plugin versions pour ajuster les versions, toutes les versions existantes doivent exister pour que le pom fonctionne correctement. C'est le plugin versions ne peut pas mettre à jour vers la dernière version de n'importe quoi s'il ne peut pas trouver 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 (de sorte que vous ne dépendez pas du fichier pom pour fonctionner correctement). J'ai écrit un tel outil dans le langage simple qu'est Bash. Le script va mettre à jour les versions comme le plugin de version et vérifier le pom dans le contrôle de la source. Il fonctionne aussi comme 100x plus rapide que le plugin versions mvn. Malheureusement, il n'est pas écrit d'une manière à usage public, mais si les gens sont intéressés, je pourrais le faire ainsi et le mettre dans un gist ou un github.

Pour en revenir au workflow, certains commentaires ont demandé ce que nous faisons:

  1. Nous avons une vingtaine de projets dans leurs propres dépôts avec leurs propres emplois jenkins
  2. Lorsque nous publions le plugin Maven Release est utilisé. Le workflow de cela est couvert dans la documentation du plugin. Le plugin maven sorte de sucks (et je suis gentil) mais ça marche. Un jour, nous prévoyons de remplacer cette méthode par quelque chose de plus optimal.
  3. Quand l'un des projets est libéré, alors jenkins exécute un travail spécial que nous appellerons le travail de mise à jour de toutes les versions (comment jenkins sait que sa version est compliquée en partie parce que le plugin de maven jenkins est assez merdique).
  4. Le travail de mise à jour de toutes les versions connaît tous les 20 projets. Il s'agit en fait d'un agrégateur pom spécifique à tous les projets de la section modules dans l'ordre des dépendances. Jenkins exécute notre magie groovy / bash foo qui va tirer tous les projets mettre à jour les versions au plus tard et ensuite checkin les poms (encore une fois fait 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 de certaines dépendances), il est archivé et nous lançons immédiatement un ping vers jenkins pour exécuter le job correspondant pour ce projet (ceci afin de préserver l'ordre de dépendance). du planificateur du sondage SCM).

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

Maintenant, vous pourriez penser maven sorte de sucks en raison des problèmes énumérés ci-dessus, mais ce serait en fait assez difficile avec un outil de construction qui n'a pas une syntaxe extensible déclarative facile à analyser (aka XML).

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


La syntaxe de dépendances se trouve dans la documentation sur la spécification des exigences de version de dépendance . Ici c'est pour l'exhaustivité:

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

  • 1.0 : "Soft" exigence sur 1.0 (juste une recommandation, si elle correspond à toutes les autres gammes pour la dépendance)
  • [1.0] : "Hard" exigence 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 de ne pas fonctionner en combinaison avec cette librairie)

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


La vérité est même en 3.x ça marche toujours, étonnamment les projets se construisent et se déploient. Mais le mot-clé LATEST / RELEASE causant des problèmes dans m2e et éclipse partout, projets ALSO dépend de la dépendance qui a déployé à travers le LATEST / RELEASE ne parviennent pas à reconnaître 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 maven-versions-plugin si vous le pouvez.


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

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

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

et ajoutez le plugin versions-maven-plugin à 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, afin de mettre à jour la dépendance, vous devez exécuter les objectifs:

mvn versions:update-properties validate

S'il y a une version plus récente que 1.1.1, elle vous dira:

[INFO] Updated ${myname.version} from 1.1.1 to 1.3.2

Si jamais vous utilisez LATEST, veuillez vous assurer que vous avez bien -U sinon le dernier snapshot ne sera pas retiré.

mvn -U dependency:copy -Dartifact=com.foo:my-foo:LATEST
// pull the latest snapshot for my-foo from all repositories

Veuillez jeter un coup d'oeil à cette page (section "Gammes de dépendances"). Ce que vous pourriez vouloir faire est quelque chose comme

<version>[1.2.3,)</version>

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


REMARQUE:

Cette réponse ne s'applique qu'à Maven 2! Les métaversions LATEST et RELEASE mentionnées ont été abandonnées dans Maven 3 "pour des raisons de reproductibilité" , il y a plus de 6 ans. Veuillez vous référer à cette solution compatible Maven 3 .

Si vous voulez toujours utiliser la dernière version, Maven a deux mots-clés que vous pouvez utiliser comme une alternative aux gammes de versions. Vous devriez utiliser ces options avec soin car vous n'avez plus le contrôle des 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 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-snapshot 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 pouvez utiliser RELEASE ou LATEST à titre de commodité, afin de 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 afin de réduire les risques que votre build ou votre projet soit affecté par une version du logiciel qui n'est pas sous votre contrôle. Utilisez DERNIER et RELÂCHE avec prudence, voire pas du tout.

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

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

Voici un exemple illustrant les différentes options. Dans le dépôt Maven, com.foo:my-foo a 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 sur cet artefact est requise, vous avez les options suivantes (d'autres gammes de versions peuvent être spécifiées bien sûr, en montrant simplement celles qui sont pertinentes ici):

Déclarer une version exacte (sera toujours résoudre à 1.0.1):

<version>[1.0.1]</version>

Déclarer une version explicite (sera toujours résolu en 1.0.1 sauf si une collision se produit, quand Maven sélectionnera une version correspondante):

<version>1.0.1</version>

Déclarer une gamme de version pour tous 1.x (résoudra actuellement à 1.1.1):

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

Déclarer une gamme de version ouverte (résoudra à 2.0.0):

<version>[1.0.0,)</version>

Déclarer la version comme LATEST (va résoudre à 2.0.0) (retiré de maven 3.x)

<version>LATEST</version>

Déclarer la version comme RELEASE (se résoudra à 1.1.1) (enlevé 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" du super POM de Maven . Vous pouvez le faire avec "-Prelease-profile" ou "-DperformRelease = true"

Il est important de souligner que toute approche permettant à Maven de choisir les versions de dépendance (LATEST, RELEASE et versions) peut vous ouvrir des problèmes de temps, car les versions ultérieures peuvent avoir un comportement différent (par exemple, le plugin dependency a précédemment activé un 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 remarque Tim , le maven-versions-plugin est un outil pratique pour mettre à jour les versions de dépendances, en particulier les versions:use-latest-versions et versions:use-latest-releases .





maven-metadata