{"id":827,"date":"2016-01-26T16:15:41","date_gmt":"2016-01-26T14:15:41","guid":{"rendered":"http:\/\/invidit.de\/blog\/?p=827"},"modified":"2016-01-24T22:07:19","modified_gmt":"2016-01-24T20:07:19","slug":"baukastensysteme-mit-maven","status":"publish","type":"post","link":"https:\/\/invidit.de\/blog\/baukastensysteme-mit-maven\/","title":{"rendered":"Baukastensysteme mit Maven"},"content":{"rendered":"<p>Hallo Spa\u00df-Coder.<\/p>\n<p>im letzten Jahr hatten wir uns mit grundlegenden Themen rund um Maven besch\u00e4ftigt. Wir haben gelernt, was <a href=\"http:\/\/invidit.de\/blog\/mit-maven-raus-aus-der-abhaengigkeit\/\" target=\"_blank\">Maven ist und wie es Abh\u00e4ngigkeiten aufl\u00f6st<\/a>. Dar\u00fcber hinaus haben wir auch schon ein bisschen \u00fcber die weitere <a href=\"http:\/\/invidit.de\/blog\/konfliktmanagement-mit-maven\/\" target=\"_blank\">Abh\u00e4ngigkeitsanalyse, Vererbung und Ordnerstruktur<\/a> gelernt. Im dritten Teil der Serie m\u00f6chten wir uns nun mit dem m\u00e4chtigen Plugin-System von Maven befassen.<\/p>\n<p>&nbsp;<\/p>\n<h1>Was war nochmal dieses Maven?<\/h1>\n<p>Diese Frage hatten wir im Artikel <a href=\"http:\/\/invidit.de\/blog\/mit-maven-raus-aus-der-abhaengigkeit\/\" target=\"_blank\">Mit Maven raus aus der Abh\u00e4ngigkeit<\/a> bereits beantwortet, weshalb ich nun einen etwas anderen Blick auf Maven werfen m\u00f6chte.<\/p>\n<p>Maven ist im Grunde nur ein Plugin-Ausf\u00fchrungsframework. Das einzige, was Maven out-of-the-box tats\u00e4chlich kann ist das Aufl\u00f6sen der Abh\u00e4ngigkeiten und die Ermittlung, in welcher Reihenfolge der Build-Prozess bei mehreren Modulen ablaufen soll. Diese letzte Aufgabe \u00fcbernimmt der sog. <em>Reactor <\/em>von Maven. Alle weiteren Funktionen, die Maven ausf\u00fchren kann, wird durch sog. <strong>Plugins<\/strong> zur Verf\u00fcgung gestellt.<\/p>\n<p>Bei Maven werden zwei Arten von Plugins unterschieden:<\/p>\n<ul>\n<li><strong>Build-Plugins<\/strong>\n<ul>\n<li>Werden konfiguriert im &lt;build&gt;-Tag<\/li>\n<\/ul>\n<\/li>\n<li><strong>Reporting Plugins<\/strong>\n<ul>\n<li>Werden konfiguriert im &lt;reporting&gt;-Tag<\/li>\n<li>Beispiel: pmd-Plugin<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<p>Im Folgenden werden wir den Fokus auf die <strong>Build-Plugins<\/strong> legen, da diese den f\u00fcr den gr\u00f6\u00dften Teil unserer Arbeit von Bedeutung sind.<\/p>\n<p>&nbsp;<\/p>\n<h1>Des Plugins Kern<\/h1>\n<p>Eine Software, die nichts kann, erf\u00fcllt in aller Regel keinen Zweck und verschwindet schnell wieder von der Bildfl\u00e4che. Aus diesem Grund stellt das Team bei Apache hinter Maven auch eine ganze Reihe n\u00fctzlicher Plugins zur Verf\u00fcgung. Diese werden die Kern-Plugins (engl. Core-Plugins) genannt.<\/p>\n<p>Hier eine Liste der f\u00fcr die Java-Entwicklung n\u00fctzlichsten Kern-Plugins:<\/p>\n<table class=\"infotable\">\n<thead>\n<tr>\n<th>Plugin<\/th>\n<th>Beschreibung<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td>clean<\/td>\n<td>R\u00e4umt das target-Verzeichnis vor dem Build auf.<\/td>\n<\/tr>\n<tr>\n<td>compile<\/td>\n<td>Kompiliert Java-Quellen.<\/td>\n<\/tr>\n<tr>\n<td>deploy<\/td>\n<td>Bringt die Artefakte des Builds auf dem Repository aus (z.B. Nexus).<\/td>\n<\/tr>\n<tr>\n<td>failsafe<\/td>\n<td>F\u00fchrt JUnit-basierte Integrationstests in einem isolierten Classloader aus.<\/td>\n<\/tr>\n<tr>\n<td>install<\/td>\n<td>Installiert die Artefakte des Builds in das lokale Maven-Repository (<em>userhome<\/em>\/.m2\/repository).<\/td>\n<\/tr>\n<tr>\n<td>resources<\/td>\n<td>Kopiert Ressourcen in das Ausgabeverzeichnis, damit sie in ein JAR gepackt werden k\u00f6nnen.<\/td>\n<\/tr>\n<tr>\n<td>site<\/td>\n<td>Generiert eine sog. Site f\u00fcr das aktuelle Projekt. Relevant f\u00fcr Reporting-Plugins.<\/td>\n<\/tr>\n<tr>\n<td>surefire<\/td>\n<td>F\u00fchrt JUnit-Tests in einem isolierten Classloader aus.<\/td>\n<\/tr>\n<tr>\n<td>verifier<\/td>\n<td>Bietet die M\u00f6glichkeit, unterschiedliche Bedingungen zu pr\u00fcfen. Hilfreich f\u00fcr Integrationstests.<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>&nbsp;<\/p>\n<p>Neben diesen Plugins gibt es noch weitere, die von Apache, aber auch von Drittanbietern bereitgestellt werden. Hier eine Liste weiterer, teils sehr n\u00fctzlicher Plugins:<\/p>\n<table class=\"infotable\">\n<thead>\n<tr>\n<th>Plugin<\/th>\n<th>Beschreibung<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td>assembly<\/td>\n<td>Bietet die M\u00f6glichkeit, Quellen und\/oder B\u00e4rdateien zu einer Gruppe f\u00fcr die Auslieferung zusammenzupacken.<\/td>\n<\/tr>\n<tr>\n<td>jar<\/td>\n<td>Packt das Build-Ergebnis zu einer JAR-Datei zusammen.<\/td>\n<\/tr>\n<tr>\n<td>release<\/td>\n<td>Erstellt ein Release f\u00fcr das Projekt. Aktualisiert die POM(s) und erstellt Tags in der Quellverwaltung.<\/td>\n<\/tr>\n<tr>\n<td>shade<\/td>\n<td>Erstellt ein sog. Uber-JAR, in das alle Abh\u00e4ngigkeiten des Projekts eingepackt werden.<\/td>\n<\/tr>\n<tr>\n<td>source<\/td>\n<td>Packt die Quellen des Projekts zu einer Source-JAR-Datei zusammen.<\/td>\n<\/tr>\n<tr>\n<td>war<\/td>\n<td>Packt das Build-Ergebnis zu einer WAR-Datei zusammen.<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>&nbsp;<\/p>\n<p>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 \u00dcbersicht \u00fcber die Phasen, an die sich die Plugins gebunden haben, die f\u00fcr das Erstellen eines JARs verwendet werden:<\/p>\n<table class=\"infotable\">\n<thead>\n<tr>\n<th>Phase<\/th>\n<th>Plugin<\/th>\n<th>Goal<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td>process-resources<\/td>\n<td>maven-resources-plugin<\/td>\n<td>resources<\/td>\n<\/tr>\n<tr>\n<td>compile<\/td>\n<td>maven-compiler-plugin<\/td>\n<td>compile<\/td>\n<\/tr>\n<tr>\n<td>process-test-resources<\/td>\n<td>maven-resources-plugin<\/td>\n<td>testResources<\/td>\n<\/tr>\n<tr>\n<td>test-compile<\/td>\n<td>maven-compiler-plugin<\/td>\n<td>testCompile<\/td>\n<\/tr>\n<tr>\n<td>test<\/td>\n<td>maven-surefire-plugin<\/td>\n<td>test<\/td>\n<\/tr>\n<tr>\n<td>package<\/td>\n<td>maven-jar-plugin<\/td>\n<td>jar<\/td>\n<\/tr>\n<tr>\n<td>install<\/td>\n<td>maven-install-plugin<\/td>\n<td>install<\/td>\n<\/tr>\n<tr>\n<td>deploy<\/td>\n<td>maven-deploy-plugin<\/td>\n<td>deploy<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>Rufen wir also <em>mvn compile<\/em> auf, so wird in der Phase <em>compile<\/em> das <em>maven-compile-plugin<\/em> aufgerufen.<\/p>\n<p>&nbsp;<\/p>\n<h1>Eine Sache der Einstellung<\/h1>\n<p>Nun wissen wir, wie wir ein Plugin aufrufen. Wie aber konfigurieren wir es, damit es unseren Anspr\u00fcchen gen\u00fcgt?<\/p>\n<p>Auch hier gilt wieder das gute alte Prinzip &#8222;Convention over Configuration&#8220;. Wir k\u00f6nnen ein Plugin einfach so verwenden. Wir m\u00fcssen es &#8211; anders als bei den Abh\u00e4ngigkeiten &#8211; in unserer POM nicht angeben, um es verwenden zu k\u00f6nnen.<\/p>\n<p>Probieren wir z.B. folgenden Aufruf in unserem TicTacToe-Projekt auf (siehe <a href=\"http:\/\/invidit.de\/blog\/hands-on-maven-dependency-management\/\" target=\"_blank\">Hands on Maven Dependency Management<\/a> f\u00fcr den Quellcode dazu)<\/p>\n<pre class=\"nums:false nums-toggle:false lang:default decode:true\">mvn pmd:pmd<\/pre>\n<p>So ergibt sich folgende Ausgabe:<\/p>\n<pre class=\"nums:false nums-toggle:false lang:xhtml mark:7 decode:true\">[INFO] Scanning for projects...\r\n[INFO]\r\n[INFO] ------------------------------------------------------------------------\r\n[INFO] Building TicTacToe 1.0.0-SNAPSHOT\r\n[INFO] ------------------------------------------------------------------------\r\n[INFO]\r\n[INFO] --- maven-pmd-plugin:3.6:pmd (default-cli) @ TicTacToe ---\r\n[WARNING] Unable to locate Source XRef to link to - DISABLED\r\n[WARNING] File encoding has not been set, using platform encoding Cp1252, i.e. build is platform dependent!\r\n[INFO] ------------------------------------------------------------------------\r\n[INFO] BUILD SUCCESS\r\n[INFO] ------------------------------------------------------------------------\r\n[INFO] Total time: 2.585 s\r\n[INFO] Finished at: 2016-01-24T10:31:03+01:00\r\n[INFO] Final Memory: 17M\/209M\r\n[INFO] ------------------------------------------------------------------------<\/pre>\n<p>Wie man in der markierten Zeile sehen kann, wird das <em>maven-pmd-plugin<\/em> aufgerufen.\u00a0 In unserer POM ist dazu nichts konfiguriert. Existiert das Plugin, wird es heruntergeladen und mit der Standard-Konfiguration ausgef\u00fchrt.<\/p>\n<p>Wie aber konfigurieren wir nun ein Plugin? Auch hier gibt es eine Konvention, die daf\u00fcr sorgt, dass alle Plugins auf die gleiche Weise konfiguriert werden. Im Bereich &lt;build&gt; (bzw. &lt;reporting&gt;) k\u00f6nnen wir im Abschnitt &lt;plugins&gt; unsere Plugins konfigurieren. Das Ganze sieht dann am Beispiel des maven-compiler-plugins in etwa wie folgt aus:<\/p>\n<pre class=\"lang:xhtml decode:true\">&lt;plugins&gt;\r\n  &lt;plugin&gt;\r\n    &lt;groupId&gt;org.apache.maven.plugins&lt;\/groupId&gt;\r\n    &lt;artifactId&gt;maven-compiler-plugin&lt;\/artifactId&gt;\r\n    &lt;version&gt;3.5&lt;\/version&gt;\r\n    &lt;configuration&gt;\r\n      &lt;!-- hier kommt die Konfiguration hin --&gt;\r\n    &lt;\/configuration&gt;\r\n  &lt;\/plugin&gt;\r\n&lt;\/plugins&gt;<\/pre>\n<p>&nbsp;<\/p>\n<p>M\u00f6chten wir nun z.B. mit einem anderen Compiler arbeiten, als es das Plugin im Default macht (das ist \u00fcbrigens Java 1.3), so k\u00f6nnen wir dies entsprechend konfigurieren:<\/p>\n<pre class=\"lang:xhtml mark:7 decode:true\">&lt;plugins&gt;\r\n  &lt;plugin&gt;\r\n    &lt;groupId&gt;org.apache.maven.plugins&lt;\/groupId&gt;\r\n    &lt;artifactId&gt;maven-compiler-plugin&lt;\/artifactId&gt;\r\n    &lt;version&gt;3.5&lt;\/version&gt;\r\n    &lt;configuration&gt;\r\n      &lt;compilerVersion&gt;1.8&lt;\/compilerVersion&gt;\r\n    &lt;\/configuration&gt;\r\n  &lt;\/plugin&gt;\r\n&lt;\/plugins&gt;<\/pre>\n<p>&nbsp;<\/p>\n<p>Alle Kern-Plugins sind auf der Maven-Seite von Apache in der Regel gut dokumentiert, die m\u00f6glichen Konfigurationen werden dort beschrieben.<\/p>\n<p>&nbsp;<\/p>\n<h1>Versionskonflikte<\/h1>\n<p>Ein weiteres Problem sind unterschiedliche Versionen des gleichen Plugins. Wie, den Satz habt ihr so \u00e4hnlich schonmal geh\u00f6rt? Das kann gut sein, mit den gleichen Worten beginnt auch der entsprechende Abschnitt im Artikel <a href=\"http:\/\/invidit.de\/blog\/konfliktmanagement-mit-maven\/\" target=\"_blank\">Konfliktmanagement mit Maven<\/a>. 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\u00f6sung ist gleich.<\/p>\n<p>Haben wir zur Aufl\u00f6sung der Abh\u00e4ngigkeits-Konflikte das sog. <em>Dependency-Management<\/em> verwendet, nutzen wir f\u00fcr die Plugins das <em>Plugin-Management<\/em>.<\/p>\n<p>Hier nochmal ein Beispiel, wie das Plugin-Management verwendet werden kann:<\/p>\n<pre class=\"lang:xhtml mark:5 decode:true \">&lt;groupId&gt;de.invidit&lt;\/groupId&gt;\r\n&lt;artifactId&gt;invid-parent&lt;\/artifactId&gt;\r\n&lt;version&gt;1&lt;\/version&gt;\r\n\r\n&lt;pluginManagement&gt;\r\n  &lt;plugins&gt;\r\n    &lt;plugin&gt;\r\n      &lt;groupId&gt;org.apache.maven.plugins&lt;\/groupId&gt;\r\n      &lt;artifactId&gt;maven-compiler-plugin&lt;\/artifactId&gt;\r\n      &lt;version&gt;3.5&lt;\/version&gt;\r\n      &lt;configuration&gt;\r\n        &lt;compilerVersion&gt;1.8&lt;\/compilerVersion&gt;\r\n      &lt;\/configuration&gt;\r\n    &lt;\/plugin&gt;\r\n  &lt;\/plugins&gt;\t\r\n&lt;\/pluginManagement&gt;<\/pre>\n<p>Wird das maven-compiler-plugin nun benutzt, wird es &#8211; wenn nichts anderes angegeben ist &#8211; in der Version 3.5 verwendet und mit der Konfiguration &lt;compilerVersion&gt;1.8&lt;\/compilerVersion&gt;. In den abh\u00e4ngigen POMs ist es nat\u00fcrlich m\u00f6glich, weitere Konfigurationen zu erg\u00e4nzen oder die bestehenden zu \u00fcberschreiben.<\/p>\n<p>&nbsp;<\/p>\n<h1>Zusammenfassung<\/h1>\n<p>Plugins sind m\u00e4chtige Erweiterungen zu Maven, mit denen sich fast alles erdenkliche erreichen l\u00e4sst. 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\u00f6st wurde.<\/p>\n<p>Wir hoffen, ein wenig mehr Licht in das vielf\u00e4ltige Dunkel der Maven-Plugins gebracht zu haben.<\/p>\n<p>&nbsp;<\/p>\n<p>Viel Spa\u00df beim Optimieren eurer Build-Abl\u00e4ufe.<\/p>\n<p>Eure Spa\u00df-Coder<\/p>\n<p>&nbsp;<\/p>\n<p>Dieser Artikel basiert neben unseren Erfahrungen auf den Ausf\u00fchrungen aus:<\/p>\n<ul>\n<li id=\"gs_cit0\" class=\"gs_citr\" tabindex=\"0\">Maven-Training von Ren\u00e9 Gielen &#8211; <a href=\"http:\/\/it-neering.net\/\">IT Neering<\/a> (nahezu alles, was wir \u00fcber Maven wissen, wissen wir direkt oder indirekt von ihm. Danke Ren\u00e9!)<\/li>\n<li class=\"gs_citr\" tabindex=\"0\"><a href=\"http:\/\/maven.apache.org\/plugins\" target=\"_blank\">http:\/\/maven.apache.org\/plugins<\/a><\/li>\n<li class=\"gs_citr\" tabindex=\"0\"><a href=\"https:\/\/maven.apache.org\/ref\/3.2.2\/maven-core\/default-bindings.html\" target=\"_blank\">https:\/\/maven.apache.org\/ref\/3.2.2\/maven-core\/default-bindings.html<\/a><\/li>\n<li class=\"gs_citr\" tabindex=\"0\">\n<div id=\"gs_cit0\" class=\"gs_citr\" tabindex=\"0\">H\u00fcttermann, Michael &#8211; <em>Agile ALM<\/em>, Manning Publications Co., 2011<\/div>\n<\/li>\n<\/ul>\n<p>&nbsp;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Hallo Spa\u00df-Coder. im letzten Jahr hatten wir uns mit grundlegenden Themen rund um Maven besch\u00e4ftigt. Wir haben gelernt, was Maven ist und wie es Abh\u00e4ngigkeiten aufl\u00f6st. Dar\u00fcber hinaus haben wir auch schon ein bisschen \u00fcber die weitere Abh\u00e4ngigkeitsanalyse, Vererbung und Ordnerstruktur gelernt. Im dritten Teil der Serie m\u00f6chten wir uns nun mit dem m\u00e4chtigen Plugin-System [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":863,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[22],"tags":[124,128],"_links":{"self":[{"href":"https:\/\/invidit.de\/blog\/wp-json\/wp\/v2\/posts\/827"}],"collection":[{"href":"https:\/\/invidit.de\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/invidit.de\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/invidit.de\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/invidit.de\/blog\/wp-json\/wp\/v2\/comments?post=827"}],"version-history":[{"count":33,"href":"https:\/\/invidit.de\/blog\/wp-json\/wp\/v2\/posts\/827\/revisions"}],"predecessor-version":[{"id":871,"href":"https:\/\/invidit.de\/blog\/wp-json\/wp\/v2\/posts\/827\/revisions\/871"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/invidit.de\/blog\/wp-json\/wp\/v2\/media\/863"}],"wp:attachment":[{"href":"https:\/\/invidit.de\/blog\/wp-json\/wp\/v2\/media?parent=827"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/invidit.de\/blog\/wp-json\/wp\/v2\/categories?post=827"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/invidit.de\/blog\/wp-json\/wp\/v2\/tags?post=827"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}