The Apache Maven Archiver

In elke editie zal Robert Scholte een probleem voorleggen en deze oplossen met behulp van Apache Maven om meer inzicht te geven in Maven zelf en de vele beschikbare plugins.

Door de jaren heen heb ik aardig wat projecten mogen migreren naar Maven. Dit soort projecten voldeden meestal niet aan de standaard folder structuur die Maven hanteert, maar dat is geen probleem. Je kunt de pom.xml altijd dusdanig configureren dat Maven prima met een afwijkende structuur overweg kan. Nee, de uitdaging zit vaak in het achterhalen van de gebruikte jars. Meestal bevatten deze projecten een lib-directory met een grote hoeveelheid jars, bij voorkeur zonder een versienummer. Hierdoor kon je makkelijker jars upgraden zonder dat er allerlei scripts of classpaths aangepast hoefden te worden. Als je tegen een bug aanliep, ging je naar dubieuze websites en downloadde je gewoon een andere jar in de hoop dat deze nieuwer was, dat de bug gefixt was en dat het nog steeds backwards compatible was. En dan maar hopen dat een collega de vorige jar niet had gepatcht om ongedocumenteerde redenen. Dat waren de “wild west”-achtige taferelen van vroeger.

Ondertussen zijn die tijden wel wat veranderd, alhoewel ik zeker weet dat er nog projecten zijn die werken volgens de vorige paragraaf. Om dit soort projecten Maven-ready te maken zit de uitdaging dus vooral in het achterhalen van de exacte jars die gebruikt worden en om deze beschikbaar te stellen via de company artifact repository. Op basis van de naam en het eventuele versienummer kun je vaak via http://search.maven.org wel de groupId erbij vinden. Er is echter een betrouwbaardere manier. Via de Advanced Search op dezelfde website kun je de SHA-1 Checksum opgeven van een artifact. Als deze in Central beschikbaar is, krijg je de bijbehorende GAV (GroupId/ArtifactId/Version) te zien. Er zijn tal van online en offline tools om de checksum van een jar uit te rekenen, bijvoorbeeld via de checksum-maven-plugin van Julien Nicoulaud. Door te zoeken op basis van de checksum kun je gemiddeld al meer dan de helft van alle dependencies achterhalen.

Levert dit geen resultaat op, dan kun je zoeken naar een alternatief voor de artifact, want wellicht is er een andere versie beschikbaar die ook compatible is. Een andere optie is om de artifact zelf te uploaden naar de artifact repository. Maar dat betekent dat je zelf een zinnige groupId en version moet verzinnen. Als de artifact een META-INF/maven folder bevat heb je geluk, want dan bestaat hoogstwaarschijnlijk ook  META-INF/maven/${groupId}/${artifactId}/pom.properties en pom.xml, die beide de version waarde bevatten. Daarmee heb je de GAV compleet.

De kans is echter vrij groot dat de artifact niet met Maven is gebouwd. In dat geval is de eerste plek waar zinvolle informatie kan staan: de META-INF/MANIFEST.MF. Met wat geluk kun je hier een versienummer uithalen via bijvoorbeeld de Implementation-version of Specification-Version, hopelijk ook de groupId op basis van Implementation-Vendor-Id of Implementation-Title. Maar deze informatie is alleen zichtbaar als de oorspronkelijke ontwikkelaar deze informatie expliciet heeft opgegeven. Vaak is dat niet zo en bevat de MANIFEST.MF slechts:

  • Manifest-Version: 1.0
  • Created-By: Ant 1.3

In zo’n geval is de best practice om de gemeenschappelijke package-structuur van alle classes als groupId te gebruiken. Als je echt geen idee hebt om welk versienummer het gaat, dan toch maar bij 1.0 beginnen.

Een groot deel van de hierboven benoemde bestanden wordt al standaard door Maven gevuld en mee gebundeld in de artifact. Hiervoor is een shared component beschikbaar: de Apache Maven Archiver. De meeste packaging-plugins maken hier gebruik van en bevatten de <archive> optie  om dit verder te specificeren. Wil je bijvoorbeeld de pom.properties en pom.xml niet in je jar? Wil je extra gegevens in je MANIFEST.MF? Wil je dat er ook een INDEX.LIST gegenereerd wordt?

Bekijk https://s.apache.org/dVyE voor alle mogelijke opties om deze metadata naar je hand te zetten.