Ant nun? Maven!


Frher war Ant, heute ist Maven. Obwohl sich beide nicht ausschliessen, sondern Maven Ant integriert, ist Maven ein neuer Ansatz einen Buildprozess umfassend zu beschreiben. Dem Flegma unterschiedlicher Buildprozesse fr Projekte und Produkte wirkt Maven entschieden entgegen. Wer seine Projekte schon immer einheitlich beschreiben, dokumentieren, packen und verteilen wollte, findet in Maven ein umfangreiches und solides Werkzeug zur Generierung und Verteilung seiner Jar- und Konfigurationsdateien. Mittels der Plugin-Architektur, der Ant-Integration und Repository Strukturen hat sich Maven zu einem Werkzeug mit grossem Funktionsumfang gemausert. Wer ein Plugin sucht, und nicht weiss, ob fr seine Zwecke ein Plugin zur Verfgung steht, der fhrt einfach maven -g aus, und erhlt eine bersicht aller installierten Plugins, oder sieht sich auf der Maven Homepage die Plugin Beschreibungen an [1 = http://maven.apache.org/reference/plugins/index.html]. Zudem sind dort alle konfigurierbaren Parameter der Plugins beschrieben.

Projektbeschreibung durch POM

Mittlerweile als stabiles Release in der Version 1.0.2 verfgbar, bezeichnet sich Maven selbst als Project Management Werkzeug, das ein Projekt durch einen POM (Project Object Modell) reprsentiert. Das POM selbst wird in der project.xml Datei verfasst, wobei die wichtigsten Parameter in Tabelle 1 aufgefhrt sind.
 
Durch die Definition von Standard-Parameter im POM werden Konfigurationen ausgelagert. Einstellungen fr alle Builds werden in identisch strukturierten Dateien gefunden und gendert. Projektverantwortliche knnen deshalb ohne Kenntnisse des Buildprozesses selbstndig das POM verwalten, ohne dass ein Buildverantwortlicher die gewnschten Einstellungen wie beispielsweise die Versionsnummer vornimmt. Hat man nun im POM folgenden Eintrag definiert,

<build>
    <sourceDirectory>src/java</sourceDirectory>
</build>

so werden mit maven java:compile alle Java Sourcen unterhalb von ./src/java kompiliert. Nheres ber java:compile erfhrt man, wenn man maven -g ausfhrt, das wiederum alle plugins und die zugehrigen Goals auffhrt. In diesem Fall ist java ein plugin und compile ein Goal. Fhrt man maven aus, so erwartet es im gegenwrtigen Verzeichnis das project.xml, sofern man den Pfad nicht mit -p vorgibt. Wnscht man eine Jar-Datei aus den Class Dateien zu erstellen, dann ruft man maven java:jar auf. Zuerst werden die Java Quelldateien kompiliert, danach wird eine Jar Datei aus den Klassen erzeugt. Durch diese Goals wird bereits deutlich, dass im Jar Goal eine Abhngigkeit zu java:compile existiert. Ruft man ein jar:deploy Goal auf, so verhlt es sich hnlich. Zuerst wird der Java Compiler aufgerufen (java:compile), dann die Classdateien in ein Jar verpackt (java:jar) und schlussendlich wird die Jar-Datei in ein Remote Repository bertragen. 

Einheitliche Verzeichnis- und Repositorystrukturen

ber Projekte hinweg erwartet Maven per Voreinstellung einige Dateien in bestimmten Verzeichnissen. Startet man Maven mit einem Goal als Parameter, so sucht es im aktuellen Verzeichnis nach einem project.xml und nach einem Goal  in maven.xml. Da Maven sehr stark ber Parameter gesteuert wird, spielen die Properties eine bergeordnete Rolle. Properties werden nach herkmmlicher Java Manier mit dem Kommandozeilenparameter -D, in plugin.properties, project.properties und build.properties, bzw. auch im maven.xml als Variable definiert und genau in dieser Reihenfolge abgearbeitet und berschrieben.
Ein neues sehr ntzliches Konzept sind die Repositories. Der Java Klassenpfad wird aus dem <Dependencies> Tag im project.xml zusammengesetzt. Startet man Maven das erste mal werden alle bentigten Jar-Dateien aus einem Remoterepository heruntergeladen und im Localrepository abgelegt. Laut Grundeinstellung ist das im Homeverzeichnis des Benutzers: $HOME/.maven/cache/repository. Oft ist es sinnvoll ein Remoterepository im lokalen Netzwerk aufzusetzen, wenn Jar-Dateien im Standard-Remoterepository nicht verfgbar sind, oder um eigene Jar-Dateien dort abzulegen. Dann definiert man ein Property: maven.repo.remote = http://myRemoteRepository/maven, http://www.ibiblio.org/maven, was Maven dazu veranlasst Jar-Dateien zuerst im erstgenannten Repository zu suchen und abzuholen. Ntzlich ist diese nderung insbesondere bei Integration von Maven in Eclipse oder Netbeans, wenn Entwicklerteams ihre Java Sourcen mit Maven kompilieren und ebenfalls diese Jar Dateien bentigen. Alternativ knnen Jar Dateien direkt im lokalen Repository abgelegt werden, was allerdings oft zu erhhten Wartezeiten bei Kompiliervorgngen fhren kann; insbesondere, wenn man Projektabhngigkeiten zu sogenannten Snapshotreleases definiert sind. Snapshotreleases haben als Versionsnummer den Namen Snapshot und sind mit einer Jar-Datei verlinkt, die als Version ein Datum besitzt. Mit dieser Technik erreicht man, dass immer die zuletzt erzeugte Jar-Datei geladen wird. 

Individuelle Buildsteuerung

Die individuelle Steuerung und Programmierung des Buildprozesses geschieht im maven.xml, das beim Buildstart im gleichen Verzeichnis gesucht wird, wie project.xml. Dort werden Plugins aufgerufen und eigene Ablufe mit einer Skriptsprache namens Jelly, ebenfalls ein Apache Projekt, verfasst. Jelly ist das, was man heutzutage unter dem Ausdruck executable XML versteht. Eine Skriptsprache die in XML deklariert wird, in Java geschrieben wurde, und dadurch Zugriff auf Java Klassen, Methoden und Attribute erlaubt. Es stehen aber nicht nur die Jelly-Sprachkonstrukte, sondern alle Ant-Konstrukte zur Verfgung. Der vollstndigkeithalber sei hier genannt, dass eigene Taglibraries, in Verbindung mit eigenen Jelly-Beans verknpft werden knnen, um individuell XML Tags bereitzustellen. Ein einfaches maven.xml ist in Listing 1 dargestellt:

<project 
  xmlns:j="jelly:core"
  xmlns:ant="jelly:ant"
  xmlns:maven="jelly:maven">
  
  <goal name="ix_testgoal" description="A testgoal">
    <j:if test="${context.getVariable('my.property') != null}">
      <attainGoal name="java:compile"/>
    </j:if>
  </goal>
  
  <preGoal name="java:compile">
    <echo>Starting ix_testgoal</echo>
  </preGoal>
  <postGoal name="java:compile">
    <echo>Finishing ix_testgoal</echo>
  </postGoal>
</project>

xmlns verbindet ein XML-Tag mit einer Jelly Library. In diesem Beispiel wird abhngig von einem gesetzten Property das bereits bekannte java:compile ausgefhrt. Der Testparameter der if-Abfrage wirkt etwas gewhnungsbedrftig. Man kann die Variable auch direkt abfragen. In diesem Beispiel wrde aber ${my.property != null} zu einer Abfrage einer Variablen property im Objekt my fhren, die offensichtlich nicht existiert und stets als Ergebnis null liefert. Trgt man nun die Zeile my.property=aProperty in build.properties ein, so wird nun das attainGoal ausgefhrt. Mit attainGoal kann an jeder Stelle des maven.xml ein beliebiges Goal ausgefhrt werden. Soll vor einem bestimmten Goal eine Aktion durchgefhrt werden, so greift man auf <preGoal> zurck. Equivalent dazu steht ein <postGoal> fr die Ausfhrung nach einem Goal zur Verfgung.
Sehr oft wird in maven.xml ein Multiprojekt Plugin eingesetzt. Es erlaubt die Ausfhrung von mehreren Projekten in Reihenfolge, was insbesondere bei Applikationen mit mehreren Teilprojekten eingesetzt wird. Es erlaubt eine individuelle Zusammenstellung von einzelnen Buildmodulen nach belieben. Existieren beispielsweise 2 Projekte, wobei Projekt A von Projekt B abhngig ist, dann definiert man in Projekt B ein <dependency> und 

Von der Buildsteuerung zum Plugin

Bei hufiger Benutzung bestimmter Ablufe im Buildprozess hegt man den Wunsch eigene Goals zur Hand zu haben, die ber ein Plugin aufgerufen werden. Die Steuerdatei fr Plugins nennt sich  plugin.jelly und ist vom Aufbau equivalent zum maven.xml. Der Goalname muss jedoch der Konvention pluginname:goalname gengen um ausgefhrt zu werden. Zuerst legt man auf gewohntem Wege ein project.xml wie in Listing 3 aufgefhrt an. Listing 4 zeigt das zugehrige plugin.jelly. In einem plugin.properties knnen Voreinstellungen fr Variablen gesetzt werden. In unserem Beispiel wurde ein Plugin zur Erstellung einer Buildnummer erzeugt. Will man das Plugin installieren, so nutzt man wieder, wie knnte es anderst sein, ein Plugin von Maven. Aus dem Verzeichnis in dem das project.xml und plugin.jelly liegt ist maven zu starten: maven plugin:install. Das Plugin wird in diesem Fall als maven-buildnumber-1.0.0.jar in $MAVEN_HOME/lib/plugins kopiert und beim ersten Aufruf nach $HOME/.maven/cache entpackt. Beim ersten Aufruf von Maven werden alle Plugins in den Cache extrahiert. Ein Blick in die verschieden plugin.jelly Dateien lohnt sich. Wer nicht weiss, wie man in Jelly ein Problem lst, der wird mit grosser Wahrscheinlichkeit dort fndig werden. Die Jelly-Skripte knnen auch direkt editiert werden. Hat man etwas falsch gemacht, dann wird das Cache Verzeichnis gelscht, und alle Plugins werden wiederum in das Cache Verzeichnis entpackt.

Sourcerepositories anbinden

In den hufigsten Fllen sind die Quelldateien in einem Sourcerepository wie Subversion, CVS oder VSS hinterlegt. Die Verbindungsdaten werden unter dem <repository> Tag als sogenannter connection String im POM hinterlegt: 
<connection>scm:cvs:pserver:username@host:/cvs:projektname</connection>
<url>http://cvs.apache.org/viewcvs.cgi/maven/</url>
Die URL wird wiederum auf der Projektwebseite als Link zum direkten Zugriff auf das Source-Repository verwendet. Zu beachten ist, dass fr die Konfiguration von Subversion der Delimiter fr den Verbindungsstring nicht ein Doppelpunkt, sondern das Pipesymbol (|) ist, weil Subversion die Host-Repository Angabe als URL beschreibt und diese bekanntlich selbst Doppelpunkte enthlt. Fr die Verbindungserstellung sind wiederum native Clients verantwortlich. Den Verbindunssaufbau und die -Kontrolle bernimmt nicht Maven, sondern es ist die Installation beispielsweise eines CVS Clients ntig. Das dafr zustndige SCM (Source Control Management) Plugin fhrt  nur den zweiten Teil des Verbindungsstrings als Systembefehl aus: cvs, oder fr Subversion svn. Zum auschecken der Quelltexte ist dann nur noch scm:project-checkout aufzurufen, und die Dateien werden nach <sourceDirectory> kopiert.

Plugins soweit das Auge reicht

In Maven gibt es fr fast alle Anwendungsflle Plugins. Sei es fr die Verteilung der generierten jar-Dateien, Dokumentationen usw.  auf andere Hosts (bspw. jar:deploy) oder das Ausfhren mehrerer Goals in unterschiedlichen Subprojekten mittels des Multiproject-Plugin, das die reactor-Anweisung von Maven benutzt. Jeder drfte das fr ihn/sie passende Plugin finden.
Besonders interessant ist das site Plugin, das eine Dokumentation basierend auf xml-Dateien erstellt. Zum einen kann individuell Dokumentation fr die Projektwebseite erstellt werden, zum anderen liefert Maven bereits vorgefertigte Reports zur Erstellung von Javadocs oder beispielsweise zur Darstellung von Dateiaktivitten. Insgesamt stehen derzeit 13 Standardreports zur Verfgung, die ber POM bei Bedarf aktiviert werden knnen. Wnscht man eigene Texte in die Webseite einzubinden, so ist ein Verzeichnis xdocs und unterhalb davon eine Datei navigation.xml zu erstellen wie in Listing 5 dargestellt. Diese Datei beschreibt das Men und die dazugehrigen Dateien, die bei der Navigation aufgerufen werden. Hat man beispielsweise eine Datei overview.html definiert, so erstellt man equivalent eine Datei overview.xml [Listing 6] die dann vom xdoc Plugin in eine entsprechende HTML Datei umgewandelt wird. Alternativ oder zustzlich kann mit maven pdf ein PDF Dokument erzeugt werden.

Fazit
Maven ist ein sehr mchtiges Werkzeug, das sich sowohl fr Einsteiger, als auch fr grosse Projekte eignet. Insbesondere fr Softwareprojekte mit vielen Modulen und/oder vielen Abhngkeiten eignet sich Maven ausgezeichnet. Etwas gewhnungsbedrftig und auch umstndlich zu debuggen ist Jelly. Administratoren die nicht sehr programmiererfahren sind, und eigene Plugins schreiben mssen, werden ihre liebe Mhe mit Jelly haben. Dennoch ist es einfacher mit einer Skriptsprache Plugins und Steuerdateien zu erstellen, als Plugins in Ant und mit Java zu programmieren. Deutlich wird von den Entwicklern hervorgehoben, dass Maven einfach zu bedienen und zu erweitern ist, und doch bietet es auch fr den eingefleischten Programmierer eine professionell durchdachte Spielwiese, die auf einer soliden Architektur mit einem gelungenen Pluginkonzept aufbaut. Die einfache Bedienung wird gerade seit und mit Release 1.0 verstrkt untersttzt, was mit der steigenden Anzahl von Dokumentationsseiten einhergeht.

 


