Meer met Maven – mvn verify als standaard

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.

Zoals bekend is het mijn doel om mensen ervan te overtuigen dat ze “mvn verify” als standaard Maven commando moeten gebruiken in plaats van “mvn clean install”. Maar er is er een tweede onderwerp dat mij bezighoudt: de onuitputtelijke verslaving aan skip parameters voor elke plugin-goal. Regelmatig komen er verzoeken voorbij om een skip-parameter toe te voegen aan bestaande goals. En het meest gehoorde argument: heel veel andere goals hebben het ook, dus waarom hier niet?

Dat het op zoveel plekken bestaat, suggereert dat het een best practice is, maar daar ben ik het niet mee eens. Ik werd tijdens de discussie erop gewezen dat zelfs de compile-goal van de maven-compiler-plugin een skipMain optie heeft. Wat mij betreft geheel onterecht: de taak van de compiler-plugin is om alle sources te compileren. En als er geen sources zijn, dan valt er niks te compileren. Ik kan geen reden bedenken, die deze skip-optie rechtvaardigt. Dat de parameter nog bestaat is meer om backwards compatibility redenen.

De noodzaak voor skip is voor mij een teken, dat elders in het project de configuratie verkeerd staat. En een skip-parameter is zeer inefficiënt: allereerst wordt de plugin instantie ingeladen en de eerste regel is: if ( skip ) { return; }

Het is veel beter, als de plugin helemaal niet voorkomt in je “buildplan. Daarom is het goed om regelmatig naar de output te kijken van builds en jezelf de vraag te stellen: snap ik waarom alle goals aangeroepen worden? Regelmatig zie ik, dat geprobeerd wordt om het resultaat van één goal te corrigeren met één of meerdere anderen. En zo ontstaat al snel een keten van elkaar “corrigerende” goals en plugins. De build wordt er niet sneller van en uiteindelijk snapt niemand er meer iets van. Opruimen is vaak de juiste oplossing, in plaats van het activeren van tal van skip-parameters.

Maven is gebaseerd op overerven en uitbreiden. Maak gebruik van de default plugins die door Maven aan een lifecycle zijn gekoppeld. Als er meer moet gebeuren, breid dan de pom uit. Bedenk het volgende: als je iets wilt verwijderen, waarom heb je het dan eerder al toegevoegd? Dit is ook de belangrijkste reden waarom de Build Helper Maven Plugin alleen maar “add” en “attach” goals heeft. Alle verzoeken voor “remove” en “detach” goals zijn afgewezen, omdat dit een hack zou zijn voor een probleem eerder in de keten.

De oplossing voor het globaal configureren en het selectief activeren van een plugin met goal werkt als volgt:

In de parent:

    <pluginManagement>
      <plugins>
        <plugin>
          <groupId>nl.jug.plugins</groupId>
          <artifactId>maven-plugin</artifactId>
          <version>1.0.0</version>
          <executions>
            <execution>
              <id>check</id>
              <phase>verify</phase>
              <goals>
                <goal>run</goal>
              </goals>
              <configuration/>
            </execution>
          </executions>
        </plugin>
      </plugins>
    </pluginManagement>

In de projecten, waar je dit wilt gebruiken, neem je het volgende op:

    <build>
      <plugins>
        <plugin>
          <groupId>nl.jug.plugins</groupId>
          <artifactId>maven-plugin</artifactId>
        </plugin>
      </plugins>
    </build>

Als er meerdere execution-bloks zijn, kun je eventueel bij het laatste nog een execution-blok met ‘check’ als id en ‘none’ als phase opvoeren om alleen dit blok niet uit te voeren. Het doel moet in ieder geval zijn om Maven alleen zinvolle plugins en goal uit te laten voeren, daar wordt je build efficiënter en overzichtelijker van.