Baukastensysteme mit Maven

Hallo Spaß-Coder.

im letzten Jahr hatten wir uns mit grundlegenden Themen rund um Maven beschäftigt. Wir haben gelernt, was Maven ist und wie es Abhängigkeiten auflöst. Darüber hinaus haben wir auch schon ein bisschen über die weitere Abhängigkeitsanalyse, Vererbung und Ordnerstruktur gelernt. Im dritten Teil der Serie möchten wir uns nun mit dem mächtigen Plugin-System von Maven befassen.

 

Was war nochmal dieses Maven?

Diese Frage hatten wir im Artikel Mit Maven raus aus der Abhängigkeit bereits beantwortet, weshalb ich nun einen etwas anderen Blick auf Maven werfen möchte.

Maven ist im Grunde nur ein Plugin-Ausführungsframework. Das einzige, was Maven out-of-the-box tatsächlich kann ist das Auflösen der Abhängigkeiten und die Ermittlung, in welcher Reihenfolge der Build-Prozess bei mehreren Modulen ablaufen soll. Diese letzte Aufgabe übernimmt der sog. Reactor von Maven. Alle weiteren Funktionen, die Maven ausführen kann, wird durch sog. Plugins zur Verfügung gestellt.

Bei Maven werden zwei Arten von Plugins unterschieden:

  • Build-Plugins
    • Werden konfiguriert im <build>-Tag
  • Reporting Plugins
    • Werden konfiguriert im <reporting>-Tag
    • Beispiel: pmd-Plugin

Im Folgenden werden wir den Fokus auf die Build-Plugins legen, da diese den für den größten Teil unserer Arbeit von Bedeutung sind.

 

Des Plugins Kern

Eine Software, die nichts kann, erfüllt in aller Regel keinen Zweck und verschwindet schnell wieder von der Bildfläche. Aus diesem Grund stellt das Team bei Apache hinter Maven auch eine ganze Reihe nützlicher Plugins zur Verfügung. Diese werden die Kern-Plugins (engl. Core-Plugins) genannt.

Hier eine Liste der für die Java-Entwicklung nützlichsten Kern-Plugins:

Plugin Beschreibung
clean Räumt das target-Verzeichnis vor dem Build auf.
compile Kompiliert Java-Quellen.
deploy Bringt die Artefakte des Builds auf dem Repository aus (z.B. Nexus).
failsafe Führt JUnit-basierte Integrationstests in einem isolierten Classloader aus.
install Installiert die Artefakte des Builds in das lokale Maven-Repository (userhome/.m2/repository).
resources Kopiert Ressourcen in das Ausgabeverzeichnis, damit sie in ein JAR gepackt werden können.
site Generiert eine sog. Site für das aktuelle Projekt. Relevant für Reporting-Plugins.
surefire Führt JUnit-Tests in einem isolierten Classloader aus.
verifier Bietet die Möglichkeit, unterschiedliche Bedingungen zu prüfen. Hilfreich für Integrationstests.

 

Neben diesen Plugins gibt es noch weitere, die von Apache, aber auch von Drittanbietern bereitgestellt werden. Hier eine Liste weiterer, teils sehr nützlicher Plugins:

Plugin Beschreibung
assembly Bietet die Möglichkeit, Quellen und/oder Bärdateien zu einer Gruppe für die Auslieferung zusammenzupacken.
jar Packt das Build-Ergebnis zu einer JAR-Datei zusammen.
release Erstellt ein Release für das Projekt. Aktualisiert die POM(s) und erstellt Tags in der Quellverwaltung.
shade Erstellt ein sog. Uber-JAR, in das alle Abhängigkeiten des Projekts eingepackt werden.
source Packt die Quellen des Projekts zu einer Source-JAR-Datei zusammen.
war Packt das Build-Ergebnis zu einer WAR-Datei zusammen.

 

Maven-Plugins werden immer auf die gleiche Weise verwendet. Es wird ein Maven-Goal angesprochen, an welches sich das Plugin gebunden hat. Welches das ist, kann der Dokumentation des Plugins entnommen werden. Hier beispielhaft eine kurze Übersicht über die Phasen, an die sich die Plugins gebunden haben, die für das Erstellen eines JARs verwendet werden:

