Meer met Maven – Plugins & PluginManagement

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.

Wie zich wel eens heeft verdiept in de opties van de pom.xml, moet het opgevallen zijn dat hier voor plugins twee plekken zijn, waar deze entiteiten opgegeven kunnen worden:

 


<project>
  <build>
    <pluginManagement>
      <plugins></plugins> <!-- managed plugins -->
    </pluginManagement>
 
    <plugins></plugins> <!-- used plugins -->
  </build>
</project>

 

Dit leidt regelmatig tot verwarring. Vrij vaak komen op diverse mailinglijsten of Q&A-sites issues voorbij waarbij gebruikers ervan overtuigd zijn dat ze de plugin goed hebben geconfigureerd, maar waar Maven de plugin toch niet aanroept. De reden blijkt vaak te zijn dat de plugin alleen onder pluginManagement opgenomen is. Vandaar deze keer: extra verheldering over het doel van pluginManagement.

 

Voordat Maven daadwerkelijk begint met bouwen, stelt het eerst een bouwplan op. Zo’n bouwplan resulteert uiteindelijk in een lijst met plugins die in een bepaalde volgorde uitgevoerd zullen worden. Allereerst zal Maven op basis van het packaging-type bepalen welke plugin per phase uitgevoerd moet worden. Een groot aantal is al geconfigureerd in Maven-core.  Zelfs voor de packaging-type ‘pom’ zijn plugins gedefinieerd:

 


<!-- START SNIPPET: pom-lifecycle -->
<phases>
  <install>
    org.apache.maven.plugins:maven-install-plugin:2.4:install
  </install>
  <deploy>
    org.apache.maven.plugins:maven-deploy-plugin:2.7:deploy
  </deploy>
</phases>
<!-- END SNIPPET: pom-lifecycle -->

 

Je ziet dat hier al een default versie opgegeven is per plugin. Deze kan per Maven release bijgewerkt worden. Maven gebruikt dus niet automatisch de laatste versie.  Hierdoor blijven builds van gebruikers even stabiel als voorheen, ondanks een nieuwe release van een specifieke plugin.

 

Vervolgens loopt Maven door de <build><plugins> van de effectieve pom.xml heen. (Effectief betekent dit dat alle overervingen van parents gecombineerd zijn tot één complete pom). Maven zal nu proberen te achterhalen welke goal(s) van een plugin uitgevoerd moet of moeten worden én op welk moment van de lifecycle. Dat doet Maven door per plugin alle execution-blocks langs te gaan, waarbij één of meerdere goals staan. Als voor zo’n execution-block ook een phase is opgenomen, dan is dát het moment wanneer de goals worden uitgevoerd. In sommige gevallen is bij voorbaat al duidelijk wat de meest ideale phase van een goal is. De plugin-ontwikkelaar kan zelf al een defaultPhase vastleggen, zodat gebruikers het niet meer expliciet in de pom.xml hoeven op te geven. Het is een default, je kunt als gebruiker nog steeds de goal aan een andere phase koppelen.

 

En dan pluginManagement. Deze kan gebruikt worden om plugins te configureren zonder ze aan te laten roepen. Als een plugin aangeroepen wordt, zal Maven ook de pluginManagement controleren voor eventuele aanpassingen van de plugin configuratie.

 

Als best practice kun je de volgende richtlijnen volgen:

  • Bij de packaging van het type ‘pom’ benoem je alle plugins in de pluginManagement.
  • Alle plugins die als default aan de lifecycle phases zijn gekoppeld op basis van de packaging neem je op in de pluginManagement. Dus bijvoorbeeld voor een jar: maven-resources-plugin, maven-compiler-plugin, maven-surefire-plugin, etc.
  • De overige plugins rechtstreeks binnen de plugins opnemen, anders worden ze immers niet aangeroepen.

 

Door de opsplitsing van de plugins tussen pluginManagement-plugins en directe plugins zie in één opslag welke plugins onderdeel zijn van de standaard build lifecycle en welke als custom plugins zijn toegevoegd aan het bouwproces van dit project. Als je je aan deze conventie houdt, zijn plugins ook sneller terug te vinden in de pom.xml.

 

De les die je hieruit kunt leren, is dat als een plugin alleen onder pluginManagement wordt genoemd, Maven de bijbehorende goals nooit aan zal roepen. Sterker nog: Maven zal niet eens controleren of deze plugins daadwerkelijk bestaan.