15.10 Maven: Build-Management und Abhängigkeiten auflösen
Software zu bauen und die Abhängigkeiten der Module zu überwachen, ist eine Tätigkeit, die nicht manuell, sondern automatisch passieren sollte. Die freie und quelloffene Software Apache Maven hat sich hier als Quasistandard durchgesetzt. Maven lässt sich entweder von der Website http://maven.apache.org/ beziehen und als Werkzeug von der Kommandozeile aus nutzen oder schön integriert über die Entwicklungsumgebung. Alle wichtigen IDEs unterstützten Maven von Haus aus.
Um Projekte zu beschreiben, nutzt Maven POM-Dateien (das Kürzel steht für Project Object Model). Sie enthalten die gesamte Konfiguration und Projektbeschreibung. Dazu zählen unter anderem:
Name und Kennung des Projekts
Abhängigkeiten
Compilereinstellungen
Lizenz
Eine POM-Datei heißt in der Regel pom.xml und liegt im Hauptverzeichnis einer Anwendung – die Dateiendung signalisiert, dass es sich um eine XML-Datei handelt. Ein Java-Compiler und die Werkzeuge müssen mit Maven nicht mehr von Hand aufgerufen werden, die ganze Steuerung liegt abschließend bei Maven.
15.10.1 Beispielprojekt in Eclipse mit Maven
Statt in Eclipse mit File • New • Java Project ein Projekt aufzubauen, ist der Schritt mit Maven ein anderer. Das liegt unter anderem daran, dass Maven eine eigene Verzeichnisstruktur definiert, die Standard Directory Layout genannt wird. Sie unterscheidet sich von der Standardstruktur von Eclipse, die nur ein einfaches src- und bin-Verzeichnis vorsieht. Maven unterteilt Klassen, Testfälle, Ressourcen in diverse Unterverzeichnisse.
In Eclipse öffnet File • New • Other einen Dialog, in dem unter Maven der Punkt Maven Project erscheint. Aktivieren wir Create a simple project und navigieren wir zum nächsten Dialog, lassen sich die zentralen Projekteigenschaften einstellen, die sich Koordinaten nennen. Wir wählen für ein Beispiel:
Group id: com.tutego.webapp: Die Gruppierungsbezeichnung ist mit dem Paketnamen vergleichbar. Sie repräsentiert das Unternehmen.
Artifact id: tutego-webapp: der Name des Artefakts, also das Produkt, das gebaut wird
Name: new-tutego-webapp
Mit Finish schließen wir ab. Im Package Explorer sieht die Ordnerstruktur anders aus als üblich, mit vier Code-Ordnern src/main/java, src/main/resources, src/main/test und src/test/resources. Neu ist auch ein Ordner target; einen versteckten bin-Ordner gibt es nicht mehr.
Beim Öffnen der pom.xml nutzt Eclipse einen eigenen Editor und unterschiedliche Reiter (Overview, Dependencies …) für verschiedene Aspekte der Konfigurationsdatei. Unter pom.xml lässt sich die XML-Datei direkt bearbeiten, wenn die bereitgestellten Editoren besondere Einstellungen nicht zulassen.
15.10.2 Properties hinzunehmen
Als Erstes wollen wir den Java-Compiler auf Version 11 hochsetzen. Dazu falten wir im Reiter Overview den Bereich Properties aus und klicken auf Create…, um zwei Eigenschaften hinzuzufügen, die je aus Name und Value bestehen:
maven.compiler.target auf 11
maven.compiler.source auf 11
Wechseln wir in die XML-Ansicht, hat Eclipse es so umgesetzt:
<properties>
<maven.compiler.target>11</maven.compiler.target>
<maven.compiler.source>11</maven.compiler.source>
</properties>
Wir wollen von Hand eine weitere Eigenschaft in das Element properties einfügen, und zwar für die Encodierung, die immer UTF-8 sein soll:
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
Zwar nutzt Maven nun den Java 11-Compiler und sieht alle Dateien als UTF-8-encodiert an, doch Eclipse bekommt davon nichts mit. Wir müssen Eclipse daher befehlen, aus der POM Informationen auszulesen und in die Projekteigenschaften zu übertragen. Daher gehen wir links auf den Package Explorer und aktivieren im Kontextmenü Maven • Update Project …. Danach steht bei den Projekten JRE System Library [JavaSE-11].
15.10.3 Dependency hinzunehmen
Wir wollen als Beispiel eine Abhängigkeit zu dem kleinen Web-Framework Spark (http://sparkjava.com) herstellen. Wir wechseln im POM-Editor auf den Reiter Dependencies und klicken auf die Schaltfläche Add. In das Textfeld Group Id tragen wir »com.sparkjava« ein, in Artifact Id »spark-core«, und bei Version setzen wir »2.8.0« hinein.
Die POM-Datei sieht nach dem Hinzufügen der Abhängigkeit so aus:
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.tutego.webapp</groupId>
<artifactId>tutego-webapp</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>new-tutego-webapp</name>
<properties>
<maven.compiler.target>11</maven.compiler.target>
<maven.compiler.source>11</maven.compiler.source>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>com.sparkjava</groupId>
<artifactId>spark-core</artifactId>
<version>2.8.0</version>
</dependency>
</dependencies>
</project>
[+] Tipp
Die besondere Stärke von Maven liegt im Auflösen transitiver Abhängigkeiten. Welche JAR-Dateien und Abhängigkeiten Spark nach sich zieht, zeigt der Reiter Dependency Hierarchy.
Alles ist vorbereitet, Zeit für das Hauptprogramm:
public class SparkServer {
public static void main( String[] args ) {
spark.Spark.get( "/hello", ( req, res ) -> "Hallo Browser " + req.userAgent() );
}
}
Starten wir das Programm wie üblich mit Run As • Java Application, startet ein Webserver, und unter der URL http://localhost:4567/hello können wir die Ausgabe ablesen. (Die Warnungen können wir ignorieren.) Über Run As liegen auch weitere Menüpunkte, die uns direkt in gewisse Stellen des Lebenszyklus eines Maven-Builds hineinspringen lassen.
Über das Terminal-Icon lässt sich die spezielle Maven-Console öffnen, die Mavens Konsolenausgabe zeigt.
15.10.4 Lokales und das Remote-Repository
Das Auflösen der abhängigen Java-Archive dauert beim ersten Mal länger, da Maven ein Remote Repository kontaktiert und von dort immer die neusten JAR-Dateien bezieht und lokal ablegt. Das umfangreiche Remote Repository speichert zu vielen bekannten quelloffenen Projekten fast alle Versionen von JAR-Dateien. Das Central Repository hat die URL https://repo.maven.apache.org/maven2/.
Unter Window • Show View • Other … • Maven • Maven Repositories zeigt Eclipse alle eingebundenen Repositories an.
In Eclipses Package Explorer lassen sich unter dem Projekt bei Maven Dependencies über 15 JAR-Dateien ablesen. Gespeichert werden sie selbst nicht im Projekt, sondern in einem lokalen Repository, das im Heimatverzeichnis des Anwenders liegt und .m2 heißt. Auf diese Weise teilen sich alle Maven-Projekte die gleichen JAR-Dateien, und diese müssen nicht projektweise immer neu bezogen und aktualisiert werden.
15.10.5 Lebenszylus, Phasen und Maven-Plugins
Ein Maven-Build besteht aus einem dreistufigen Lebenszyklus clean, default und site. Innerhalb dessen gibt es Phasen, zum Beispiel in default die Phase compile zum Übersetzen der Quellen. Alles, was Maven ausführt, sind Plugins, etwa compiler und viele andere, die http://maven.apache.org/plugins/ auflistet. Ein Plugin kann unterschiedliche Goals ausführen. So kennt zum Beispiel das Javadoc-Plugin (beschrieben unter http://maven.apache.org/components/plugins/maven-javadoc-plugin/) 14 Goals. Ein Goal wird später über die Kommandozeile angesprochen oder über das Run As-Kontextmenü auf der pom.xml in Eclipse.
15.10.6 Archetypes
Ein Maven-Archetype ist eine Vorlage für neue Projekte, sodass gleich diverse Klassen und Konfigurationen für einen schnellen Start generiert werden. Die Archetypen werden in einem Katalog gesammelt. http://repo.maven.apache.org/maven2/archetype-catalog.xml ist so ein Remote-Katalog.
In Eclipse lässt sich ein Katalog über Windows • Properties • Maven • Archetypes und Add Remote Catalog … hinzufügen. Anschließend können wir in Eclipse wie am Anfang ein Maven-Projekt aufbauen, nur ist jetzt Create a simple project nicht zu aktivieren, sondern wir müssen dazu mit Next auf die nächste Dialogseite wechseln. Jetzt lässt sich aus einer riesigen Liste ein Archetyp auswählen.