Anpassung von Maven an eigene Wünsche
←
→
Transkription von Seiteninhalten
Wenn Ihr Browser die Seite nicht korrekt rendert, bitte, lesen Sie den Inhalt der Seite unten
Kapitel 2 KAPITEL 2 Anpassung von Maven an eigene Wünsche In Kapitel 1 haben Sie die Datei project.xml kennen gelernt, die die Be- In diesem Kapitel: schreibung des Projekts, Ihrer Organisation, des Teams, die Platzierung • Installation ei- der Quelltextdateien und alle anderen für Mavens Buildprozess erforder- nes Plugins aus lichen Informationen enthält. Sie haben gesehen, wie man die verfügba- einem Inter- ren Ziele ausgibt und wie einfach der Umgang mit Maven ist. Oft ist es net-Repository aber erforderlich, den Standardbuildprozess von Maven an eigene Vor- • Benutzerspezifi- stellungen anzupassen. Vielleicht benötigen Sie zum Beispiel eine JAR- sche Anpassung eines Plugins Datei in einem anderen Verzeichnis, oder Sie wollen sogar ein eigenes • Erstellung eige- Ziel erstellen. In diesem Kapitel werden wir solche Dinge mit Hilfe von ner Ziele Jelly und der Datei maven.xml ermöglichen. • Definition eines Die benutzerspezifische Anpassung von Maven geschieht in einer XML- preGoal basierenden Skriptsprache namens Jelly. Jelly verarbeitet eine Folge von • Definition eige- XML-Tags, die sequenziell ausgeführt werden. Jelly kennt so genannte ner Properties Tag-Bibliotheken, die jeweils eine Gruppe von Tags definieren und zur • Start des Pro- Verfügung stellen. Darüber hinaus gibt es verschiedene Tags, die den gramms aus ei- nem eigenen Ziel Kern von Jelly bilden und Kontrollstrukturen, z.B. Schleifen, zur Verfü- • Einrichtung ei- gung stellen. Wenn Sie sich mit den Buildskripten von Ant auskennen, nes Standard- dann werden Sie Jelly auf Anhieb verstehen. Im Kontext von Maven wird ziels Jelly als Skriptsprache benutzt. Die Plugins von Maven 1 sind zu großen • Properties über- Teilen in Jelly geschrieben. Dieses Kapitel behandelt Jelly als Mittel der schreiben Wahl zur Erweiterung und Anpassung von Maven. • Iteration über Das Beispielprojekt namens Weather, mit dem wir in dieser Übung arbei- Abhängigkeiten ten werden, finden Sie auf der Website des Buchs unter http://www. • Anpassung von Look and Feel mavenbook.org. Sie können das Projekt auch aus dem Subversion-Repo- der Website sitory ziehen, das Sie unter http://www.mavenbook.org/svn/mdn/code/ • Benutzung des finden. FAQ-Plugins 43
TIPP Bei Maven 1 sind Plugins normalerweise in Jelly geschrieben. In Ma- ven 2 wird diese XML-basierende Skriptsprache durch Plugins ersetzt, die in ganz normalem Java geschrieben sind. Seien Sie also einiger- maßen zurückhaltend mit Jelly. Für die Abkehr von Jelly in Maven 2 gibt es verschiedene Gründe, unter anderem Geschwindigkeit. Dem- zufolge tun Sie gut daran, in Ihr maven.xml so wenig wie möglich zu packen und vorzugsweise vorhandene Plugins zu verwenden. Sie er- leichtern sich damit den zukünftigen Umstieg auf Maven 2. Natürlich wirft das gerade eben Gesagte die Frage nach dem Sinn dieses Kapi- tels auf. Aber bei der Arbeit mit Maven 1 ist Jelly eben doch unver- zichtbar, und letzten Endes wird auch Maven 2 in irgendeiner Form Unterstützung für Jelly enthalten, auch wenn Plugin-Autoren aufge- fordert sind, Java zur Implementation ihrer Plugins zu bevorzugen. Tatsächlich werden in Maven 2 sogar mehrere Skriptsprachen wie Groovy oder Marmalade unterstützt. In diesem Kapitel werden wir aber nur Jelly vorstellen und uns darauf verlassen, dass die vorge- stellten Konzepte und Ideen weiterhin möglich und relevant bleiben. Installation eines Plugins aus einem Internet-Repository Alle Ihre Bekannten aus der Java-Szene benutzen die neueste und beste Version dieses ganz bestimmten Maven-Plugins, so dass Sie sich allmäh- lich altbacken vorkommen. Wo bekommt man dieses Plugin? Und wenn man es hat, wie wird es installiert? Wir demonstrieren das mit Hilfe des Plugins für Apache Axis, das wir in unsere Maven-Installation mit auf- nehmen wollen. Wie mache ich das? Zunächst benötigt man natürlich die Adresse des Internet-Repositorys, in dem man das Plugin findet. Im Falle des Plugins für Apache Axis handelt es sich dabei um das Repository von http://maven-plugins.sourceforge. net/maven/. Allerdings wird dieses Repository alle paar Stunden mit http://www.ibiblio.org/maven/ synchronisiert. Das Repository von Ibiblio ist das Standardrepository von Maven. Maven benutzt es eigentlich im- mer, sofern Sie nicht ausdrücklich ein anderes Repository konfigurieren. Wenn Sie trotzdem das SourceForge-Repository direkt verwenden wol- len, dann können Sie dies in Ihrer Datei build.properties tun. (Soll die Einstellung auch für andere Teammitglieder gelten, dann verwenden Sie dagegen project.properties.) Dazu setzen Sie die folgende Property: 44 Kapitel 2: Anpassung von Maven an eigene Wünsche
maven.repo.remote=http://www.ibiblio.org,http://maven-plugins.sf.net/maven Wie schon gesagt, ist das aber nicht nötig, da der Inhalt des SourceForge- Repositorys zu Ibiblio synchronisiert wird. Während wir dies schreiben, trägt die aktuelle Version des Axis-Plugins die Nummer 0.7. (Sie können unter http://www.ibiblio.org/maven/maven-plugins/plugins/ prüfen, ob das immer noch der Fall ist.) Die Installation des Axis-Plugins erledigt das Ziel plugin:download eines anderen Plugins namens Plugin für Sie. Wie Sie gleich noch sehen werden, müssen darüber hinaus lediglich einige Properties gesetzt werden. Ganz analog zur Definition der groupId, der artifactId und der version bei der Spezifikation einer Abhängigkeit in project.xml benötigen Sie auch dieselben Properties bei der Installation eines Plugins. Das Plugin namens Plugin leitet daraus die exakte URL ab, die zum Download des neuen Plugins erforderlich ist. Das folgende Kommando installiert daher Version 0.7 des Axis-Plugins: C:\>maven plugin:download -DgroupId=maven-plugins ^ More? -DartifactId=maven-axis-plugin -Dversion=0.7 __ __ | \/ |__ _Apache__ ___ | |\/| / _` \ V / -_) ' \ ~ intelligent projects ~ |_| |_\__,_|\_/\___|_||_| v. 1.0.2 build:start: plugin:download-artifact: [echo] repo is 'http://www.ibiblio.org/maven' [echo] trying to download http://www.ibiblio.org/maven/maven-plugins/ plugins/maven-axis-plugin-0.7.jar 11K downloaded plugin:download: [copy] Copying 1 file to C:\apps\maven-1.0.2\plugins BUILD SUCCESSFUL Total time: 2 seconds Sie fragen sich möglicherweise nach dem Zusammenhang zwischen groupId, artifactId und version einerseits und der URL des Plugins an- dererseits. In Abbildung 2-1 sehen Sie, wie diese Abbildung im Falle des Axis-Plugins funktioniert. Abbildung 2-1: Konvention für die URL eines Plugins in einem Internet-Repository Installation eines Plugins aus einem Internet-Repository 45
TIPP Die vollständige zum Download erforderliche URL eines Plugins lautet: [repository URL]/[groupId]/plugins/[artifactId]-[version].jar Dies ist die allgemeine »Formel«, die das Plugin namens Plugin be- nutzt. Übrigens kennt das Ziel plugin:download auch einen interaktiven Modus. Dieser wird verwendet, wenn Sie das Ziel ohne die nötigen Optionen aufrufen: C:\>maven plugin:download __ __ | \/ |__ _Apache__ ___ | |\/| / _` \ V / -_) ' \ ~ intelligent projects ~ |_| |_\__,_|\_/\___|_||_| v. 1.0.2 What is the artifactId of the plugin to download (e.g. maven-axis-plugin)? maven-axis-plugin What is the groupId of the plugin to download? [maven] maven-plugins What is the version of the plugin to download? 0.7 In Maven 2 wer- build:start: den Plugins bei plugin:download-artifact: Bedarf automa- [echo] repo is 'http://www.ibiblio.org/maven' tisch geladen und [echo] trying to download http://www.ibiblio.org/maven/maven-plugins/ plugins/maven-axis-plugin-0.7.jar installiert, so- 11K downloaded bald ein Plugin zum ersten Mal plugin:download: benutzt wird. [copy] Copying 1 file to C:\apps\maven-1.0.2\plugins BUILD SUCCESSFUL Total time: 33 seconds Um die erfolgreiche Installation des Plugins zu kontrollieren, lassen Sie es am besten seine eigenen Ziele ausgeben. Dies geschieht durch den Auf- ruf von maven -P axis. Sie sollten eine Liste aller Ziele des Axis-Plugins sehen. Wenn Sie wissen wollen, welche Version des Plugins installiert ist (wir verwenden in dieser Übung die Version 0.7.), dann geben Sie maven -i ein: C:\>maven -i [...] maven-aspectj-plugin-3.2 maven-aspectwerkz-plugin-1.2 46 Kapitel 2: Anpassung von Maven an eigene Wünsche
maven-axis-plugin-0.7 maven-caller-plugin-1.1 maven-castor-plugin-1.2 [...] Das war’s auch schon! Das Axis-Plugin ist installiert und steht zur An- wendung bereit. Und dazu mussten Sie nur das Ziel plugin:download aufrufen. Und was ist mit … … anderen Internet-Repositories von Maven? Während wir dies schreiben, gibt es schon eine ganze Reihe bekannter und öffentlich zugänglicher Maven-Repositories, die allerdings alle mit dem Haupt-Repository auf Ibiblio synchronisiert werden: • Das Apache-Repository • Das Maven-Plugins-Repository auf SourceForge • Das Codehaus-Repository • Und verschiedene andere, zum Beispiel OSJava, OpenSymphony oder MortBay) Wenn Sie das Standard-Repository von Ibiblio benutzen, gibt es also kei- nen Grund, diese Repositories in Ihre eigene Liste mit aufzunehmen, da sie alle durch Ibiblio abgedeckt werden. Benutzerspezifische Anpassung eines Plugins In dieser Übung arbeiten wir mit einem Webservice, der von der NOAA (National Oceanic and Atmospheric Administration), einer Behörde der US- Regierung, bereitgestellt wird. Die US-Regierung hat kürzlich beschlos- sen, kostenlose Wettervorhersagen bereitzustellen. Diese Aufgabe erle- digt nun der unter http://weather.gov/xml/ zugängliche Server. Wir wol- len das Axis-Plugin von Maven benutzen, um Klassen zu generieren, mit denen wir anschließend eine Vorhersage von diesem Webservice abru- fen. Dazu werden wir das Axis-Plugin in einem gewissen Rahmen konfi- gurieren müssen. Wie mache ich das? Wenn Sie das Axis-Plugin erfolgreich installiert haben, dann erhalten Sie mit maven -P axis eine Liste aller Ziele, die dieses Plugin anbietet. Unter anderem sollte darin axis:wsdl2java enthalten sein. Wir wollen dieses Benutzerspezifische Anpassung eines Plugins 47
Ziel benutzen, um eine Client-Bibliothek anhand der Web Service De- scription Language (WSDL) des Wettervorhersagedienstes zu generieren. Die WSDL des Vorhersagedienstes der NOAA finden Sie unter http:// weather.gov/forecasts/xml/DWMLgen/wsdl/ndfdXML.wsdl. Ein WSDL- Dokument ist eine XML-Datei, die eine Beschreibung aller per SOAP angebotenen Methoden enthält. Das Axis-Plugin soll dieses XML-Doku- ment benutzen, um eine passende Client-Bibliothek zu generieren. Für diese Übung wollen wir festlegen, dass die WSDL in weather/src/wsdl/ weather.wsdl gespeichert wird. Das Axis-Plugin soll Java-Quelltexte für alle in diesem Verzeichnis liegenden WSDL-Dateien generieren. Um die vom Axis-Plugin generierten Quelltexte nutzen zu können, müs- sen wir die folgenden Abhängigkeiten in unseren Projektdeskriptor auf- nehmen: commons-discovery commons-discovery 20030211.213356 commons-logging commons-logging 1.0.4 axis axis 1.2-RC3 axis axis-jaxrpc 1.2-RC3 axis axis-saaj 1.2-RC3 axis axis-wsdl4j 1.2-RC3 Um die Client-Bibliothek zu generieren, müssen wir das Axis-Plugin leicht umkonfigurieren, da es standardmäßig Java-Quelltexte für die Serverseite generiert. Die Konfiguration geschieht durch das Überschreiben von Plug- in-Properties in der Datei project.properties. Um eine Liste solcher Proper- ties und ihrer Standardwerte zu suchen, haben wir zwei Möglichkeiten: 48 Kapitel 2: Anpassung von Maven an eigene Wünsche
Zunächst einmal können wir einen Blick auf die Website des Projekts werfen. Zum anderen bietet sich ein Blick in unseren lokalen Plugin- Cache an. In unserem Fall heißt das, dass wir die Datei ~/.maven/cache/ maven-axis-plugin-0.7/plugin.properties öffnen. Sie sollte in etwa die fol- genden Werte enthalten: maven.axis.dir=${maven.build.dir}/axis maven.axis.generated.dir=${maven.axis.dir}/src maven.axis.test.dir=${maven.axis.dir}/test maven.axis.url=${maven.src.dir}/wsdl maven.axis.all=true maven.axis.deployscope=session maven.axis.factory=org.apache.axis.wsdl.toJava.JavaGeneratorFactory maven.axis.helpergen=false maven.axis.serverside=true maven.axis.skeletondeploy=true maven.axis.noimports=no maven.axis.verbose=yes maven.axis.debug=false maven.axis.typemappingversion=1.1 maven.axis.timeout=45000 Das sind also die Standardwerte der Properties des Axis-Plugins. Wir bemerken vor allem, dass die Property maven.axis.serverside den Wert true enthält. Da wir Client-Bibliotheken generieren wollen, müssen wir diese Property für unser Projekt auf false setzen. Darüber hinaus wer- den Sie bemerken, dass der Wert von maven.axis.timeout auf 45.000 Millisekunden steht. In unserem Projekt wollen wir das auf 20 Sekunden reduzieren. Eine besser dokumentierte Liste der Properties des Axis-Plug- ins finden Sie übrigens auf der zugehörigen Website unter http://maven- plugins.sourceforge.net/maven-axis-plugin/properties.html. Zusammen- fassend nehmen wir also zur Konfiguration des Plugins die beiden fol- genden Properties in weather/project.properties auf: # Anpassung des Maven XDoc-Plugins maven.xdoc.date = left maven.xdoc.date.format = MM/dd/yyyy # Anpassung des Maven Axis-Plugins maven.axis.serverside = false maven.axis.timeout = 20000 # Anpassung des Maven Test-Plugins maven.test.skip = false maven.test.fork = yes Ein Aufruf des Ziels axis:wsdl2java generiert also eine Client-Bibliothek mit einem Timeout von 20 Sekunden. Vielleicht ist Ihnen aufgefallen, dass in project.properties auch zwei andere Plugins konfiguriert werden, nämlich Test und XDoc. Mit der Konfiguration des XDoc-Plugins werden wir uns noch weiter unten in diesem Kapitel beschäftigen. Benutzerspezifische Anpassung eines Plugins 49
Mit maven axis:wsdl2java können wir nun die Client-Bibliothek für den SOAP-Service der Wettervorhersage generieren. Die generierten Quell- texte werden in maven.axis.generate.dir gespeichert. Wenn Sie die Unit-Tests des Beispielprojekts aufrufen, dann sollten Sie feststellen, dass das Projekt auch einen Unit-Test enthält, der die Wettervorhersage der NOAA tatsächlich abruft und damit die Funktion der Client-Bibliotheken überprüft. Erstellung eigener Ziele Um eine Client-Bibliothek für den SOAP-Service zu generieren, benötigt man zunächst die WSDL-Datei, die man an wsdl2java übergeben will. Wir wollen nun ein eigenes Ziel namens weather:get-wsdl definieren, das den Download dieser Datei vom Server der NOAA automatisiert. Wie mache ich das? Die Definition unseres eigenen Ziels geschieht als Jelly-Skript in der Da- tei weather/maven.xml. Das ist nicht weiter schwer, wir benutzen intern den get-Task von Ant, der die WSDL-Datei für uns abholen soll. Das neue Ziel sieht damit so aus: Für Ihr eigenes Projekt empfiehlt der WSDL-Datei in project.proper- ren. Das erleich- Retrieving WSDL from ${wsdl} tert die Der Wert der Variablen ${wsdl} wird mit j:set gesetzt, eine Mitteilung wird auf der Konsole ausgegeben, und das WSDL-Dokument wird gela- den und in weather/src/wsdl abgelegt. Die Ausgabe der Mitteilung wird mit Hilfe von Ants echo-Task implementiert. Geben Sie einmal maven weather:get-wsdl auf der Kommandozeile ein, dann sollten Sie die fol- gende Ausgabe sehen: C:\dev\mavenbook\code\weather>maven weather:get-wsdl __ __ | \/ |__ _Apache__ ___ | |\/| / _` \ V / -_) ' \ ~ intelligent projects ~ |_| |_\__,_|\_/\___|_||_| v. 1.0.2 50 Kapitel 2: Anpassung von Maven an eigene Wünsche
build:start: weather:get-wsdl: [echo] Retrieving WSDL from http://weather.gov/forecasts/xml/DWMLgen/ wsdl/ndfdXML.wsdl [get] Getting: http://weather.gov/forecasts/xml/DWMLgen/wsdl/ndfdXML. wsdl BUILD SUCCESSFUL Total time: 2 seconds Was ist da gerade geschehen? Das Tag j:set setzt eine Property namens wsdl. Der Wert der Property ist die URL der aus dem Internet zu ladenden WSDL-Datei. Sobald die Vari- able gesetzt ist, steht sie dem Jelly-Skript zur Verfügung und kann mit ${wsdl} referenziert werden. Das Tag set ist ein Bestandteil der Stan- dardtagbibliothek von Jelly. Diese Standardbibliothek enthält zum Bei- spiel auch Tags zur Ausführung bedingten Codes oder zur Iteration über eine Folge. In diesem Kapitel werden Sie noch einige dieser Tags ken- nen lernen, zum Beispiel j:if oder j:forEach. Ausführlichere Informa- tionen über die Standardtags von Jelly finden Sie unter http://jakarta. apache.org/commons/jelly/tags.html. In maven.xml werden XML-Namensräume benutzt, um die vom jewei- ligen Jelly-Skript verwendeten Tagbibliotheken zu erkennen. Im obigen Beispiel wird das Präfix ant auf den Namensraum jelly:ant abgebildet. Der Namensraum jelly:ant ist wiederum mit Jellys Tag-Library zum Zugriff auf Ant verbunden. Mit dieser Tag-Library kann man aus Jelly heraus Ant-Tasks benutzen. In diesem Fall haben wir zum Beispiel den echo-Task von Ant genauso verwendet, wie wir das auch in einem build. xml von Ant gemacht hätten: Print out some important message! Der wesentliche Punkt an dieser Stelle ist, dass das Element, das den Ant-Task anspricht, im Namensraum jelly:ant liegt. Mit Namensräumen umzugehen ist etwas gewöhnungsbedürftig, aber der wesentliche Punkt ist eben, dass Ihnen in einem eigenen Ziel von Maven alle Möglichkei- ten zur Verfügung stehen, die Sie auch in einem Ant-Buildskript haben. Insbesondere können Sie natürlich alle anderen Ant-Tasks einsetzen, mit denen Sie sich auskennen. Betrachten Sie dazu das folgende Beispiel aus einer anderen maven.xml-Datei: Erstellung eigener Ziele 51
Wenn man in einem Jelly-Skript beliebige Ant-Tasks einsetzen kann, dann stellt sich natürlich die Frage nach einer Liste aller Tasks, die in Ants build.xml erlaubt sind. Eine vollständige Liste entnehmen Sie am besten dem Ant-Manual, das Sie online unter http://ant.apache.org/ manual/index.html finden. Übrigens verwendet Jelly den Namensraum jelly:ant sogar als Standardnamensraum. Statt ant:copy oder ant: include können Sie also einfach copy oder include schreiben, wenn Sie das angenehmer finden. Wir raten Ihnen davon aber eher ab: Langfristig ist es besser, das Präfix ant zu verwenden, auch wenn man dadurch ein paar Tastendrucke spart. Die Benutzung von Ant ist nichts Besonderes und nur eine der Möglichkeiten von Jelly. Die Verwendung des Ant- Namensraums als Vorgabe ist daher reichlich willkürlich und wird mög- licherweise in zukünftigen Maven-Versionen entfallen. Benutzen Sie also lieber das Präfix ant in Jelly-Skripten. Und was ist mit … … der Behauptung, Maven sei ein Ersatz für Ant? Das ist so nicht ganz richtig. Maven ist kein »Ersatz« für Ant, auch wenn Maven auf dem Erfolg von Systemen wie Ant aufbaut. Ant ermöglicht ein XML-basierendes Build-Skript, aber Maven ist ein komplettes Buildsys- tem. Aber viele Plugins von Maven arbeiten intern mit Ant-Tasks. In die- sem Sinne sollte man also eher davon sprechen, dass Maven 1 Ant integriert. Definition eines preGoal Wir möchten als Nächstes den generierten SOAP-Client in unser Projekt einbinden. Das geht am besten mit Mavens Axis-Plugin. Wenn das Axis- Plugin Quelltexte generiert, dann muss sichergestellt werden, dass die generierten Quelltexte mit kompiliert werden. Das wird mit Hilfe eines preGoal und eines postGoal des Ziels java:compile realisiert. Wie mache ich das? Das Axis-Plugin generiert Quelltexte in das Verzeichnis maven.axis. generated.dir, das auf target/axis/src voreingestellt ist. Im Normalfall ist es nicht erwünscht, die generierten Quelltexte in das Verzeichnis src/ 52 Kapitel 2: Anpassung von Maven an eigene Wünsche
main/java mit den manuell erstellten Quelltexten zu kopieren. Anderer- In Maven 2 gibt seits müssen die kompilierten Klassen natürlich in das Artefakt des es preGoal und Projekts übernommen werden. Aus diesem Grund muss das Ziel axis: postGoal nicht compile vor dem Ziel java:compile aufgerufen werden: Die Aufgabe von mehr. Stattdes- axis:compile ist es, dafür zu sorgen, dass die von axis:wsdl2java sen wird der erzeugten Dateien mit kompiliert werden. Die folgende Datei maven.xml Buildprozess als benutzt ein preGoal, das ein anderes Ziel vor java:compile aufruft: eine Serie von Phasen wie build, compile und test
[axis-wsdl2java] WSDL2Java C:\dev\mavenbook\code\weather\src\wsdl\ weather.wsdl Parsing XML file: C:\dev\mavenbook\code\weather\src\wsdl\weather.wsdl Generating C:\...\gov\weather\forecasts\xml\DWMLgen\schema\ndfdXML_xsd\ FormatType.java Generating C:\...\gov\weather\forecasts\xml\DWMLgen\schema\ndfdXML_xsd\ ProductType.java Generating C:\...\gov\weather\forecasts\xml\DWMLgen\schema\ndfdXML_xsd\ WeatherParametersType.java Generating C:\...\gov\weather\forecasts\xml\DWMLgen\wsdl\ndfdXML_wsdl\ NdfdXMLPortType.java Generating C:\...\gov\weather\forecasts\xml\DWMLgen\wsdl\ndfdXML_wsdl\ NdfdXMLBindingStub.java Generating C:\...\gov\weather\forecasts\xml\DWMLgen\wsdl\ndfdXML_wsdl\ NdfdXML.java Generating C:\...\gov\weather\forecasts\xml\DWMLgen\wsdl\ndfdXML_wsdl\ NdfdXMLLocator.java Generating C:\...\gov\weather\forecasts\xml\DWMLgen\wsdl\ndfdXML_wsdl\ NdfdXMLTestCase.java move the generated testcases to folder c:\dev\mavenbook\code\weather/target/ axis/test [move] Moving 1 files to C:\dev\mavenbook\code\weather\target\axis\test axis:copy: Der Name axis: [copy] Copying 7 files to C:\dev\mavenbook\code\weather\target\axis\ compile ist irre- build adding c:\dev\mavenbook\code\weather/target/axis/src to the maven.compile. führend, wie man src.set an der Ausgabe erkennt. Das Ziel axis:compile: [echo] Compiling to c:\dev\mavenbook\code\weather/target/classes ruft keineswegs den Java-Compi- java:compile: ler auf, sondern [javac] Compiling 8 source files to C:\dev\mavenbook\code\weather\ target\classes erweitert ledig- Note: Some input files use unchecked or unsafe operations. lich den Such- Note: Recompile with -Xlint:unchecked for details. pfad für Quell- BUILD SUCCESSFUL textdateien um Total time: 7 seconds das Verzeichnis Wird java:compile aufgerufen, dann ruft Maven automatisch zunächst target/axis/src. axis:compile auf. Dieses Ziel hängt seinerseits von denjenigen Zielen des Axis-Plugins ab, die die WSDL-Dokumente in src/wsdl übersetzen. Die ge- nerierten Quelltexte werden automatisch in den Suchpfad für Quelltexte eingebunden. Prinzipiell könnten wir auch die generierten Quelltexte ins Versionskontrollsystem übernehmen. Das wäre aber redundant, denn die WSDL, das heißt die Vorlage dieser Dateien, ist ja bereits im Versionskont- rollsystem. Indem wir axis:compile als preGoal von java:compile ins Spiel bringen, lassen wir auch diese Klassen kompilieren, ohne sie zu- nächst nach src/main/java kopieren zu müssen. 54 Kapitel 2: Anpassung von Maven an eigene Wünsche
Was ist gerade geschehen? Die Syntax eines postGoal ist die Mit Axis WSDL2Java werden Klassen generiert und im Verzeichnis selbe wie die ei- target/axis/src gespeichert. Da wir diese Klassen keinesfalls modifizieren nes preGoal. In wollen, haben wir ein preGoal von java:compile definiert, das axis: diesem Fall wird compile aufruft. axis:compile fügt maven.axis.generated.dir in die Pro- ein Jelly-Skript perty maven.compile.src.set ein. Dadurch werden die generierten Klas- definiert, das sen mit kompiliert, wenn java:compile aufgerufen wird. Mit anderen ausgeführt wird, Worten: axis:compile informiert Maven, dass das Verzeichnis target/ nachdem das im axis/src Java-Quelltexte enthält, die kompiliert und in das Artefakt einge- name-Attribut bunden werden müssen. angegebene Ziel Schauen wir uns nochmals an, was das Ziel axis:compile genau tut. Dazu ausgeführt wurde. werfen wir einen Blick in die zum Axis-Plugin gehörende Datei plugin. jelly, die wir in ~/.maven/cache/maven-axis-plugin-0.7/plugin.jelly fin- den: Verzeichnis ${maven.axis.generated.dir} wird in maven.compile.src.set eingefügt Die wesentliche Zeile haben wir hervorgehoben: Ein Pfad axis.src.set wird erzeugt und zu maven.compile.src.set hinzugefügt. Das hat zur Folge, dass die generierten Axis-Klassen von java:compile mit kompi- liert werden. Definition eigener Properties Das Axis-Plugin generiert unter anderem einen Unit-Test für den Web- service, den die WSDL beschreibt. Allerdings muss dieser Unit-Test ein wenig an die lokalen Gegebenheiten angepasst werden. Zum Beispiel erwartet der SOAP-Service für die Wettervorhersage als Parameter einen Längen- und Breitengrad. Die vom generierten Unit-Test verwendeten Werte (0,0) sind aber für unsere Zwecke ungeeignet, weil der Wettervor- hersagedienst weder den Äquator noch die Länge von Greenwitch ak- Definition eigener Properties 55
zeptiert. Wir benötigen ein preGoal und ein postGoal für das Ziel axis: wsdl2java, das den Unit-Test in unser Verzeichnis src/test/java kopiert und von axis:compile ausschließt. Dieser Unit-Test soll nicht bei jedem Aufruf von axis:wsdl2java überschrieben werden. Dazu benötigen wir eine eigene Property namens generate.tests. Wie mache ich das? Zunächst definieren Sie bitte die Property generate.tests in Ihrem pro- ject.properties. Die Property soll in Ihrem preGoal und in Ihrem postGoal ausgelesen werden. Fügen Sie bitte die folgenden Zeilen in project.pro- perties ein: # Eigene Properties generate.tests = false Als Nächstes modifizieren Sie das preGoal und postGoal in maven.xml. Beide sollen die neue Property benutzen, um den Unit-Test nur dann zu überschreiben, wenn generate.tests den Wert true enthält: Wenn Sie maven axis:wsdl2java aufrufen, dann liest Maven die Proper- ties aus project.properties. Der Standardwert der Property generate. tests ist dort als false definiert. Dementsprechend soll axis:wsdl2java im Normalfall die Unit-Tests in ${pom.build.unitTestSource} nicht über- schreiben. Soll das ausnahmsweise aber doch geschehen, dann rufen wir maven axis:wsdl2java -Dgenerate.tests=true auf. In diesem Fall sollten wir die folgende Ausgabe sehen: axis:wsdl2java: [copy] Copying 1 file to C:\dev\mavenbook\code\weather\src\test [delete] Deleting directory C:\dev\mavenbook\code\weather\target\axis\ test\gov 56 Kapitel 2: Anpassung von Maven an eigene Wünsche
Was ist gerade geschehen? In Maven 2 gibt es sowohl maven. Man bezeichnet diese Vorgehensweise als passive oder einmalige Code- xml als auch generierung. Zwar müssen die aus der WSDL generierten Quelltexte im project.properties Allgemeinen nicht modifiziert werden, im Unit-Test müssen aber die nicht mehr. Die Parameter für Längen- und Breitengrad angepasst werden. Wenn der Konfiguration des Unit-Test generiert werden soll, dann wird die Property generate.tests Projekts erfolgt auf true gesetzt. Ein preGoal von axis:wsdl2java überschreibt Ihren komplett durch Unit-Test in src/test genau dann, wenn generate.tests auf true steht. das Project Ob- Darüber hinaus gibt es ein postGoal von axis:wsdl2java, das den gene- ject Model (POM) rierten Unit-Test in jedem Fall löscht. in der Datei pom. In dieser Übung haben wir eine Variable in project.properties definiert. Die xml. Variable namens generate.tests dient der Spezifikation eines Standard- verhaltens, das durch Überschreiben der Variablen auf der Kommando- zeile angepasst werden kann. Als Sie maven axis:wsdl2java -Dgenerate. tests=true aufgerufen haben, haben Sie damit einen Wert für generate. tests definiert, der den aus project.properties überschreibt. Mit Hilfe von j:if wird der Wert dieser Variablen in maven.xml geprüft: Tests werden generiert. In diesem Beispiel wird durch einen Aufruf von context.getVariable( ) auf den Wert von generate.tests zugegriffen. Die Variable context hat den Typ JellyContext und bietet Zugriff auf die von Maven definierten Variablen des Projekts. Die Variable generate.tests wird mit der String- konstanten true verglichen. Wenn generate.tests den Wert true ent- hält, dann wird das Tag ant:echo ausgeführt. HINWEIS Wenn generate.tests den Wert true enthält, dann würden Sie vielleicht versuchen, mit dem folgenden Codefragment die Referenz auf ${generate.tests} auszuwerten, um gegebenenfalls die Aus- führung von ant:echo auszulösen: Die Property generate.tests enthält den Wert true. Tatsächlich würde dieses Jelly-Skript das Tag ant:echo ausführen. Der Grund ist aber ein ganz anderer, als man zunächst vermuten würde. Die Kurzform ${generate.tests} wird zu true evaluiert, wenn eine Property generate.tests im Jelly-Kontext definiert und nicht null ist. Der Punkt im obigen Jelly-Ausdruck kann zweierlei Definition eigener Properties 57
Bedeutungen haben. Falls es eine Variable im Jelly-Kontext gibt, die den Namen generate.tests trägt, dann wird diese Variable zurück- gegeben. Falls es keine solche Variable gibt, dann wird Jelly den Punkt als Methodenaufruf einer Property interpretieren. Mit anderen Worten: ${generate.tests} wird als ${generate.getTests( )} interpretiert, was dem Wert null entspricht, da das Objekt gene- rate nicht existiert. Im Endeffekt würde ant:echo auch dann ausgeführt, wenn generate.tests den String false enthielte, da ${generate.tests} als true interpretiert wird, wenn der Inhalt der Variablen nicht null ist. Aus diesem Grund sollten Sie eine Variable stets mit Hilfe der Methode context.getVariable( ) auswerten. Die generierten Unit-Tests verwenden als Längen- und Breitengrad je- weils den Wert 0, weshalb sie mit einer Fehlermeldung scheitern. Wenn Sie axis:wsdl2java aufrufen und dabei versehentlich Ihr korrigiertes Exemplar von NdfdXMLTestCase.java überschrieben haben, dann müs- sen Sie anschließend Ihr Original aus dem Versionskontrollsystem wie- derherstellen oder das Beispiel erneut korrigieren. In dieser Übung wird die Variable ${pom} referenziert. ${pom} bietet unter anderem den Zugriff auf alle in project.xml definierten Informationen. Wenn Jelly einen Ausdruck wie diesen findet, dann überprüft es zu- nächst, ob es einen zum Ausdruck passenden Property-Namen gibt. Wenn es keine solche Property im Jelly-Kontext gibt, dann wertet Jelly den Aus- druck als eine Folge von Property-Accessormethoden aus. Zum Beispiel wird ${pom.build.sourceDirectory} als ${pom.getBuild( ).getSource Directory( )} interpretiert. Hier sehen Sie ein anderes Ziel, das den Zu- griff auf einige andere Informationen über ${pom} demonstriert: Projektname: ${pom.name} Beschreibung: ${pom.description} Quelltextverzeichnis: ${pom.build.sourceDirectory} Verzeichnis mit Unit-Tests: ${pom.build.unitTestSourceDirectory} Dieses Ziel gibt einfach den Namen und die Beschreibung des Projekts sowie die Verzeichnisse mit den Quelltexten und den Unit-Tests aus. Die Verzeichnisnamen erhält man durch Abfragen des org.apache.maven. project.Build-Objekts, das als getBuild( ) über org.apache.maven.pro- ject.Project zugänglich ist. So sieht die zugehörige Ausgabe aus: build:start: pom-example: [echo] Projektname: Test Application [echo] Beschreibung: An example project 58 Kapitel 2: Anpassung von Maven an eigene Wünsche
[echo] Quelltextverzeichnis: C:\dev\mavenbook\code\genapp\test- application\src\java [echo] Verzeichnis mit Unit-Tests: C:\dev\mavenbook\code\genapp\test- application\src\test BUILD SUCCESSFUL Total time: 1 seconds Eine vollständige Liste aller über ${pom} zugänglichen Variablen ent- nimmt man am besten den JavaDocs der Project-Klasse, die man unter http://maven.apache.org/apidocs/org/apache/maven/project/Project.html findet. Ganz analog findet man eine Liste der Properties der Dependency- und Build-Objekte unter http://maven.apache.org/apidocs/org/apache/ maven/project/Dependency.html bzw. http://maven.apache.org/apidocs/ org/apache/maven/project/Build.html. Ganz nebenbei haben Sie übrigens mit dem Tag maven:get eine Pro- perty des Axis-Plugins abgerufen. Der Zugriff auf Plugin-Properties sollte stets über maven:get geschehen und nicht zum Beispiel über ${maven. axis.test.dir}. Wenn ein Plugin noch nicht initialisiert ist, dann führt die Referenz auf maven.axis.generated.dir zu einem Fehler. Wenn man die Property dagegen mit maven:get referenziert, dann initialisiert Maven bei Bedarf das Plugin, bevor der Zugriff erfolgt. Ganz analog kann man auch eine Plugin-Property mit maven:set definieren. Zwei Beispiele mit maven:get bzw. maven:set sollen dies illustrieren: Das erste Beispiel liest mit maven:get die Property maven.axis.generated.dir aus dem Axis- Plugin. Das zweite Beispiel modifiziert diesen Wert: Bevor man die Maven-Tags benutzt, muss allerdings erst das Namens- raumpräfix maven an den Namensraum jelly:maven gebunden werden. Details zu Jellys Tag-Library Maven finden Sie unter http://maven.apache. org/reference/maven-jelly-tags/tags.html. Kapitel 6 enthält noch weitere Details über Plugins. Und was ist mit … ... den eingebauten Variablen wie ${basedir} und ${pom}? Gibt es dazu eine Liste? Ja, die gibt es. Einige besonders häufige Maven-Properties finden Sie in Tabelle 2-1. Alle diese Properties stehen für die Definition eigener Ziele in maven.xml zur Verfügung. Die obigen Beispiele eines postGoal und eines preGoal referenzieren zum Beispiel die Variable ${pom.build. Definition eigener Properties 59
sourceDirectory}, um das Verzeichnis mit den Java-Quelltexten zu le- sen. Die Variable ${pom} liefert darüber hinaus bei Bedarf alle anderen Informationen aus dem POM. Ein anderes wichtiges Beispiel einer einge- bauten Property ist ${basedir}, das Wurzelverzeichnis des Projekts. Tabelle 2-1: Eine Auswahl von Maven zur Verfügung gestellter Properties Eingebaute Property Beschreibung ${basedir} Wurzelverzeichnis des Projekts; das Verzeichnis, in dem project.xml und maven.xml liegen. ${maven.build.dir} Das Verzeichnis für temporäre Dateien und generierte Artefakte; normalerweise ${basedir}/target. ${maven.build.dest} Das Verzeichnis für kompilierte Klassen; normalerweise ${basedir}/classes. ${user.home} Das Home-Directory des Benutzers. Unter Unix ist dies üblicherweise /home/tobrien oder dergleichen, unter Windows dagegen C:\Documents and Settings\tobrien. ${maven.home.local} Das Verzeichnis ${user.home}/.maven. ${maven.repo.remote} Das Internet-Repository, aus dem Maven bei Bedarf Arte- fakte nachlädt. Standardmäßig ist dies http://www.ibiblio. org/maven/. Die Property darf eine durch Kommata getrennte Liste von Repositories enthalten. Wenn ein Artefakt im ersten angegebenen Repository nicht gefun- den wird, dann werden der Reihe nach die anderen ver- sucht, bis das Artefakt entweder gefunden wird oder die Liste zu Ende ist. ${maven.repo.local} Das lokale Repository, meist ${maven.home.local}/ repository. ${context} Diese Variable ist in allen Jelly-Skripten automatisch defi- niert und enthält ein Objekt vom Typ JellyContext. Die- ses Objekt bietet Zugriff auf alle Variablen, die dem Jelly- Skript zur Verfügung stehen. Nähere Informationen zu diesem Objekt finden Sie unter http://jakarta.apache.org/ commons/jelly/apidocs. ${pom} Enthält ein Objekt des Typs org.apache.maven.project. Project mit Informationen über das aktuelle Projekt. Diese Variable bietet Ihnen den Zugriff auf die Pfade des Projekts oder der verwendeten Abhängigkeiten. Alle System-Properties Die Klasse System stellt eine Reihe von Properties zur Ver- fügung, die automatisch übernommen werden. Dazu gehören Properties wie java.home, os.arch oder file. separator sowie alle anderen von System definierten Pro- perties. Eine vollständige Liste der von Maven bereitgestellten Properties finden Sie unter http://maven.apache.org/reference/properties.html. In Kapitel 6 gehen wir detailliert darauf ein, wie ein Maven-Plugin auf diese Proper- ties zugreifen bzw. eigene Properties definieren kann. 60 Kapitel 2: Anpassung von Maven an eigene Wünsche
Start des Programms aus einem eigenen Ziel Die Client-Bibliothek ist erzeugt, und damit wird es Zeit, mit Maven die Klasse mdn.weather.Weather aufzurufen, um die Wettervorhersage für Chi- cago, Illinois, zu bekommen. Wie mache ich das? Definieren Sie ein neues Ziel in maven.xml, das den java-Task von Ant benutzt, um die Klasse mdn.weather.Weather zu starten: Die Klasse Weather akzeptiert drei Argumente: Breitengrad, Längengrad und die Anzahl der Tage, für die eine Vorhersage zu erstellen ist. In die- sem Ziel haben wir die Koordinaten von Chicago angegeben und die Vorhersage auf einen einzigen Tag beschränkt. Wenn wir nun mit maven weather:run unser neues Ziel aufrufen, dann erhalten wir die Antwort in Form eines XML-Dokuments mit der gewünschten Wettervorhersage: // Start des Programms aus einem eigenen Ziel 61
point1 Daily Maximum Temperature 53 Daily Minimum Temperature 34 12 Hourly Probability of Precipitation 30 8 Wir können also mit 53° rechnen1 und müssen mit einer Wahrscheinlich- keit von 30% Regen befürchten. Nun ja, letzte Woche war’s schlechter! Was ist gerade geschehen? Sie haben Ants java-Task benutzt, um die Klasse Weather zu starten. Dabei wurden drei Argumente mit Hilfe von ant:arg übergeben. Der Klas- senpfad wurde durch einen Aufruf der Methode getDependencyPath( ) des Objekts ${pom} gebildet. ${pom.getDependencyPath('axis:axis-saaj')} liefert zum Beispiel den absoluten Pfad der Abhängigkeit mit groupId axis und artifactId axis-saaj. Natürlich muss eine Abhängigkeit in project. xml definiert sein, um in dieser Art und Weise referenziert werden zu kön- nen. Das Ziel weather:run ruft zunächst ein anderes Ziel (jar) auf, da das prereqs-Attribut des Elements goal den Wert jar enthält. Wenn weather: run von mehr als einem Ziel abhängen würde, dann könnten diese Ziele durch Kommata getrennt in demselben Attribut angegeben werden. Weil weather:run vom Ziel jar abhängt, wird dieses Ziel vor jedem Aufruf von weather:run ausgeführt. Insbesondere werden auch die Unit-Tests aus- 1 Gemeint sind 53° Fahrenheit, also ca. 12° Celsius. (Anm.d.Übers.) 62 Kapitel 2: Anpassung von Maven an eigene Wünsche
geführt. Sie können die Unit-Tests auslassen, indem Sie -Dmaven.test. skip=true als zusätzliches Argument auf der Kommandozeile angeben. Die folgende Kommandozeile ruft also die Weather-Klasse auf, ohne zuvor die Unit-Tests auszuführen: maven weather:run -Dmaven.test.skip=true Die Verwendung von ant:java zum Start einer Java-Anwendung ist nicht die einzige Möglichkeit. Es gibt bessere Vorgehensweisen, als ein eige- nes Ziel in einem Maven-Projekt zu formulieren. In Kapitel 6 werden Sie unter anderem ein einfaches Plugin schreiben, das eine JAR-Datei star- tet. Einrichtung eines Standardziels Wenn Sie das Ziel weather:run häufiger von der Kommandozeile aufru- fen, dann kommt vielleicht irgendwann der Wunsch auf, dieses Ziel als Standardziel Ihres Maven-Projekts zu verwenden. Das Standardziel ist dasjenige, das aufgerufen wird, wenn Sie maven von der Kommandozeile ohne weitere Argumente starten. In diesem Fall würde also das Ziel weather:run ausgeführt. Wie mache ich das? Das Standardziel wird einfach im default-Attribut des project-Elements angegeben: // …snip… Wenn Sie Maven aufrufen, ohne ein bestimmtes Ziel anzugeben, dann würde Maven also weather:run als Standardziel aufrufen. Niemand hat gesagt, das würde kompliziert werden! Properties überschreiben Sie haben bereits festgestellt, dass die Definition einer Property auf der Kommandozeile eine andere Definition in den project.properties über- schreibt. Darüber hinaus werden Properties von Plugins durch Definitio- nen in den project.properties überschrieben. Nachdem Sie nun den Properties überschreiben 63
prinzipiellen Mechanismus des Überschreibens von Properties kennen, stellt sich die Frage, wo und wie genau man eine projekt- oder benutzer- spezifische Konfiguration vornehmen kann. Wie mache ich das? In der Übung zur »Benutzerspezifischen Anpassung eines Plugins« zu Beginn dieses Kapitels haben wir die Property maven.axis.serverside in der Datei project.properties gesetzt. Rufen Sie nun zum Test das Ziel axis:wsdl2java auf, und setzen Sie dabei die Property maven.axis.ser- verside auf true: maven axis:wsdl2java -Dmaven.axis.serverside=true Sie sollten an dieser Stelle sehen, dass Maven eine Reihe verschiedener Klassen und Deploymentdeskriptoren für einen SOAP-Service von Apa- che Axis generiert. Indem Sie die Property maven.axis.serverside auf der Kommandozeile gesetzt haben, haben Sie damit den Wert aus pro- ject.properties überschrieben. Auf der Kommandozeile gesetzte Proper- ties haben Vorrang vor Properties, die an anderer Stelle in Maven gesetzt werden. Tatsächlich kennt Maven eine ganze Hierarchie von Property-Dateien, die man allesamt zur Anpassung an projekt- oder benutzerspezifische Wünsche benutzen kann. Maven liest Properties der Reihe nach von den folgenden Stellen: ${basedir}/project.properties Diese Datei liegt im selben Verzeichnis wie maven.xml und project. xml. Sie legt das Standardverhalten eines Projekts fest und erlaubt die projektspezifische Anpassung der Standards von Maven. ${basedir}/build.properties Diese Datei liegt ebenfalls im selben Verzeichnis wie maven.xml und project.xml. Ihre Aufgabe ist die Anpassung des Projekts an die Wün- sche eines bestimmten Benutzers. Wenn Sie den Wert einer Property an Ihre persönliche Umgebung anpassen wollen, ohne zugleich die Properties anderer Benutzer zu verändern, dann erzeugen Sie eine Datei build.properties in ${basedir}. Die in dieser Datei festgelegten Werte überschreiben ggf. die in project.properties definierten. Achten Sie allerdings darauf, dass build.properties nicht ins Versionskontroll- system2 übernommen wird: Diese Datei ist ausschließlich zur Anpas- sung des Projekts an die Bedürfnisse eigener Benutzer gedacht. 2 Am einfachsten geht das, wenn Sie den Namen build.xml in Ihr .cvsignore bzw. als Property svn:ignore übernehmen. (Anm.d.Übers.) 64 Kapitel 2: Anpassung von Maven an eigene Wünsche
${user.home}/build.properties Falls Ihr Homedirectory eine Datei build.properties enthält, dann wird diese zur benutzerspezifischen Anpassung aller Projekte benutzt. In diese Datei gehören zum Beispiel die Konfiguration eines Proxyser- vers oder eines speziellen Online-Repositorys. Die in dieser Datei definierten Properties gelten für alle Projekte, und sie überschreiben Werte aus den beiden vorherigen Dateien. System-Properties (mit der Option -D definiert) Sie haben in diesem Kapitel bereits häufig von dieser Möglichkeit Gebrauch gemacht. Die Angabe einer Property auf der Kommando- zeile überschreibt alle Konfigurationsdateien. Solchermaßen definierte Properties sind endgültig. Abbildung 3-3 illustriert die Definition von Properties in mehreren Schich- ten, die Sie in dieser Übung kennen lernen. In Kapitel 3 werden Sie se- hen, dass ein Projekt Properties von einem übergeordneten Projekt erben kann. Sie werden in Kapitel 3 außerdem sehen, dass Unterprojekte auto- matisch alle Properties aus den Dateien project.properties und build. properties des übergeordneten Projekts erben. Was ist gerade geschehen? Die verschiedenen Konfigurationsstufen sind je nach Aufgabe unter- schiedlich gut geeignet. Die Konfiguration eines Proxyservers ist norma- lerweise für alle Ihre Maven-Projekte dieselbe. Aus diesem Grund setzt man die entsprechenden Properties am besten in build.properties im eigenen Homedirectory. Falls Sie dagegen eine Property setzen müssen, die nur für Sie und nur für ein bestimmtes Projekt gelten soll, dann ist ${basedir}/build.properties dafür der richtige Ort. Falls Sie zum Beispiel der Release-Manager eines bestimmten Projekts sind, dann benötigen Sie eine Property maven.username. Diese Property ist benutzer- und pro- jektspezifisch und gehört deshalb in ${basedir}/build.properties. Diese Datei gibt es nur auf Ihrer lokalen Maschine, denn sie wird nicht ins Ver- sionskontrollsystem übernommen. Damit eignet sie sich zur Anpassung eines bestimmten Projekts an Ihre persönlichen Bedürfnisse. Da die Vor- gaben eines Open Source-Projekts wie Maven oft für den Einsatz in einer Firma oder einer ähnlichen Organisation ungeeignet sind, werden Sie feststellen, dass Sie in ${basedir}/build.properties oder ${user.home}/ build.properties häufig dieselben Einstellungen vornehmen. Wenn Sie die Properties eines Projekts so konfigurieren wollen, dass diese auch für die anderen Entwickler gelten, dann gehören diese Einstellun- gen in ${basedir}/project.properties. Diese Datei gehört ins Versionskon- Properties überschreiben 65
trollsystem und eignet sich damit für allgemein sichtbare projektspezifi- sche Konfigurationen. Iteration über Abhängigkeiten Es kommt recht häufig vor, dass man in Jelly-Skripten auf Informationen aus dem POM zugreifen muss. Wie wäre es zum Beispiel mit einem Auf- ruf des Wetterprogramms ohne die explizite Angabe jeder einzelnen Ab- hängigkeit als pathelement? Wie mache ich das? Der Zugriff auf das POM erfolgt in einem Jelly-Skript über die Variable ${pom}. Das folgende Ziel benutzt das Jelly-Tag forEach und ein path- element-Tag von Apache Ant, um den korrekten Klassenpfad zum Aufruf der Klasse mdn.weather.Weather zu setzen: Dieses geänderte Ziel funktioniert genauso wie das ursprüngliche Ziel weather:run aus dem vorigen Abschnitt. Offensichtlich ist diese Methode besser als die erste, weil man die Abhängigkeiten nur an einer Stelle pflegen muss: Wenn man eine neue Abhängigkeit zu project.xml hinzu- fügt, dann wird sie auch von weather:run automatisch in den Klassen- pfad übernommen. Was ist gerade geschehen? Ihr neues Jelly-Ziel iteriert über die Abhängigkeiten mit Hilfe des Tags j: forEach. Die Referenz ${pom.artifacts} bezieht sich auf die Methode getArtifacts( ) im POM, also auf eine Instanz der Klasse org.apache. maven.project.Project. Das Ergebnis von getArtifacts( ) ist eine Liste von org.apache.maven.project.Artifact-Objekten mit Informationen 66 Kapitel 2: Anpassung von Maven an eigene Wünsche
über je ein Artefakt aus project.xml. Die Schleife weist der Reihe nach Dieses Beispiel der Variablen lib je eines dieser Artefakte zu. Die Variable erlaubt damit benutzt j:for- den Zugriff auf den absoluten Pfad je eines Artefakts über ${lib.path}. Each, eine von Viele Informationen wie zum Beispiel der Pfad eines Artefakts aus ${pom} zwei Kontroll- sind wie in diesem Fall erst zur Laufzeit verfügbar. Wenn Sie mehr über strukturen in Jelly das Artifact-Objekt erfahren wollen, dann werfen Sie am besten einen zum Bilden von Blick in die JavaDocs dieser Klasse, die Sie unter http://maven.apache. Schleifen. Sowohl org/apidocs/org/apache/maven/repository/Artifact.html finden. j:forEach als auch j:while können über beliebige Col- Anpassung von Look and Feel lections, Maps, der Website Listen oder Arrays iterieren. Das Wettervorhersageprogramm funktioniert wie gewünscht. Allerdings entspricht die mit Maven generierte Website immer noch den Voreinstel- lungen von Maven. Sie können das Aussehen aber weitgehend an Ihre eigenen Vorstellungen anpassen. Wie mache ich das? Konfigurieren Sie das XDoc-Plugin. Werfen Sie dazu einen Blick auf die folgenden Properties aus project.properties: maven.xdoc.date = right maven.xdoc.date.format = MM/dd/yyyy maven.xdoc.crumb.separator = > maven.xdoc.developmentProcessUrl = http://www.slashdot.org maven.xdoc.poweredBy.title = Powered by the Mighty Maven maven.xdoc.theme.url=./style/custom.css Diese Properties setzen die Position und das Format des angezeigten Datums, den Pfadseparator in der Navigationsleiste, die URL zur Beschrei- bung des Entwicklungsprozesses sowie den Titel des »Powered by«- Icons. Wenn Sie maven site aufrufen, dann werden Sie sehen, dass diese Properties eine Reihe von subtilen Änderungen an der Website vorneh- men. Die Änderung der URL des Entwicklungsprozesses empfiehlt sich vor allem dann, wenn Ihre Firma eine eigene Seite zu diesem Thema unterhält. Wenn Sie diese Property unverändert lassen, dann verweist sie auf maven.apache.org. Was ist gerade geschehen? Die wichtigste Änderung des Look and Feel ist die Wahl des CSS, das von Maven benutzen soll. Um sich einen Überblick über die verfügbaren Stylesheets zu verschaffen, werfen Sie am besten einen Blick in das Anpassung von Look and Feel der Website 67
Verzeichnis target/docs/style Ihrer generierten Website. Sie sollten dort verschiedene Dateien mit Namen wie maven-base.css, maven-classic. css oder maven-theme.css finden. Die Anpassung des Look and Feel von Maven geschieht durch die Änderung dieser Dateien. Die ursprüngliche Datei liegt in xdocs/style/custom.css und wird durch die Property maven. xdoc.theme.url referenziert und in die generierte Website eingebunden. Eine vollständige Liste aller Properties des XDoc-Plugins finden Sie in der Online-Dokumentation unter http://maven.apache.org/reference/plugins/ xdoc/. Wenn Sie sich einen Überblick über die Anpassung der von Maven generierten Website verschaffen wollen, dann schauen Sie sich am bes- ten die Website eines anderen Projekts an, die mit Maven erstellt wurde. Ein Projekt, dessen Website von Maven generiert wurde, ist übrigens Maven selbst. (So eine Überraschung!) Abbildung 2-2 zeigt einen Screen- shot der Website des Maven-Projekts. Abbildung 2-2: Screenshot einer benutzerspezifisch konfigurierten und mit Maven generierten Website Die Maven-Website hat eine eigene Navigation, externe Links, ein eige- nes Datumsformat und bietet ein generiertes PDF mit dem Inhalt der kom- 68 Kapitel 2: Anpassung von Maven an eigene Wünsche
pletten Site an. Wenn Sie Ihre eigene Site konfigurieren wollen, dann empfiehlt sich ein Blick in das xdocs-Verzeichnis im Subversion-Reposi- tory von Apache (http://cvs.apache.org/viewcvs.cgi/maven/maven-1/core/ trunk/xdocs/?root=Apache-SVN). Das Apache-Repository kann über View- CVS eingesehen werden und erlaubt damit einen Einblick in die Website des Maven 1-Projekts. Man kann sich damit sehr schön anschauen, wie man die eigene Website konfigurieren kann. Werfen Sie zum Beispiel einen Blick in die Datei navigation.xml im Verzeichnis /maven/maven-1/ core/trunk/xdocs. Sie werden dann feststellen, dass das folgende XML- Fragment das aufklappbare Menü definiert, das wir im Abschnitt User’s Guide in Abbildung 2-2 sehen: In demselben Verzeichnis finden wir auch die FAQ von Maven in faq.fml sowie andere XDoc-Dateien mit der ausführlichen Dokumentation des Maven-Projekts, die bei der Generierung der Website benutzt werden. Nehmen Sie die Maven-Website ruhig als Vorlage für Ihr eigenes kom- merzielles oder Open Source-Projekt. Anpassung von Look and Feel der Website 69
Benutzung des FAQ-Plugins Viele Projekte enthalten ganze Seiten voller häufig gestellter Fragen und Das Element re- Antworten. Themen wie »Warum wurde das Projekt gestartet?« findet ports ist nicht als man ebenso wie Anweisungen zum Umgang mit speziellen technischen Ergänzung zu ver- Problemen. Das FAQ-Plugin von Maven ist ein praktisches Werkzeug zur stehen. Wenn es Entwicklung einer solchen Seite. nur ein report- Element ent- Wie mache ich das? hält, dann wird Um das FAQ-Plugin zu benutzen, müssen Sie es wie folgt im reports-Ele- auch nur dieser ment der Datei project.xml referenzieren: Bericht generiert. Sie müssen wirk- maven-faq-plugin lich alle zu gene- rierenden Be- Damit ist der Report aktiviert. Als Nächstes erzeugen Sie bitte eine Datei richte explizit xdocs/faq.fml mit dem folgenden Inhalt: angeben.
Installation Wie installiere ich das Weather-Projekt? Ganz einfach: Kopieren Sie das Projekt aus dem Subversion-Repository, und rufen Sie maven wsdl2java auf. Als Nächstes generieren Sie die Site erneut, indem Sie maven site aus- führen. Dann laden Sie target/docs/index.html in Ihren Browser. Klicken Sie auf PROJECT REPORTS und FAQS, dann sollten Sie die in Abbildung 2-3 abgebildete Seite sehen. Abbildung 2-3: Beispiel einer mit Maven generierten FAQ Benutzung des FAQ-Plugins 71
Was ist gerade geschehen? Sie haben das FAQ-Plugin aktiviert, indem Sie es im reports-Element Ihres project.xml referenziert haben. Als Nächstes haben Sie in einem XML-Dokument verschiedene Fragen und Antworten formuliert. Bei der Generierung der Site wurde diese FAQ automatisch in eine HTML-Seite übersetzt und als Link in das Untermenü mit Berichten über das Projekt integriert. 72 Kapitel 2: Anpassung von Maven an eigene Wünsche
Sie können auch lesen