Phase Plugin Goal
process-resources maven-resources-plugin resources
compile maven-compiler-plugin compile
process-test-resources maven-resources-plugin testResources
test-compile maven-compiler-plugin testCompile
test maven-surefire-plugin test
package maven-jar-plugin jar
install maven-install-plugin install
deploy maven-deploy-plugin deploy

Rufen wir also mvn compile auf, so wird in der Phase compile das maven-compile-plugin aufgerufen.

 

Eine Sache der Einstellung

Nun wissen wir, wie wir ein Plugin aufrufen. Wie aber konfigurieren wir es, damit es unseren Ansprüchen genügt?

Auch hier gilt wieder das gute alte Prinzip „Convention over Configuration“. Wir können ein Plugin einfach so verwenden. Wir müssen es – anders als bei den Abhängigkeiten – in unserer POM nicht angeben, um es verwenden zu können.

Probieren wir z.B. folgenden Aufruf in unserem TicTacToe-Projekt auf (siehe Hands on Maven Dependency Management für den Quellcode dazu)

So ergibt sich folgende Ausgabe:

Wie man in der markierten Zeile sehen kann, wird das maven-pmd-plugin aufgerufen.  In unserer POM ist dazu nichts konfiguriert. Existiert das Plugin, wird es heruntergeladen und mit der Standard-Konfiguration ausgeführt.

Wie aber konfigurieren wir nun ein Plugin? Auch hier gibt es eine Konvention, die dafür sorgt, dass alle Plugins auf die gleiche Weise konfiguriert werden. Im Bereich <build> (bzw. <reporting>) können wir im Abschnitt <plugins> unsere Plugins konfigurieren. Das Ganze sieht dann am Beispiel des maven-compiler-plugins in etwa wie folgt aus:

 

Möchten wir nun z.B. mit einem anderen Compiler arbeiten, als es das Plugin im Default macht (das ist übrigens Java 1.3), so können wir dies entsprechend konfigurieren:

 

Alle Kern-Plugins sind auf der Maven-Seite von Apache in der Regel gut dokumentiert, die möglichen Konfigurationen werden dort beschrieben.

 

Versionskonflikte

Ein weiteres Problem sind unterschiedliche Versionen des gleichen Plugins. Wie, den Satz habt ihr so ähnlich schonmal gehört? Das kann gut sein, mit den gleichen Worten beginnt auch der entsprechende Abschnitt im Artikel Konfliktmanagement mit Maven. Aber nicht nur die Problemstellung ist identisch (ich wiederhole sie hier nicht noch einmal, wenn sie nicht mehr klar sein sollte, lest bitte dort nach), auch die Lösung ist gleich.

Haben wir zur Auflösung der Abhängigkeits-Konflikte das sog. Dependency-Management verwendet, nutzen wir für die Plugins das Plugin-Management.

Hier nochmal ein Beispiel, wie das Plugin-Management verwendet werden kann:

Wird das maven-compiler-plugin nun benutzt, wird es – wenn nichts anderes angegeben ist – in der Version 3.5 verwendet und mit der Konfiguration <compilerVersion>1.8</compilerVersion>. In den abhängigen POMs ist es natürlich möglich, weitere Konfigurationen zu ergänzen oder die bestehenden zu überschreiben.

 

Zusammenfassung

Plugins sind mächtige Erweiterungen zu Maven, mit denen sich fast alles erdenkliche erreichen lässt. Es gibt einen ganzen Haufen Plugins, nicht nur die von Apache, hier lohnt es sich, bei einer Problemstellung mal ein wenig zu suchen, ob das Ganze nicht schon einmal gelöst wurde.

Wir hoffen, ein wenig mehr Licht in das vielfältige Dunkel der Maven-Plugins gebracht zu haben.

 

Viel Spaß beim Optimieren eurer Build-Abläufe.

Eure Spaß-Coder

 

Dieser Artikel basiert neben unseren Erfahrungen auf den Ausführungen aus:

 

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht.