Ako vyriešiť kolíziu verzií artefaktov v Mavene

1. Prehľad

Viacmodulové projekty Maven môžu mať zložité grafy závislostí. Tieto môžu mať neobvyklé výsledky, tým viac moduly navzájom importujú.

V tomto návode uvidíme, ako na to vyriešiť kolíziu verzií artefaktov v Mavene.

Začneme projektom s viacerými modulmi, kde sme zámerne použili rôzne verzie toho istého artefaktu. Potom uvidíme, ako zabrániť získaniu nesprávnej verzie artefaktu pomocou správy vylúčenia alebo závislostí.

Nakoniec skúsime použiť maven-enforcer-plugin aby sme uľahčili ovládanie vecí zákazom používania tranzitívnych závislostí.

2. Verzia Kolízia artefaktov

Každá závislosť, ktorú zahrnieme do nášho projektu, sa môže prepojiť s inými artefaktmi. Maven môže automaticky priniesť tieto artefakty, ktoré sa tiež nazývajú tranzitívne závislosti. Ku kolízii verzie dôjde, keď sa na ten istý artefakt odkazuje viac závislostí, ale používajú sa rôzne verzie.

V dôsledku toho sa môžu v našich aplikáciách vyskytnúť chyby vo fáze kompilácie, ako aj za behu programu.

2.1. Štruktúra projektu

Definujme viacmodulovú štruktúru projektu, s ktorou budeme experimentovať. Náš projekt sa skladá z a verzia-kolízia modul pre rodičov a tri deti:

version-collision project-a project-b project-collision 

The pom.xml pre projekt-a a projekt-b sú takmer identické. Jediný rozdiel je vo verzii com.google.guava artefakt, od ktorého závisia. Najmä projekt-a používa verziu 22.0:

  com.google.guava guava 22.0 

Ale, projekt-b používa novšiu verziu, 29,0-jre:

  com.google.guava guava 29.0-jre 

Tretí modul, kolízia projektu, závisí od ďalších dvoch:

  com.baeldung project-a 0.0.1-SNAPSHOT com.baeldung project-b 0.0.1-SNAPSHOT 

Takže, ktorá verzia guava bude k dispozícii pre kolízia projektu?

2.2. Používanie funkcií z konkrétnej verzie závislosti

To, ktorá závislosť sa používa, môžeme zistiť vytvorením jednoduchého testu v kolízia projektu modul, ktorý používa Futures.immediateVoidFuture metóda z guava:

@Test public void whenVersionCollisionDoesNotExist_thenShouldCompile () {assertThat (Futures.immediateVoidFuture (), notNullValue ()); }

Táto metóda je k dispozícii iba od spoločnosti 29,0-jre verzia. Toto sme zdedili z jedného z ďalších modulov, ale náš kód môžeme zostaviť, iba ak dostaneme tranzitívnu závislosť od projekt-b.

2.3. Chyba kompilácie spôsobená kolíziou verzie

Podľa poradia závislostí v kolízia projektu modul v určitých kombináciách vráti Maven chybu kompilácie:

[CHYBA] Nepodarilo sa uskutočniť cieľ org.apache.maven.plugins: maven-compiler-plugin: 3.8.1: testCompile (default-testCompile) pri kolízii projektu: Zlyhanie kompilácie [CHYBA] / tutoriály / maven-all / verzia -collision / project-collision / src / test / java / com / baeldung / version / collision / VersionCollisionUnitTest.java: [12,27] nemôže nájsť symbol [ERROR] symbol: method google.common.util.concurrent.Futures

To je výsledok kolízie verzie com.google.guava artefakt. V predvolenom nastavení vyberie Maven prvú knižnicu, ktorú nájde, pre závislosti na rovnakej úrovni v strome závislostí. V našom prípade oboje com.google.guava závislosti sú v rovnakej výške a je vybraná staršia verzia.

2.4. Použitím maven-dependency-plugin

The maven-dependency-plugin je veľmi užitočný nástroj na predstavenie všetkých závislostí a ich verzií:

% závislosť mvn: strom -Dverbose [INFO] --- plugin pre závislosť maven: 2,8: strom (predvolené-cli) @ kolízia projektu --- [INFO] com.baeldung: kolízia projektu: jar: 0,0.1 -SNAPSHOT [INFO] + - com.baeldung: project-a: jar: 0.0.1-SNAPSHOT: kompilácia [INFO] | \ - com.google.guava: guava: jar: 22.0: kompilácia [INFO] \ - com.baeldung: project-b: jar: 0.0.1-SNAPSHOT: kompilácia [INFO] \ - (com.google.guava: guava : jar: 29.0-jre: kompilácia - vynechané pre konflikt s 22.0)

