Come faccio a dire a Maven di usare l'ultima versione di una dipendenza?


788

In Maven, le dipendenze sono generalmente impostate in questo modo:

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

Ora, se stai lavorando con librerie che hanno rilasci frequenti, l'aggiornamento costante del tag <version> può essere alquanto fastidioso. C'è un modo per dire a Maven di usare sempre l'ultima versione disponibile (dal repository)?


@Martin Sono a conoscenza della convenzione xyz-SNAPSHOT, ma pensavo alle librerie rilasciate nelle versioni finali al repository (ovvero passando da dream-library-1.2.3.jar a dream-library-1.2.4.jar , e così via).
Anders Sandvig,

176
Non raccomando davvero questa pratica (né l'utilizzo degli intervalli di versione) per motivi di riproducibilità della build. Una build che inizia a fallire improvvisamente per un motivo sconosciuto è molto più fastidiosa dell'aggiornamento manuale di un numero di versione.
Pascal Thivent,

12
@PascalThivent Aggiornare manualmente un numero di rilascio in un pom è una seccatura se si eseguono rilasci continui. Uso il plug-in delle versioni combinato con il plug-in scm per superarlo (vedi la mia risposta).
Adam Gent,

4
@PascalThivent Entrambi sono fastidiosi, ma in modo diverso. Vorrei scegliere tra entrambi dipendenti dalla mia situazione e non essere costretto a usarne uno perché qualcun altro ha deciso che sarebbe stato meglio.
piegames

Risposte:


745

NOTA:

Questa risposta si applica solo a Maven 2! Le citate LATESTe le RELEASEmetaversioni sono state eliminate in Maven 3 "per motivi di costruzioni riproducibili" , oltre 6 anni fa. Fare riferimento a questa soluzione conforme a Maven 3 .


Se vuoi sempre utilizzare la versione più recente, Maven ha due parole chiave che puoi utilizzare come alternativa agli intervalli di versioni. Dovresti usare queste opzioni con cura poiché non hai più il controllo dei plugin / dipendenze che stai utilizzando.

Quando si dipende da un plug-in o una dipendenza, è possibile utilizzare il valore della versione LATEST o RELEASE. ULTIMO si riferisce all'ultima versione rilasciata o istantanea di un particolare artefatto, l'ultimo manufatto distribuito in un particolare repository. RELEASE si riferisce all'ultima versione non snapshot nel repository. In generale, non è consigliabile progettare software che dipende da una versione non specifica di un artefatto. Se stai sviluppando software, potresti voler utilizzare RELEASE o LATEST per comodità, in modo da non dover aggiornare i numeri di versione quando viene rilasciata una nuova versione di una libreria di terze parti. Quando rilasci software, dovresti sempre assicurarti che il tuo progetto dipenda da versioni specifiche per ridurre le possibilità della tua build o del tuo progetto di essere influenzato da una versione del software non sotto il tuo controllo.

Vedi la sezione Sintassi POM del libro Maven per maggiori dettagli. O vedi questo documento su Range di versioni di dipendenza , dove:

  • Una parentesi quadra ( [& ]) significa "chiuso" (incluso).
  • Una parentesi ( (& )) significa "aperto" (esclusivo).

Ecco un esempio che illustra le varie opzioni. Nel repository Maven, com.foo:my-foo ha i seguenti metadati:

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

Se è richiesta una dipendenza da tale artefatto, sono disponibili le seguenti opzioni ( ovviamente è possibile specificare altri intervalli di versione , mostrando qui quelli pertinenti):

Dichiara una versione esatta (risolverà sempre alla 1.0.1):

<version>[1.0.1]</version>

Dichiara una versione esplicita (risolverà sempre alla 1.0.1 a meno che non si verifichi una collisione, quando Maven selezionerà una versione corrispondente):

<version>1.0.1</version>

Dichiarare un intervallo di versioni per tutti 1.x (attualmente risolverà a 1.1.1):

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

Dichiara un intervallo di versioni aperto (risolverà fino alla 2.0.0):

<version>[1.0.0,)</version>

Dichiara la versione come ULTIMA (verrà risolta in 2.0.0) (rimossa da maven 3.x)

<version>LATEST</version>

Dichiara la versione come RELEASE (risolverà alla 1.1.1) (rimossa da maven 3.x):

<version>RELEASE</version>

Si noti che per impostazione predefinita le proprie distribuzioni aggiorneranno la voce "più recente" nei metadati di Maven, ma per aggiornare la voce "rilascio", è necessario attivare il "profilo di rilascio" da Maven super POM . Puoi farlo con "-Prelease-profile" o "-DperformRelease = true"


Vale la pena sottolineare che qualsiasi approccio che consente a Maven di scegliere le versioni di dipendenza (LATEST, RELEASE e intervalli di versioni) può lasciarti aperto per creare problemi di tempo, poiché le versioni successive possono avere comportamenti diversi (ad esempio il plug-in di dipendenza ha precedentemente impostato un valore predefinito valore da vero a falso, con risultati confusi).

Pertanto è generalmente una buona idea definire versioni esatte nelle versioni. Come sottolinea la risposta di Tim , il plug-in Maven-version è uno strumento utile per l'aggiornamento delle versioni di dipendenza, in particolare le versioni: use-latest-version e version: use-latest-rilascia obiettivi.


76
Ciao ricco! Sembra che il RELEASE e ultima versione marcatori sono non è più supportato in Maven 3.x .
Pascal Thivent,

16
Quella deprecazione sembra applicarsi solo ai plugin piuttosto che alle normali dipendenze se capisco correttamente il documento
Mond Raymond

9
@RichSeller hey Rich; Ho trascorso un po 'di tempo su questo prima di capire che questo non è più disponibile in Maven 3.0;) Considereresti di modificare la risposta in modo che inizi con un aggiornamento che indica la depreaction di Maven 3.0? Grazie mille!
Miquel,

6
Credo che un buon equilibrio sarebbe bloccare la versione principale ma ottenere l'ultima versione minore (o patch) (qualunque sia usata per la correzione di bug solo nell'artefcat da cui dipendi). Con l'attuale sintassi questo sembra essere possibile solo con un intervallo come (nota: inizia con parentesi e finisce con parentesi):[1.1,2.0)
Amr Mostafa

