Att hantera beroenden i Maven 2

Maven är bra på många sätt och vis. Det underlättar verkligen byggprocessen och beroenden mellan olika komponenter hanteras tämligen väl. Det är ändå inte ovanligt att man behöver hjälpa Maven lite på traven om man har många snåriga beroenden och det är ämnet för dagens inlägg.

Om ditt projekt har ett beroende till tredjepartskomponenten VeryGoodLibraryA-1.0 som beror på StandardComponent-2.1 kommer Maven att hantera detta transitiva beroende (från version 2.0) och ladda ner (om det behövs) och tillhandahålla såväl VeryGoodLibraryA-1.0 som StandardComponent-2.1. Men vad händer om du även beror på VeryGoodLibraryB-1.0 som i sin tur beror på StandardComponent-2.5?

Folk som är inne i OSGi-svängen kanske rycker på axlarna undrar vad som är problemet. Men så roligt ska vi inte ha eftersom vi nu antar att såväl VeryGoodLibraryA-1.0 som VeryGoodLibraryB-1.0 klarar sig bra med StandardComponent-2.5 som råkar vara bakåtkompatibel med StandardComponent-2.1.

Hur reder vi ut detta? Till att börja med kanske man inte vet att det är VeryGoodLibraryA och VeryGoodLibraryB som har olika åsikter om vad som är lämplig version på StandardComponent. Lyckligtvis är det en av de saker som Maven-pluginet Maven Dependency Plugin kan hjälpa oss med.

För att se vilka beroenden som huserar i vårt projekt kör vi följande harang:
mvn dependency:resolve

I den rapport som spottas ut ser vi egentligen bara problemet, Maven har favoriserat fel version av StandardComponent (2.1 istället för 2.5).

För att bli lite klokare på vem som har bereonden till vem prövar vi träd-vyn:
mvn dependency:tree

Med samma enkla exempel som ovan skulle svaret kunna se ut ungefär så här:

[INFO] +- org.verygoodlibrary:A:jar:1.0:compile
[INFO] | +- org.standardcomponent:standard-component:jar:2.1:compile
[INFO] +- org.verygoodlibrary.B:jar:1.0:compile
[INFO] | - org.standardcomponent:standard-component:jar:2.5:compile

Nu bör vi ha fått lite bättre kläm på problemet och vet hur vi skulle vilja ha det. Det finns, som vanligt, flera sätt att lösa problemet och innan man gör något förhastat kan det vara klokt att läsa en introduktion till beroende-hanteringen i Maven.

I introduktionen ovan kan man läsa att Maven favoriserar det beroende som är närmast till ditt projekt i beroendeträdet. Om beroendena är på samma nivå avgör (sedan Maven 2.0.5) deklarationsordningen.

Ett sätt att lösa det förenklade exemplet ovan skulle kunna vara att byta plats på beroendena (dependency-elementen för VeryGoodLibraryA och VeryGoodLibraryB) i pom.xml:en.

Ett annat sätt att lösa ut knuten skulle kunna vara att säga åt Maven att ignorera VeryGoodLibraryA:s beroende på StandardComponent-2.1. Då kommer VeryGoodLibraryB:s beroende på StandardComponent-2.5 att kunna lösas ut och allt blir bra. Detta kan göras med exclusion-element på VeryGoodLibraryA:s dependency-element i ditt projekts pom.

 <dependency>
  <groupid>org.verygoodlibrary</groupid>
  <artifactid>A</artifactid>
  <version>1.0</version>
  <exclusions>
   <exclusion>
    <artifactid>standard-component</artifactid>
   </exclusion>
  </exclusions>
 </dependency>

I mitt konkreta verkliga fall består mitt projekt av en hel hierarki med egna projekt. Där tyckte jag det blev enklast att speca lite versioner på toppnivån (den “översta” pom.xml:en).

Har ni egna erfarenheter av Mavens beroendehantering eller byggverktyg i allmänhet? Eller bättre lösningar på ovanstående problem? Kommentera gärna isf.

This entry was posted in arbete, datorer, Java, programmering and tagged , . Bookmark the permalink.

Leave a Reply

Your email address will not be published. Required fields are marked *