Kortgeleden heeft de Maven community besloten om toe te gaan werken naar een Maven 4 release. De eerste vraag die bij je opkomt zal waarschijnlijk zijn: wat kunnen we verwachten van deze nieuwe major release van Maven? Helaas kunnen we niet alles behandelen, maar in dit artikel lichten wij een aantal nieuwe features toe waar wij erg enthousiast over zijn (maarten mulders & Martin Kanders)
{ Verbeteringen aan de Reactor }
De features die waarschijnlijk het meeste effect zullen hebben bij het dagelijks gebruik van Maven zijn enkele verbeteringen aan de Reactor. Niet iedereen zal zich realiseren wat de Reactor is, maar het is een erg belangrijk onderdeel van Maven. Wanneer iemand Maven uitvoert is het de taak van de Reactor om de projectstructuur te verwerken, de modules in de juiste volgorde te zetten en uiteindelijk alles te bouwen. De Reactor maakt het mogelijk om met multimodule-projecten te werken.
Deze verbeteringen zijn dus vooral interessant voor gebruikers van multimodule-projecten. Tijdens onze presentatie op J-Fall 2020 hebben we een poll gehouden om te onderzoeken in hoeverre hiervan gebruik wordt gemaakt.
//multi-module-poll.jpg//
Ongeveer 75% van de Maven-gebruikers maakt gebruik van multimodule-projecten.
In de volgende paragrafen maken we gebruik van een fictief Maven-project dat uit drie modules bestaat: common, client en app. De afhankelijkheid tussen de modules is hieronder afgebeeld.
//example-project.png//
Fictief multimodule-project met onderlinge afhankelijkheden
{ Gebruik van eerder gebouwde artifacts bij –resume-from }
Het eerste punt dat we bespreken is een bugfix. Eerder was het zo dat als je Maven-build faalde op de client-module, je een hint te zien kreeg dat je de build verder kon laten gaan vanaf de gefaalde module: mvn <goal> –resume-from :client. Dit werkte echter alleen als je van tevoren common in je lokale repository had geïnstalleerd, aangezien client een afhankelijkheid op common heeft. De bugfix zorgt ervoor dat hij de gebouwde class files of artifacts in de target folder kan vinden en gebruiken als afhankelijkheid van client. Precies zoals je verwacht wanneer je de originele build wilt laten verdergaan waar die gebleven is. Meer informatie vind je in het JIRA-ticket: MNG-4660 [1].
{ Combinatie van –also-make en –resume-from }
Bij het vorige punt zou je kunnen denken: waarom zou je niet de –also-make-vlag toevoegen in combinatie met –resume-from? Dit zou automatisch de afhankelijkheden moeten bepalen en opnieuw bouwen. Het antwoord is: omdat het door een andere bug niet werkt in Maven 3. In Maven 4 is deze bug ook gefixt. Meer informatie vind je in het JIRA-ticket: MNG-6863 [2].
Hervat de build automatisch vanaf de laatst gefaalde module }Natuurlijk is –resume-from een krachtige feature, maar helaas moet je altijd nog zelf de hint lezen onderaan de gefaalde build en vervolgens overnemen in je volgende Maven-aanroep. Dit is meer moeite dan nodig zou moeten zijn. Maven 4 onthoudt zelf welke module als laatste gefaald is, zodat je met de nieuwe –resume-vlag met iets meer gemak je build hervat. Meer informatie vind je in het JIRA-ticket: MNG-5760 [3].
{ Submodule builds bewust gemaakt van volledige multimodule-project }
Stel je voor dat app een webapplicatie is die je met mvn jetty:run kunt starten. Als je dit uitvoert op de root van het multimodule-project gaat het fout. Maven zal namelijk jetty:run ook op client en common uitvoeren. Aangezien deze modules geen webapplicaties zijn, zal het falen.
Om dit op te lossen kan je Maven ook uitvoeren in de subdirectory van de app-module. Helaas zal Maven 3 zich niet bewust zijn van de andere modules in het multimodule-project. Hij zal de afhankelijkheden dus alleen kunnen vinden en gebruiken wanneer deze in een lokale of remote repository zijn geïnstalleerd. In Maven 4 is dit opgelost door Maven altijd bewust te laten zijn van het volledige multimodule-project, zelfs als je maar één module van het project wilt bouwen. Weer een reden minder om een onnodige mvn install te doen!
Op twee manieren kan jetty:run uitgevoerd worden op alleen de app-module:
- Navigeer naar de directory van de app directory en voer vanaf daar het Maven goal uit: cd app; mvn jetty:run.
- Met de ‘-f’-vlag kan je refereren naar een POM-bestand dat gebruikt moet worden voor de build. In dit geval vanaf root zou dat er als volgt uitzien: mvn -f app/pom.xml jetty:run. Meer informatie vind je in het JIRA-ticket: MNG-6118 [4].
{ Standaard recursieve build bij aggregator-POM’s }
Deze verandering is vooral interessant voor multimodule-projecten die vele levels diep gaan. Neem bijvoorbeeld Quarkus; voor elke extensie zijn er in ieder geval altijd twee submodules, namelijk deployment en runtime.
Eerder was het zo dat als je bijvoorbeeld de gRPC-module inclusief alle vijf de childmodules wilde bouwen, je de lijst van alle modules moest opgeven: mvn -pl extensions/grpc,extensions/grpc/codegen,extensions/grpc/deployment et cetera …
Maven 4 brengt de verandering dat bij de selectie van een aggregator-POM (extensions/grpc in dit geval) Maven standaard de child modules ook zal selecteren. Het bouwen van alleen de aggregator-POM zal meestal niet nuttig zijn. Mocht je dit toch willen, kan je met de vlag –non-recursive het oude gedrag terugkrijgen. Meer informatie vind je in het JIRA-ticket: MNG-6981 [5].
{ Detecteren van een warning- of error-vrije build }
Er zijn natuurlijk ook wijzigingen gedaan los van de Reactor en multimodule-projecten!
A warning is an error in the making.
(unknown author)
Veel tools geven via warnings aan dat er iets niet helemaal goed gaat en dat dit mogelijk kan leiden tot ongewenst gedrag of errors in de toekomst. Daarom is het een goed idee om bewust te zijn van de warnings en ze te limiteren.
Met de nieuwe vlag –fail-on-severity <severity> kun je de build laten falen wanneer er minimaal één WARN- of ERROR- logregel voorkomt in Maven of in één van de plug-ins. Meer informatie vind je in het JIRA-ticket: MNG-6065 [6].
{ Consistente timestamp in multimodule-projecten }
Maven genereert tijdens een build een timestamp die uiteindelijk terecht komt in het gebouwde artifact. Er was helaas een bug die ervoor zorgde dat bij elke module de timestamp opnieuw gegenereerd werd, waardoor deze dus per module verschilde.
Dit klopt niet en kan bijvoorbeeld voor in CI-situaties een erg irritante bug zijn.
Nu zal de ‘maven.build.timestamp’-property altijd gelijk zijn voor alle modules. Meer informatie vind je in het JIRA-ticket: MNG-6754 [7].
{ En er is meer! }
Maven 4 brengt nog veel meer moois, maar helaas gaat dat niet passen in dit artikel. In het kort een overzicht van enkele andere features:
– De standaardversie van een aantal plug-ins is geüpdatet. Dit geldt voor de POM, JAR, EJB, WAR, EAR, RAR en Maven Plugin packaging types.
– Wanneer de checksum van een gedownloade file niet correct is zal de build nu breken. Eerder was dit een warning. Snap je nu ons enthousiasme over –fail-on-severity ;-)?
– Bepaalde huidige warnings zullen de build nu breken. Opnieuw iets dat –fail-on-severity kan voorkomen.
– De POM’s voor het bouwen van het project en degene die gedistribueerd zal worden zullen niet meer per sé gelijk zijn. Het nut en de werking hiervan is uitgelegd in de column van Robert Scholte in het Java Magazine (eerste editie 2020) en in een videochat [9].
– De Maven Wrapper (vergelijkbaar met de Gradle Wrapper) was jarenlang apart onderhouden functionaliteit, maar maakt sinds Maven 4 deel uit van Maven zelf.
– Automatische parent/dependency-versionering.
Graag verwijzen we je door naar de release notes [10] voor alle gedetailleerde informatie.
Help zelf mee!
Maven is een enorm belangrijk project voor vrijwel alle Javanen wereldwijd. Gek genoeg zijn er maar enkele tientallen actieve contributors. Mocht je zelf willen meehelpen, kan je dat in ieder geval op de volgende twee manieren doen.
Up-for-grabs oppakken
Zoals meerdere opensource-projecten heeft Maven een grote lijst van issues die opgepakt kunnen worden door ontwikkelaars. Echter, niet alle issues zijn gemakkelijk op te pakken voor ontwikkelaars die (nog) onbekend zijn met de codebase. Speciaal hiervoor is er een selectie gemaakt van issues die dat wel zijn. Deze issues hebben het label ‘up-for-grabs’ en zijn te vinden op [11].
Automatische builds op GitHub Actions
Of je nu een ervaren Maven-ontwikkelaar bent of een beginner, het eerste wat je wilt weten bij een wijziging is of alles nog naar behoren werkt. Normaliter was het proces dat je als Maven-committer een build moest starten op de Jenkins-servers van de Apache Software Foundation met jouw wijzigingen. Deze build test de wijzingen dan op Windows- en Linux-machines met verschillende JDK-versies. Voordat wij zelf committer werden merkten we dat dat helaas soms lang kan duren.
We hebben dit proces vereenvoudigd met GitHub Actions. Als je nu een pull request opent start automatisch een build op Windows, Linux en macOS tegen verschillende JDKs. Veel snellere feedback dus, juist voor die eerste bijdragen!
Doordat macOS nu ook wordt meegenomen hebben we zelfs een falende test gevonden [8] die alleen op macOS voorkwam. Je kunt de GitHub builds in actie zien op https://github.com/apache/maven/actions.
{ Bleeding edge testen }
Naast het doorontwikkelen van Maven is het ook belangrijk om de laatste (onuitgebrachte) versies te testen. Het is immers niet handig als de nieuwste versie vol bugs uitkomt. Dus, als jij de nieuwste versie wilt uitproberen juichen we dat toe! Bijkomend voordeel is dat je meteen kunt profiteren van de nieuwste features en bugfixes. Als je macOS of Linux gebruikt, kun je gebruikmaken van Maartens ‘Homebrew tap’ [12] om gemakkelijk de nieuwste versie te installeren. Dit werkt als volgt:
brew ta mthmulders/maven-snapshot brew install maven-snapshot
Mocht je weer terug willen naar de laatst uitgebrachte Maven-versie, kan dat met de volgende commando’s:
brew unlink maven && brew link maven-snapshot
brew unlink maven-snapshot && brew link maven
Op Windows kun je hetzelfde doen door middel van Martins ‘Chocolatey’-package. Voer het volgende uit om de maven-snapshot te installeren:
choco install maven-snapshot refreshenv
Gebruik daarna het volgende om de origineel geïnstalleerde Maven-versie weer te activeren:
choco uninstall maven-snapshot refreshenv
Let wel op: hoewel er getest wordt tegen duizenden integratietesten op verschillende platformen, kunnen er absoluut nog fouten in zitten. We raden het dus niet aan om dit in te zetten in bedrijfskritieke situaties. We moedigen het aan om het in te zetten op je development-machine. Mocht je issues vinden, laat het dan alsjeblieft weten op JIRA [13].
{ Samenvattend }
Wij zijn erg enthousiast over al het moois dat Maven 4 brengt! Wij hebben met veel plezier meegewerkt aan een aantal van deze mooie features in de tijd van onze werkgever Info Support. We zijn erg blij dat we deze tijd krijgen, want we vinden het belangrijk om de tool die zo belangrijk is voor ons werk nóg beter te kunnen maken. Volg de JIRA-links om meer informatie en de relevante GitHub pull requests te vinden.
{ Verwijzingen }
- MNG-4660: https://issues.apache.org/jira/browse/MNG-4660
- MNG-6863: https://issues.apache.org/jira/browse/MNG-6863
- MNG-5760: https://issues.apache.org/jira/browse/MNG-5760
- MNG-6118: https://issues.apache.org/jira/browse/MNG-6118
- MNG-6981: https://issues.apache.org/jira/browse/MNG-6981
- MNG-6065: https://issues.apache.org/jira/browse/MNG-6065
- MNG-6754: https://issues.apache.org/jira/browse/MNG-6754
- MNG-6951: https://issues.apache.org/jira/browse/MNG-6951
- Videochat Build/consumer POM: https://youtu.be/KDAmlNKZJto
- Maven 4 release notes: https://issues.apache.org/jira/secure/ReleaseNote.jspa?projectId=12316922&version=12346477
- Up for grab issues: https://s.apache.org/for-the-grabs_maven
- Maven Snapshot tap voor Homebrew: https://github.com/mthmulders/homebrew-maven-snapshot/
- Maven issue tracker: https://issues.apache.org/jira/
{ Bio’s }
Martin Kanters
Martin Kanters is senior software engineer en Java community lead bij Info Support en actief als committer bij Apache Maven.
Maarten Smulders
Maarten Mulders is architect, senior software engineer en trainer bij Info Support; daarnaast spreekt hij op conferenties en is hij als committer actief bij Apache Maven.