The -Dverbose príznak zobrazuje konfliktné artefakty. V skutočnosti máme a com.google.guava závislosť v dvoch verziách: 22.0 a 29.0-jre. Posledný z nich by sme chceli použiť v kolízia projektu modul.

3. Vylúčenie prechodnej závislosti z artefaktu

Jedným zo spôsobov riešenia kolízie verzie je odstránenie konfliktnej prechodnej závislosti od konkrétnych artefaktov. V našom príklade nechceme mať com.google.guava knižnica prechodne pridaná z projekt-a artefakt.

Preto to môžeme vylúčiť v kolízia projektu pom:

  com.baeldung project-a 0.0.1-SNAPSHOT com.google.guava guava com.baeldung project-b 0.0.1-SNAPSHOT 

Teraz, keď spustíme závislosť: strom príkaz, vidíme, že tam už nie je:

% závislosť mvn: strom -Dverbose [INFO] --- plugin pre závislosť maven: 2,8: strom (predvolené-cli) @ kolízia projektu --- [INFO] com.baeldung: kolízia projektu: jar: 0,0.1 -SNAPSHOT [INFO] \ - com.baeldung: project-b: jar: 0.0.1-SNAPSHOT: kompilovať [INFO] \ - com.google.guava: guava: jar: 29.0-jre: kompilácia

Výsledkom je, že fáza kompilácie končí bez chyby a môžeme použiť triedy a metódy z verzie 29,0-jre.

4. Pomocou dependencyManagement Oddiel

Maven dependencyManagement oddiel je a mechanizmus centralizácie informácií o závislosti. Jednou z najužitočnejších funkcií je ovládanie verzií artefaktov používaných ako tranzitívne závislosti.

S ohľadom na to vytvorme a dependencyManagement konfigurácia v našom rodičovi pom:

   com.google.guava guava 29.0-jre 

Výsledkom bude, že Maven zaistí použitie verzie 29,0-jre z com.google.guava artefakt vo všetkých podradených moduloch:

% závislosť mvn: strom -Dverbose [INFO] --- plugin pre závislosť maven: 2,8: strom (predvolené-cli) @ kolízia projektu --- [INFO] com.baeldung: kolízia projektu: jar: 0,0.1 -SNAPSHOT [INFO] + - com.baeldung: project-a: jar: 0.0.1-SNAPSHOT: kompilácia [INFO] | \ - com.google.guava: guava: jar: 29.0-jre: kompilácia (verzia spravovaná od 22.0) [INFO] \ - com.baeldung: project-b: jar: 0.0.1-SNAPSHOT: kompilácia [INFO] \ - (com.google.guava: guava: jar: 29.0-jre: kompilácia - verzia spravovaná od 22.0; pre duplikát vynechaná)

5. Zabráňte náhodným tranzitným závislostiam

The maven-enforcer-plugin poskytuje mnoho zabudovaných pravidiel, ktoré zjednodušiť správu viacmodulového projektu. Jeden z nich zakazuje používanie tried a metód z tranzitívnych závislostí.

Explicitná deklarácia závislosti odstraňuje možnosť kolízie verzií artefaktov. Pridajme maven-enforcer-plugin s týmto pravidlom nášmu rodičovi pom:

 org.apache.maven.plugins maven-enforcer-plugin 3.0.0-M3 vynútiť-zakázať-závislosti vynútiť 

V dôsledku toho musíme teraz výslovne vyhlásiť com.google.guava artefakt v našom kolízia projektu modul, ak ho chceme používať sami. Musíme buď určiť verziu, ktorá sa má použiť, alebo nastaviť dependencyManagement u rodiča pom.xml. Vďaka tomu je náš projekt viac odolný voči chybám, ale vyžaduje si od nás, aby sme boli v našom dokumente explicitnejší pom.xml súbory.

6. Záver

V tomto článku sme videli, ako vyriešiť kolíziu verzií artefaktov v Mavene.

Najskôr sme preskúmali príklad kolízie verzie v multimodulovom projekte.

Potom sme si ukázali, ako vylúčiť prechodné závislosti v pom.xml. Pozreli sme sa na to, ako ovládať verzie závislostí pomocou dependencyManagement oddiel v rodič pom.xml.

Nakoniec sme vyskúšali maven-enforcer-plugin zakázať používanie tranzitívnych závislostí s cieľom prinútiť každý modul prevziať kontrolu nad svojou vlastnou.

Ako vždy, kód zobrazený v tomto článku je k dispozícii na GitHub.