2
FWIW ... link aggiornato a Maven3 Note sulla compatibilità: cwiki.apache.org/confluence/display/MAVEN/…
dyodji

384

Ora so che questo argomento è vecchio, ma leggendo la domanda e la risposta fornita dall'OP sembra che il plug-in Maven Versions potrebbe effettivamente essere stata una risposta migliore alla sua domanda:

In particolare, potrebbero essere utili i seguenti obiettivi:

  • versioni: use-latest-version cerca pom per tutte le versioni che sono state una versione più recente e le sostituisce con l'ultima versione.
  • versioni: use-latest-release cerca nel pom tutte le versioni non SNAPSHOT che sono state una versione più recente e le sostituisce con l'ultima versione.
  • versioni: update-properties aggiorna le proprietà definite in un progetto in modo che corrispondano all'ultima versione disponibile di dipendenze specifiche. Ciò può essere utile se una suite di dipendenze deve essere bloccata su un'unica versione.

Sono inoltre previsti i seguenti altri obiettivi:

  • versioni: display-dependency-updates analizza le dipendenze di un progetto e produce un rapporto di quelle dipendenze che hanno versioni più recenti disponibili.
  • versioni: display-plugin-updates analizza i plugin di un progetto e produce un rapporto di quei plugin che hanno versioni più recenti disponibili.
  • versioni: update-parent aggiorna la sezione parent di un progetto in modo che faccia riferimento alla versione più recente disponibile. Ad esempio, se si utilizza un POM radice aziendale, questo obiettivo può essere utile se è necessario assicurarsi di utilizzare l'ultima versione del POM radice aziendale.
  • versioni: update-child-modules aggiorna la sezione padre dei moduli figlio di un progetto in modo che la versione corrisponda alla versione del progetto corrente. Ad esempio, se si dispone di un aggregatore pom che è anche il genitore per i progetti che aggrega e le versioni figlio e genitore non sono sincronizzate, questo mojo può aiutare a correggere le versioni dei moduli figlio. (Nota che potrebbe essere necessario invocare Maven con l'opzione -N per eseguire questo obiettivo se il tuo progetto è rotto così tanto da non poterlo costruire a causa della versione errata della versione).
  • versioni: lock-snapshot cerca nel pom tutte le versioni -SNAPSHOT e le sostituisce con la versione attuale di quella -SNAPSHOT, ad es. -20090327.172306-4
  • versioni: unlock-snapshot cerca nel pom tutte le versioni di snapshot bloccate timestamp e le sostituisce con -SNAPSHOT.
  • versioni: resol-range trova dipendenze usando gli intervalli di versione e risolve l'intervallo nella versione specifica in uso.
  • versioni: use-release cerca nel pom tutte le versioni -SNAPSHOT che sono state rilasciate e le sostituisce con la versione di rilascio corrispondente.
  • versioni: use-next-release cerca nel pom tutte le versioni non SNAPSHOT che sono state una versione più recente e le sostituisce con la versione successiva.
  • versioni: use-next-version cerca nel pom tutte le versioni che sono state una versione più recente e le sostituisce con la versione successiva.
  • versioni: commit rimuove i file pom.xml.versionsBackup. Forma la metà del "Poor Man's SCM" incorporato.
  • versioni: ripristina ripristina i file pom.xml dai file pom.xml.versionsBackup. Forma la metà del "Poor Man's SCM" incorporato.

Ho pensato di includerlo per qualsiasi riferimento futuro.


10
In questo contesto, qual è la differenza tra "release" e "version".
Ben Noland,

1
@BenNoland, credo che la differenza in questo caso sia che la prossima versione potrebbe non essere un artefatto di rilascio. Ad esempio, dato un artefatto con versione 1.0.0-SNAPSHOT, 1.0.0 e 1.0.1-SNAPSHOT e un riferimento pom a 1.0.0-SNAPSHOT, versioni: next-version e version: next-release si risolverà in 1.0.0 , mentre versioni: ultime versioni e versioni: ultime versioni si risolveranno in 1.0.1-SNAPSHOT e 1.0.0 rispettosamente.
Ryan Beesley,

1
Puoi risolvere alcune incertezze tra versioni / rilasci / istantanee in questa bella tabella qui: goo.gl/iDq6PK
Ev0oD

1
La stampa di tutti gli obiettivi possibili e non correlati non è utile.
MariuszS

2
Vorrei pensare alle versioni: use-latest-version risolve la maggior parte dei problemi del PO.
Alex R

172

Dai un'occhiata a questa pagina (sezione "Intervalli di versioni di dipendenza"). Quello che potresti voler fare è qualcosa di simile

<version>[1.2.3,)</version>

Queste gamme di versioni sono implementate in Maven2.


Per qualche ragione questa opzione non ha funzionato per me, ha scelto una versione all'interno della gamma ma non la più recente.
sorin,

4
Potresti voler dare un'occhiata più da vicino a come Maven confronta i numeri di versione - se non sei conforme a uno schema rigoroso Maven confronta come stringhe e non numeri.
Thorbjørn Ravn Andersen,

Quella pagina è su Codehaus e si descrive come cose "che non sono ancora state implementate per Maven 2.0" ... La stessa documentazione di Maven non dice nulla sugli intervalli di versioni. Mi sto perdendo qualcosa? Quando sono state introdotte le gamme di versioni? Dove sono descritti nella documentazione ufficiale?
Shannon,

1
Sbagli, l'intervallo di versioni indica che tutte le versioni sono OK dalla 1.2.3 alla successiva. Questa non è affatto l'ultima versione.
MariuszS

@sorin Hai forse avuto altre dipendenze nel tuo progetto che dipendevano anche dal manufatto in questione? Prova mvn dependency:tree -Dverbosea capirlo. Questo potrebbe spiegare la versione inaspettata.
Eugene Beresovsky,

83

A differenza di altri, penso che ci siano molte ragioni per cui potresti desiderare sempre l'ultima versione. Soprattutto se stai eseguendo una distribuzione continua (a volte abbiamo circa 5 versioni in un giorno) e non vuoi fare un progetto multi-modulo.

Quello che faccio è fare in modo che Hudson / Jenkins faccia quanto segue per ogni build:

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

Cioè uso il plug-in delle versioni e il plug-in scm per aggiornare le dipendenze e quindi registrarlo per il controllo del codice sorgente. Sì, ho lasciato che il mio CI eseguisse i check-in SCM (cosa che devi fare comunque per il plugin di rilascio di Maven).

Ti consigliamo di installare il plug-in delle versioni per aggiornare solo ciò che desideri:

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

Uso il plug-in di rilascio per eseguire il rilascio che si occupa di -SNAPSHOT e conferma che esiste una versione di -SNAPSHOT (che è importante).

Se fai quello che faccio, otterrai l'ultima versione per tutte le build di snapshot e l'ultima versione di rilascio per le build di rilascio. Le tue build saranno anche riproducibili.

Aggiornare

Ho notato alcuni commenti che chiedevano alcuni dettagli di questo flusso di lavoro. Dirò che non usiamo più questo metodo e il grande motivo per cui il plugin delle versioni Maven è difettoso e in generale è intrinsecamente imperfetto.

È difettoso perché per eseguire il plug-in delle versioni per regolare le versioni devono esistere tutte le versioni esistenti affinché il pom funzioni correttamente. Cioè il plug-in delle versioni non può essere aggiornato all'ultima versione di nulla se non riesce a trovare la versione a cui si fa riferimento nel pom. Questo in realtà è piuttosto fastidioso poiché spesso puliamo le vecchie versioni per motivi di spazio su disco.

In realtà hai bisogno di uno strumento separato da Maven per regolare le versioni (quindi non dipendi dal file pom per funzionare correttamente). Ho scritto un tale strumento nel linguaggio umile che è Bash. Lo script aggiornerà le versioni come il plug-in versione e controllerà il pom nel controllo del codice sorgente. Funziona anche come 100 volte più veloce del plug-in delle versioni mvn. Sfortunatamente non è scritto in un modo per uso pubblico, ma se le persone sono interessate potrei farlo e metterlo in un senso o github.

Tornando al flusso di lavoro come alcuni commenti ci chiedevano che questo è ciò che facciamo:

  1. Abbiamo circa 20 progetti nei loro repository con i loro lavori jenkins
  2. Quando rilasciamo viene utilizzato il plugin di rilascio di Maven. Il flusso di lavoro è descritto nella documentazione del plug-in. Il plugin di rilascio maven fa schifo (e io sono gentile) ma funziona. Un giorno abbiamo in programma di sostituire questo metodo con qualcosa di più ottimale.
  3. Quando uno dei progetti viene rilasciato, jenkins esegue quindi un lavoro speciale, chiameremo il processo di aggiornamento di tutte le versioni (il modo in cui jenkins sa che è una versione è un modo complicato in parte perché anche il plug-in di rilascio di jenkins è piuttosto scadente).
  4. Il processo di aggiornamento di tutte le versioni conosce tutti i 20 progetti. In realtà è un aggregatore pom per essere specifico con tutti i progetti nella sezione moduli in ordine di dipendenza. Jenkins esegue il nostro magico groovy / bash foo che tirerà tutti i progetti aggiornando le versioni alla più recente e quindi controllando i poms (di nuovo fatto in ordine di dipendenza in base alla sezione dei moduli).
  5. Per ogni progetto se il pom è cambiato (a causa di una modifica della versione in alcune dipendenze) viene archiviato e quindi eseguiamo immediatamente il ping di jenkins per eseguire il lavoro corrispondente per quel progetto (questo è per preservare l'ordine di dipendenza build altrimenti sei in balia del programmatore sondaggio SCM).

A questo punto sono dell'opinione che sia una buona cosa avere la versione automatica e la versione uno strumento separato dalla tua build generale.

Ora si potrebbe pensare Maven sorta di schifo a causa dei problemi sopra elencati, ma questo in realtà sarebbe abbastanza difficile con un tool di creazione che non ha un dichiarativa facile da analizzare estensibile sintassi (aka XML).

In effetti aggiungiamo attributi XML personalizzati attraverso gli spazi dei nomi per aiutare a suggerire gli script bash / groovy (ad es. Non aggiornare questa versione).


5
Grazie per aver incluso una motivazione (implementazione continua) nella tua risposta.
David J. Liszewski l'

10
Penso che il punto importante qui che le build siano riproducibili con questo metodo, mentre, quando si usano gli intervalli di versioni o -LATEST, non lo sono!
marc.guenther,

Vorrei secondare la soluzione usando uno strumento esterno apportando modifiche al project pom prima di eseguire build. Stiamo anche usando questo approccio poiché il plug-in versione range è intrinsecamente infastidito, ad esempio prendendo in considerazione le date dell'account e non solo le versioni.
Daniel Hajduk,

37

La sintassi delle dipendenze si trova nella documentazione relativa alle Specifiche dei requisiti della versione delle dipendenze . Eccolo per completezza:

L' versionelemento Dipendenze definisce i requisiti di versione, utilizzati per calcolare la versione effettiva delle dipendenze. I requisiti di versione hanno la sintassi seguente:

  • 1.0: Requisito "Soft" su 1.0 (solo una raccomandazione, se corrisponde a tutti gli altri intervalli per la dipendenza)
  • [1.0]: Requisito "Difficile" su 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 o x> = 1.2; più set sono separati da virgola
  • (,1.1),(1.1,): questo esclude 1.1 (ad esempio se si sa che non funziona in combinazione con questa libreria)

Nel tuo caso, potresti fare qualcosa del genere <version>[1.2.3,)</version>


15

Probabilmente stai dipendendo dalle versioni di sviluppo che ovviamente cambiano molto durante lo sviluppo?

Invece di incrementare la versione delle versioni di sviluppo, potresti semplicemente usare una versione di snapshot che sovrascrivi quando necessario, il che significa che non dovresti cambiare il tag di versione ad ogni piccola modifica. Qualcosa come 1.0-SNAPSHOT ...

Ma forse stai cercando di ottenere qualcos'altro;)


7

Chiunque abbia mai usato ULTIMO, assicurati di avere -U, altrimenti l'ultima istantanea non verrà estratta.

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

anche usando il -UI sto ricevendoCouldn't download artifact: Failed to resolve version for com.app:common:jar:LATEST
Robert

7

Quando questa domanda è stata posta, c'erano alcuni nodi con gli intervalli di versione in Maven, ma questi sono stati risolti nelle versioni più recenti di Maven. Questo articolo illustra molto bene il funzionamento delle gamme di versioni e le migliori pratiche per comprendere meglio in che modo Maven comprende le versioni: https://docs.oracle.com/middleware/1212/core/MAVEN/maven_version.htm#MAVEN8855


2
Sebbene ciò possa teoricamente rispondere alla domanda, sarebbe preferibile includere qui le parti essenziali della risposta e fornire il collegamento come riferimento.
Karl Richter,

6

La verità è che anche in 3.x funziona ancora, sorprendentemente i progetti vengono sviluppati e distribuiti. Ma la parola chiave LATEST / RELEASE che causa problemi in m2e ed eclissi dappertutto, i progetti ALSO dipendono dalla dipendenza che è stata distribuita tramite LATEST / RELEASE non riescono a riconoscere la versione.

Provocherà anche problemi se si tenta di definire la versione come proprietà e fare riferimento altrove.

Quindi la conclusione è usare le versioni-maven-plugin se puoi.


5

A volte non si desidera utilizzare gli intervalli di versioni, perché sembra che siano "lenti" per risolvere le dipendenze, soprattutto quando è in atto una consegna continua e ci sono tonnellate di versioni, principalmente durante lo sviluppo pesante.

Una soluzione alternativa sarebbe quella di utilizzare il plug-in versioni-maven . Ad esempio, puoi dichiarare una proprietà:

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

e aggiungi le versioni-maven-plugin al tuo file 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>

Quindi, per aggiornare la dipendenza, è necessario eseguire gli obiettivi:

mvn versions:update-properties validate

Se esiste una versione più recente della 1.1.1, ti dirà:

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

3

Se vuoi che Maven usi l'ultima versione di una dipendenza, allora puoi usare Versions Maven Plugin e come usare questo plugin, Tim ha già dato una buona risposta, segui la sua risposta .

Ma come sviluppatore, non consiglierò questo tipo di pratiche. PERCHÉ?

risposta al perché è già stato dato da Pascal Thivent nel commento della domanda

Non raccomando davvero questa pratica (né l'utilizzo degli intervalli di versione) per motivi di riproducibilità della build. Una build che inizia a fallire improvvisamente per un motivo sconosciuto è molto più fastidiosa dell'aggiornamento manuale di un numero di versione.

Consiglierò questo tipo di pratica:

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

è di facile manutenzione e facile da eseguire il debug. Puoi aggiornare il tuo POM in pochissimo tempo.


se si utilizza version-maven-plugin, la build è ancora riproducibile. L'aggiornamento della versione maven può essere fatto in un commit separato (come puoi vedere dalla mia risposta, devi specificare un obiettivo separato, semplicemente non accade magicamente nella build).
Markon,

1

LA MIA soluzione in Maven 3.5.4, usa nexus, in eclissi:

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

quindi in eclipse:, atl + F5e scegliere ilforce update of snapshots/release

per me funziona.


Non funzionerà dalla riga di comando, anche se per motivi indicati sopra in vari post. Molti di noi devono conformarsi alle build automatizzate e quindi i nostri POM devono funzionare quando vengono eseguiti dalla riga di comando, non solo in Eclipse.
bigbadmouse,

Sto usando Maven 3.5.4 e ottengo questo quando si usa 'latest': è ULTIMO o RILASCIO (entrambi sono deprecati) @ linea 154, colonna 13
Leonardo Leonardo
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.