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.
Robert Scholte
Voor een basis Java project heb je vaak voldoende aan de plugins die tijdens de build lifecycle aangeroepen worden. Maar wat als je structureel extra plugins wilt uit laten voeren, hoe doe je dat?
Laten we als voorbeeld gebruik maken van de maven-enforcer-plugin om een aantal randvoorwaarden voor dit project te controleren. Door de maven-enforcer-plugin op te nemen in je pom onder project.build.plugins kan deze plugin onderdeel uit gaan maken van de lifecycle. Voor alle duidelijkheid, onder pluginManagement zal dit niet lukken. PluginManagement is namelijk bedoelt voor het globaal configureren van plugins zonder dat de plugins actief deel uitmaken van een lifecycle.
De maven-enforcer-plugin plugin heeft drie zogenoemde goals, te weten enforce, display-info en help. We moeten in de pom op de een of andere manier aan gaan geven dat we de enforce-goal willen uitvoeren tijden de lifecycle. Dit bereiken we door het toevoegen van een execution-block, waarbinnen we als goal “enforce” opgeven.
Vervolgens moeten we ons af gaan vragen tijdens welke phase deze goal uitgevoerd moet worden. Het ligt voor de hand dat we deze enforcer rules zo snel mogelijk willen uitvoeren zodat de build al faalt bij de start als niet aan de randvoorwaarden wordt voldaan. Met andere woorden: de validate-phase lijkt de beste keuze, dus deze phase kunnen we opgeven binnen ons execution-block. Als we echter de documentatie van deze goal erbij pakken, dan zien we het volgende: “Binds by default to the lifecycle phase: validate”. Dit is een goed voorbeeld van convention over configuration: de enforce-goal zal zichzelf standaard koppelen aan de validate-phase, maar dit kun je naar behoefte aanpassen. Met andere woorden: in dit geval is het toevoegen van de phase optioneel.
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-enforcer-plugin</artifactId>
<version>3.0.0-M1</version>
<executions>
<execution>
<id>enforce-dependencies</id>
<phase>validate</phase> <!– optioneel –>
<goals>
<goal>enforce</goal>
</goals>
<configuration>
<rules>
<requireUpperBoundDeps/>
</rules>
</configuration>
</execution>
</executions>
<configuration>
<!– globale plugin configuratie –>
</configuration>
</plugin>
Als je voortaan `mvn validate` uitvoert, zal bovenstaand executionblock uitgevoerd worden.
Voor alle duidelijkheid: het opnemen van de plugin met slechts een groupId, artifactId en version is niet voldoende. Maven gaat namelijk NIET uitzoeken welke goals een plugin bevat en welke aan een specifieke phase zijn gekoppeld. De kans bestaat namelijk dat een plugin meerdere goals bevat en dat je slechts in één geïnteresseerd bent. Je zal per execution-block minstens één goal moeten benoemen, eventueel aangevuld met de phase wanneer de goal of goals uitgevoerd moeten worden.
Stel nu dat er meerdere plugins aan de validate gekoppeld zijn, kun je dan alleen de maven-enforcer-plugin aanroepen? Als je “mvn enforcer:enforce” aanroept, zal de plugin klagen over het onbreken van rules. Er is namelijk geen globale plugin configuratie, er is allleen configuratie binnen een execution-block.
Sinds Maven 3.3.1 is het mogelijk om vanaf de commandline een expliciete executionblock uit te voeren door de goal-aanroep uit te breiden met @<executionId>, oftewel in ons voorbeeld:
mvn enforcer:enforce@ enforce-dependencies
Dit is voor die uitzonderlijke gevallen waarbij je een specifiek execution-block wilt uitvoeren en het gebruik van een globale plugin configuratie niet mogelijk is.