1 Welches Problem löst Maven? Maven kann den kompletten Projektlifecycle verwalten und im Speziellen die internen und externen Abhängigkeiten eines Projekts managen. Im Wesentlichen geschieht dies über eine projektspezifische XML Konfigurationsdatei namens pom.xml. Die benötigten Artefakte werden dabei automatisch von einem der Maven Paket Repositories aus dem Internet heruntergeladen oder aus einem lokalen Repository kopiert (dies befindet sich per default in $home/.m2/repository). Maven bietet eine Abstraktion von der IDE. Das heißt, dass in Teams mit unterschiedlichen IDEs gearbeitet werden kann. Es können Eclipse-Projektdateien, Netbeans-Projektdateien, etc generiert werden. Im.m2-Verzeichnis können sich außer dem lokalen Respository auch Konfigurationsdateien befinden. 1.1 Aufbau der pom.xml Ablageort: Toplevel im Projektordner Einfaches Beispiel mit nur einer Abhängigkeit: <p r o j e c t xmlns="http : / / maven. apache. org /POM/ 4. 0. 0 " xmlns : x s i ="http : / /www. w3. org /2001/XMLSchema i n s t a n c e " x s i : schemalocation="http : / / maven. apache. org /POM/ 4. 0. 0 http : / / maven. apache. org /maven v4_0_0. xsd"> <modelversion >4.0.0 </ modelversion> <groupid>org. sonatype. mavenbook. simple </groupid> <a r t i f a c t I d >simple </ a r t i f a c t I d > <packaging>j a r </packaging> <v e r s i o n >1.0 SNAPSHOT</v e r s i o n > <name>simple </name> <url >http : / / maven. apache. org </url > <dependencies > <dependency> <groupid>j u n i t </groupid> <a r t i f a c t I d >j u n i t </ a r t i f a c t I d > <v e r s i o n >3.8.1 </ v e r s i o n > <scope>t e s t </scope> </dependency> </dependencies > </p r o j e c t > Detailliertere Information zur pom kann man den frei-verfügbaren Onlinebüchern 1 von Sonatype entnehmen. 2 Prinzipien Maven funktioniert (wie viele andere Java Projekte) nach dem Prinzip Convention over Configuration. Das bedeutet bei Maven, dass eine feste Verzeichnisstruktur vorgegeben ist: Sourecode: $basedir/src/main/java Resources: $basedir/src/main/resources Tests: $basedir/src/test Bytecode: $basedir/target/classes Buildartefakte (JARs, WARs, etc.): $basedir/target/ Natürlich können diese Defaults überschrieben werden, aber der Vorteil von Convention over Configuration ist, dass diese eben nicht zwingend angegeben werden müssen. 1 http://www.sonatype.com/documentation/books 1
3 Lifecycle Der Maven Default Lifecycle umfasst mehr als 20 Phasen. Hier die wichtigsten: compile: Sourcecode compilieren test-compile: Test-Sourcecode compilieren test: (Unit-) Tests ausführen package: Buildartefakt erzeugen (JAR, WAR, etc.) integration-test: Integrationtests durchführen (z.b. auf einem Embedded Appserver wie jetty) install: Die Buildartefakte ins lokale Repository installieren deploy: Die Buildartefakte ins remote Repository kopieren (z.b. Nexus) Ausführen einer einzelnen dieser Default Phasen mit mvn <phase>. 3.1 compile Standardmäßig verwendet Maven javac um die Sourcen aus $basedir/src/main/java nach $basedir/target/classes zu compilieren. Dabei werden als Minimal Settings für den Source Java 1.3 und als Compileziel gar Java 1.1 angesetzt. Um dies zu überschreiben, müssen wir folgendes in der pom hinzufügen: <p r o j e c t > <build > <p l u g i n s > <plugin > <a r t i f a c t I d >maven compiler plugin </ a r t i f a c t I d > <c o n f i g u r a t i o n > <source >1.5</ source > <t a r g e t >1.5</ t a r g e t > </ c o n f i g u r a t i o n > </plugin > </p l u g i n s > </build > </p r o j e c t > 3.2 test-compile Compilieren der Testsourcen aus $basedir/src/test. 3.3 test Ausführen der Tests mit JUnit (andere Testframeworks erfordern Anpassung der pom). 3.4 package Wertet das packaging-element aus (default jar) und erzeugt in $basedir/target/ das entsprechende Buildartefakt. 3.5 install Kopiert das Buildartefakt zur Verwendung in anderen Maven-Projekten in das lokale Repository. 2
3.6 deploy Kopiert das Buildartefakt zur Verwendung in anderen Maven-Projekten in das remote Repository. 4 Plugins Bei Maven ist eigentlich alles ein Plugin, vom Compiler-Plugin bis zur Testausführung. 4.1 Befehle zur Nutzung wichtiger Plugins Ausführen der einzelnen Befehle mit mvn <befehl>. archetype:generate: Ein neues Projekt anlegen, hierbei wird interaktiv durch den Prozess geführt install:install-file -Dfile=foo.jar -DgroupId=bar -DartifactId=foo -Dversion=1.0 -Dpackaging=jar: Ein eigenes Artefakt im lokalen Repository installieren eclipse:eclipse: Eine passende Eclipse-Projektdatei erzeugen eclipse:add-maven-repo -Declipse.workspace=/path/to/wsp: Das lokale Maven-Repository zum Eclipse-Buildpath hinzufügen netbeans-freeform:generate-netbeans-project: Eine passende Netbeans-Projektdatei erzeugen jetty:run: Webprojekt auf dem integrierten jetty laufen lassen Bei archetype:generate gibt es im Moment 249 Projekte zur Auswahl, hier ein Ausschnitt: [ INFO ] Scanning f o r p r o j e c t s [ INFO ] S e a r c h i n g r e p o s i t o r y f o r p l u g i n with p r e f i x : a r c h e t y p e. [ INFO ] B u i l d i n g Maven D e f a u l t P r o j e c t [ INFO ] task segment : [ a r c h e t y p e : g e n e r a t e ] ( a g g r e g a t o r s t y l e ) [ INFO ] Preparing archetype : generate [ INFO ] No g o a l s needed f o r p r o j e c t s k i p p i n g [ INFO ] [ archetype : generate ] [ INFO ] G e n e r a t i n g p r o j e c t i n I n t e r a c t i v e mode [ INFO ] No archetype defined. Using maven archetype q u i c k s t a r t ( org. apache. maven. a r c h e t y p e s : maven a r c h e t y p e q u i c k s t a r t : 1. 0 ) Choose archetype : 1 : remote > docbkx quickstart archetype ( n u l l ) 2 : remote > j2me simple ( Maven 2 Archetype f o r midlet a p p l i c a t i o n using j2me maven plugin ) 3 : remote > vaadin a r c h e t y p e c l e a n ( This a r c h e t y p e g e n e r a t e s a s i m p l e Vaadin a p p l i c a t i o n as a Maven p r o j e c t. No custom widgetset i s included. ) 4 : remote > vaadin a r c h e t y p e sample ( This a r c h e t y p e g e n e r a t e s a Vaadin a p p l i c a t i o n as a Maven p r o j e c t. The a p p l i c a t i o n c o n t a i n s a custom GWT w i d g e t s e t t h a t i s compiled by the GWT c o m p i l e r and i n t e g r a t e d i n t o the p r o j e c t as p a r t o f the b u i l d p r o c e s s. The a p p l i c a t i o n i s based on the Vaadin Color P i c k e r Demo a p p l i c a t i o n a v a i l a b l e at http : / / vaadin. com. ) 1 3 : remote > l i f t a r c h e t y p e blank ( Blank p r o j e c t a r c h e t y p e f o r L i f t Web Framework. ) 1 4 : remote > l i f t a r c h e t y p e h e l l o l i f t ( Archetype h e l l o l i f t, a sample L i f t a p p l i c a t i o n ) 15: remote > l i f t archetype jpa basic ( Basic JPA archetype f o r L i f t Web Framework. ) 16: remote > l i f t archetype jpa blank ( Blank JPA archetype f o r L i f t Web Framework. ) 21: remote > maven archetype sar ( n u l l ) 22: remote > maven archetype gwt (An archetype which contains a sample Maven GWT p r o j e c t. ) 5 8 : remote > maven a r c h e t y p e q u i c k s t a r t (An a r c h e t y p e which c o n t a i n s a sample Maven p r o j e c t. ) 1 1 4 : remote > wicket a r c h e t y p e q u i c k s t a r t ( n u l l ) 162: remote > gwt maven plugin ( Maven plugin f o r the Google Web Toolkit. ) 2 0 8 : remote > a p p l i c a t i o n ( n u l l ) 209: remote > hibernate support ( n u l l ) 2 1 0 : remote > html war ( n u l l ) 244: remote > spring osgi bundle archetype ( Spring OSGi Maven2 Archetype ) 245: remote > spring ws archetype ( Spring Web S e r v i c e s Maven2 Archetype. ) 2 4 6 : remote > t r a i l s a r c h e t y p e ( n u l l ) 2 4 7 : remote > t r a i l s s e c u r e a r c h e t y p e ( n u l l ) 248: remote > tynamo archetype ( n u l l ) 3
249: remote > circumflex archetype ( n u l l ) Choose a number : 5 8 : Choose version : 1 : 1. 0 2 : 1.0 alpha 1 3 : 1.0 alpha 2 4 : 1.0 alpha 3 5 : 1.0 alpha 4 Choose a number : : 1 D e f i n e v a l u e f o r p r o p e r t y groupid : : hm. s e 2. t e s t D e f i n e v a l u e f o r p r o p e r t y a r t i f a c t I d : : Test Define value f o r property version : 1.0 SNAPSHOT: D e f i n e v a l u e f o r p r o p e r t y package : hm. s e 2. t e s t : Confirm p r o p e r t i e s c o n f i g u r a t i o n : groupid : hm. s e 2. t e s t a r t i f a c t I d : Test version : 1.0 SNAPSHOT package : hm. s e 2. t e s t Y: [ INFO ] Using f o l l o w i n g p a r a m e t e r s f o r c r e a t i n g OldArchetype : maven a r c h e t y p e q u i c k s t a r t : 1. 0 [ INFO ] Parameter : groupid, Value : hm. s e 2. t e s t [ INFO ] Parameter : packagename, Value : hm. s e 2. t e s t [ INFO ] Parameter : package, Value : hm. s e 2. t e s t [ INFO ] Parameter : a r t i f a c t I d, Value : Test [ INFO ] Parameter : basedir, Value : / Software_Engineering_II /GruppenPuzzleMaven [ INFO ] Parameter : v e r s i o n, Value : 1.0 SNAPSHOT [ INFO ] End of debug i n f o from r e s o u r c e s from generated POM [ INFO ] OldArchetype created in d i r : / Software_Engineering_II /GruppenPuzzleMaven / Test [ INFO ] BUILD SUCCESSFUL [ INFO ] Total time : 1 minutes 10 seconds [ INFO ] Finished at : Wed May 05 1 5 : 0 8 : 1 5 CEST 2010 [ INFO ] Final Memory : 18M/182M Im Anschluss an die Projektwahl (default hier ein simples Java Hello World ) wird noch nach verschiedenen projekt-spezifischen Angaben gefragt, wie Name des Projekts (artifactid), version, usw. archetype:generate erleichtert den Start-up von Projekten, da vor allem bei Webprojekten eine sehr grosse Anzahl an Dependencies benötigt wird. Die Archetypen in der Liste stammen aus dem archetype-catalog.xml des verwendeten Maven-Repositories. Sehr praktisch ist auch das jetty-plugin, mit dem man sein Webprojekt direkt über Maven auf dem jetty-appserver ausführen und damit ausprobieren kann. Häufig werden mit diesem Plugin auch Integrations-Tests realisiert. <p l u g i n s > <plugin > <groupid>org. mortbay. j e t t y </groupid> <a r t i f a c t I d >maven j e t t y plugin </ a r t i f a c t I d > <v e r s i o n >6.1.22 </ v e r s i o n > <c o n f i g u r a t i o n > <contextpath >/</contextpath> <s c a n I n t e r v a l S e c o n d s >2</s c a n I n t e r v a l S e c o n d s > <stopkey>foo </stopkey> <stopport >9999</ stopport> <connectors > <connector implementation="org. mortbay. j e t t y. nio. SelectChannelConnector"> <port >9998</ port> <maxidletime >6000</maxIdleTime> </connector > </connectors > </ c o n f i g u r a t i o n > <e x e c u t i o n s > <execution > <id>s t a r t j e t t y </id> <phase>pre i n t e g r a t i o n t e s t </phase> <g o a l s > <goal >run</goal > </g o a l s > <c o n f i g u r a t i o n > <s c a n I n t e r v a l S e c o n d s >0</s c a n I n t e r v a l S e c o n d s > <daemon>true </daemon> <usetestclasspath >true </usetestclasspath > </ c o n f i g u r a t i o n > </execution > <execution > 4
<id>stop j e t t y </id> <phase>post i n t e g r a t i o n t e s t </phase> <g o a l s > <goal >stop </goal > </g o a l s > </execution > </e x e c u t i o n s > </plugin > </p l u g i n s > 5 Der Nexus Server Der Nexus-Server ist ein Maven-Package-Proxyserver der von Projekten und Firmen benutzt wird. Mit ihm kann man Dependencies aus dem Internet cachen und sammeln, sowie lokale eigene Artefakte allen Entwicklern/innen zur Verfügung stellen. Der Nexus bietet ein Webinterface über das man Artefakte suchen kann. Findet er das passende Artefakt, stellt er auch gleich den passenden Dependency-Block für die pom.xml zur Verfügung. Abbildung 1: Weboberfläche des Nexus Abbildung 2: Suche im Nexus-Repository 5
Abbildung 3: Information zum Artefakt inklusive copy-paste-barem Dependency-Block 6 Eclipse Integration Es exisitiert ein Eclipse-Plugin, mit dem sich die Maven-Funktionalitäten aus Eclipse heraus nutzen lassen. Abbildung 4: Eclipse-Frontend für archetype:generate 6
Abbildung 5: Eclipse-Projekt unter Maven-Kontrolle Abbildung 6: Eclipse-XML-Editor 7
Abbildung 7: Hinzufügen von Dependencies Abbildung 8: Dependency-Tab im XML-Editor 8