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)
1 |
mvn pmd:pmd |
So ergibt sich folgende Ausgabe:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
[INFO] Scanning for projects... [INFO] [INFO] ------------------------------------------------------------------------ [INFO] Building TicTacToe 1.0.0-SNAPSHOT [INFO] ------------------------------------------------------------------------ [INFO] [INFO] --- maven-pmd-plugin:3.6:pmd (default-cli) @ TicTacToe --- [WARNING] Unable to locate Source XRef to link to - DISABLED [WARNING] File encoding has not been set, using platform encoding Cp1252, i.e. build is platform dependent! [INFO] ------------------------------------------------------------------------ [INFO] BUILD SUCCESS [INFO] ------------------------------------------------------------------------ [INFO] Total time: 2.585 s [INFO] Finished at: 2016-01-24T10:31:03+01:00 [INFO] Final Memory: 17M/209M [INFO] ------------------------------------------------------------------------ |
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:
1 2 3 4 5 6 7 8 9 10 |
<plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>3.5</version> <configuration> <!-- hier kommt die Konfiguration hin --> </configuration> </plugin> </plugins> |
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:
1 2 3 4 5 6 7 8 9 10 |
<plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>3.5</version> <configuration> <compilerVersion>1.8</compilerVersion> </configuration> </plugin> </plugins> |
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:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
<groupId>de.invidit</groupId> <artifactId>invid-parent</artifactId> <version>1</version> <pluginManagement> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>3.5</version> <configuration> <compilerVersion>1.8</compilerVersion> </configuration> </plugin> </plugins> </pluginManagement> |
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:
- Maven-Training von René Gielen – IT Neering (nahezu alles, was wir über Maven wissen, wissen wir direkt oder indirekt von ihm. Danke René!)
- http://maven.apache.org/plugins
- https://maven.apache.org/ref/3.2.2/maven-core/default-bindings.html
-
Hüttermann, Michael – Agile ALM, Manning Publications Co., 2011