2013-04-19 32 views
27

Uso il plugin maven-enforcer per verificare i problemi di convergenza delle dipendenze. Un output tipico sarebbe:Risoluzione dei problemi di convergenza delle dipendenze Maven

[WARNING] Rule 1: org.apache.maven.plugins.enforcer.DependencyConvergence failed 
    with message: 
Failed while enforcing releasability the error(s) are [ 
Dependency convergence error for junit:junit:3.8.1 paths to dependency are: 
+-foo:bar:1.0-SNAPSHOT 
    +-ca.juliusdavies:not-yet-commons-ssl:0.3.9 
    +-commons-httpclient:commons-httpclient:3.0 
     +-junit:junit:3.8.1 
and 
+-foo:bar:1.0-SNAPSHOT 
    +-junit:junit:4.11 
] 

Vedendo questo messaggio, normalmente lo "risolvere" escludendo la dipendenza transitiva, ad es.

<dependency> 
    <groupId>ca.juliusdavies</groupId> 
    <artifactId>not-yet-commons-ssl</artifactId> 
    <version>0.3.9</version> 
    <exclusions> 
    <!-- This artifact links to another artifact which stupidly includes 
     junit in compile scope --> 
    <exclusion> 
     <groupId>junit</groupId> 
     <artifactId>junit</artifactId> 
    </exclusion> 
    </exclusions> 
</dependency> 

mi piacerebbe capire se questo è veramente una difficoltà e dei rischi connessi a escludere le librerie in questo modo. Come la vedo io:

  • La "correzione" è normalmente sicura, purché ho scelto di utilizzare la versione più recente. Ciò si basa sugli autori delle librerie che mantengono la retrocompatibilità.

  • V'è in genere alcun impatto sul Maven costruire (dal momento che la definizione più vicino vince), ma escludendo la dipendenza che sto dicendo Maven che so su questo problema e placare l'esperto-enforcer-plugin così.

I miei pensieri sono corretti e c'è un modo alternativo di gestire questo problema? Sono interessato alle risposte che si concentrano sul caso generale: mi rendo conto che l'esempio junit è un po 'strano.

risposta

39

Siamo tutti d'accordo sul fatto che JUnit non dovrebbe mai essere impostato su un altro ambito rispetto a test. In generale, non penso nemmeno che esista un'altra soluzione che escludere la dipendenza indesiderata, quindi siamo tutti d'accordo sul fatto che abbiate ragione a farlo.

un caso semplice:

Come dice Andreas Krueger, ci può essere un rischio con le versioni (in realtà ho incontrato esso). Lasciate che dicono che le dipendenze del progetto sono i seguenti:

+-foo:bar:1.0-SNAPSHOT 
    +-group1:projectA:2.0 
    +-group2:projectB:3.8.1 
    +-group2:projectB:4.11 

Nota che è solo una mera semplificazione del vostro caso.Vedendo questo albero delle dipendenze, si dovrebbe escludere la dipendenza ProjectB data da Projecta:

<dependency> 
    <groupId>group1</groupId> 
    <artifactId>projectA</artifactId> 
    <version>2.0</version> 
    <exclusions> 
    <exclusion> 
     <groupId>group2</groupId> 
     <artifactId>projectB</artifactId> 
    </exclusion> 
    </exclusions> 
</dependency> 

Dopo il confezionamento del progetto con Maven, la dipendenza restante sarebbe group2-someProjectB-4.11.jar, versione 4.11 e non 3.8.1. Tutto andrebbe bene e il progetto funzionerebbe senza incontrare alcun problema.

Poi, un po 'dopo, diciamo che si decide di eseguire l'aggiornamento alla prossima versione del progetto A, versione 3.0 che aggiunge nuove grandi caratteristiche:

<dependency> 
    <groupId>group1</groupId> 
    <artifactId>projectA</artifactId> 
    <version>3.0</version> 
    <exclusions> 
    <exclusion> 
     <groupId>group2</groupId> 
     <artifactId>projectB</artifactId> 
    </exclusion> 
    </exclusions> 
</dependency> 

Il problema è che non siete ancora a conoscenza che projectA la versione 3.0 anche aver aggiornato la sua dipendenza ProjectB alla versione 5.0:

+-foo:bar:1.0-SNAPSHOT 
    +-group1:projectA:3.0 
    +-group2:projectB:5.0 
    +-group2:projectB:4.11 

In tal caso, l'esclusione si sarebbe fatto qualche tempo fa esclude ProjectB versione 5.0.

Tuttavia, projectA versione 3.0 richiede i miglioramenti dal progetto B versione 5.0. A causa dell'esclusione, dopo aver imballato il progetto con Maven, la dipendenza rimanente sarebbe group2-someProjectB-4.11.jar, versione 4.11 e non 5.0. Al momento si utilizza una delle nuove funzionalità di projectA, il programma non funzionerà correttamente.

QUALE ERA LA SOLUZIONE?

Ho riscontrato questo problema in un progetto Java-EE.

Un team ha sviluppato servizi di database. Lo hanno confezionato come progettoA. Ogni volta che aggiornavano i servizi, aggiornavano anche un file che elencava tutte le loro attuali dipendenze e le versioni correnti.

ProjectA era una dipendenza per il progetto Java-EE su cui stavo lavorando. Ogni volta che il team di servizio aggiornava ProjectA, controllavo anche gli aggiornamenti delle versioni.

In effetti, non c'è nulla di male nell'escludere una dipendenza. Ma ogni volta che si aggiorna una dipendenza in cui è stata impostata un'esclusione, è necessario controllare:

  • se questa esclusione ha ancora senso.
  • se è necessario aggiornare la versione della dipendenza esclusa nel proprio progetto.

Immagino che le esclusioni del maven siano come coltelli da cucina. È nitido, taglia le verdure senza sforzo, ma richiede attenzione quando lo manipola ...

+1

Un'ottima risposta, grazie. Non avevo pensato ai pericoli di mantenere un'esclusione. –

+0

Ti ho assegnato il premio in base al livello di dettaglio nella tua risposta.È stato bello vedere un esempio (un po 'reale) di come questo può andare storto. –

+0

@DuncanJones Grazie. La mia risposta è piuttosto un avvertimento che una soluzione. Comunque, spero che possa essere d'aiuto. –

3

Se JUnit come un artefatto si presenta come una dipendenza in ambito di compilazione, è un errore di una delle tue librerie, qui: ca.juliusdavies.

JUnit deve sempre essere incluso nella portata del test. Pertanto, è non impacchettato nel file .jar, .war o .ear prodotto, in caso di successo.

In generale, non vi è alcun danno nell'escludere le dipendenze già incluse, come quando la libreria 1 e la libreria 2 condividono una dipendenza comune.

L'unico problema, ovviamente, che può verificarsi, è quando la libreria 1 e la libreria 2 includono versioni diverse dello stesso artefatto dipendente. Ciò può causare errori di runtime, quando le funzionalità della libreria sono cambiate. Fortunatamente, questo non accade spesso, a meno che la differenza nei numeri di versione sia ottima. In generale, è consigliabile includere l'ultima versione di dipendenza ed escludere quella più vecchia. Questo è il più delle volte percorribile.

In caso contrario, controllare se ci sono aggiornamenti per le dipendenze di primo livello del progetto.

+0

Per quanto riguarda il tuo primo punto, sì sei corretto (da qui il commento nel mio XML lamenta la stupidità di doverlo fare). Sembra che siamo d'accordo sul tuo secondo punto (relativo alla retrocompatibilità). –

+0

Duncan, penso di averti già dato la tua risposta sulla tua seconda domanda. Il rischio è potenzialmente di fronte a errori di runtime. Dato che le dipendenze dirette sono già compilate, quando le includi, la build di Maven non te lo dirà. Tutto ciò che può accadere quando si confondono versioni diverse di dipendenze indirette sono errori di runtime. Un errore di runtime è anche un errore di distribuzione di una WAR. File JAR o EAR nel contenitore Web o dell'applicazione. –

Problemi correlati