Maven-Multimodulprojekte (= Multiprojekte) stellen eine besondere Herausforderung dar: Je nach Maven-Multimodulprojekt-Konfiguration funktionieren nicht mehr alle Maven-Plugins, die Zusammenarbeit mit anderen Tools wie Eclipse kann schwierig sein und der Versionierungsprozess kann aufwändig sein.
Wichtig ist, bei Maven-Multimodulprojekten die Unterschiede zwischen dem "Flat Project Layout" und dem "Hierachical Project Layout" zu kennen.
Infos zu den genannten Tools finden Sie unter Maven, Eclipse und Mercurial (hg).
Weiter unten finden Sie konkrete Beispiele und Erläuterungen für Projekte im "Flat Project Layout" und im "Hierachical Project Layout".
Vorab folgt eine Gegenüberstellung einiger Unterschiede:
| Flat Project Layout | Hierachical Project Layout | |
|---|---|---|
| Verzeichnisstruktur |
MeinWorkspace
|- Parent-Modul
| '- ...
|- Untermodul-1
| '- ...
'- Untermodul-2
'- ...
|
MeinWorkspace
'- Parent-Modul
|- ...
|- Untermodul-1
| '- ...
'- Untermodul-2
'- ...
|
| <modules>-Sektion in der pom.xml |
<artifactId>Parent-Modul</artifactId>
<packaging>pom</packaging>
<modules>
<module>../Untermodul-1</module>
<module>../Untermodul-2</module>
</modules>
|
<artifactId>Parent-Modul</artifactId>
<packaging>pom</packaging>
<modules>
<module>Untermodul-1</module>
<module>Untermodul-2</module>
</modules>
|
| DVCS-Repositories (z.B. Mercurial) | Sowohl pro Maven-Parent-Modul als auch pro Maven-Untermodul (also pro pom.xml) wird jeweils ein eigenes DVCS-Repository verwendet | Pro Maven-Multimodulprojekt (inkl. aller Unterprojekte) wird nur ein einziges DVCS-Repository verwendet |
| Import in Eclipse | Problemlos, es muss nicht unbedingt ein Plugin verwendet werden | Nur mit dem M2Eclipse-Plugin möglich |
| Maven Release Plugin | Funktioniert nicht (abhängig vom VCS) | Funktioniert |
| Probleme (z.B. in Eclipse) wegen nicht eindeutiger Unterprojektnamen |
Unterprojektnamen sind zwangsläufig eindeutig | Unterprojektnamen sind oft nicht eindeutig über verschiedene Maven-Multimodulprojekte: Dann können nicht mehrere Maven-Multimodulprojekte gleichzeitig in Eclipse importiert werden |
Im Folgenden werden beispielhaft mehrere Maven-Projekte angelegt, um mögliche Vorgehensweisen und die Unterschiede zu erläutern.
Das folgende Beispiel wurde unter Windows 7 64 Bit getestet mit:
Das Beispiel geht von einem zentralen hgweb-Webserver für
Mercurial-Repositories aus.
Falls Sie noch keinen installiert haben, siehe: hgweb-Installationsbeschreibung.
Falls Sie einen entsprechend dieser Anleitung installiert haben, starten Sie ihn über (bitte Tomcat-Pfad anpassen):
cd /D D:\Tools\Tomcat-hgweb\bin
startup.bat
Folgende Mercurial-Repositories-Struktur soll eingerichtet werden:

Verzweigen Sie auf dem hgweb-Server in das Verzeichnis für Mercurial-Repositories und legen Sie folgendermaßen die neuen Projektrepositories an (passen Sie den Pfad D:\Tools\hgweb-repos an):
cd /D D:\Tools\hgweb-repos
md Basisprojekt
cd Basisprojekt
hg init masterpom
echo [web] > masterpom\.hg\hgrc
echo description = Zentrale Maven-Master-POM >> masterpom\.hg\hgrc
hg init commons
echo [web] > commons\.hg\hgrc
echo description = Zentrale Common-Utilities >> commons\.hg\hgrc
md ..\Flatprojekt
cd ..\Flatprojekt
hg init flat-multiproj
echo [web] > flat-multiproj\.hg\hgrc
echo description = Flat-Multiprojekt-Parent-POM >> flat-multiproj\.hg\hgrc
hg init flat-bean
echo [web] > flat-bean\.hg\hgrc
echo description = Flat-Multiprojekt-Bean-Modul >> flat-bean\.hg\hgrc
hg init flat-web
echo [web] > flat-web\.hg\hgrc
echo description = Flat-Multiprojekt-Web-Modul >> flat-web\.hg\hgrc
md ..\Hierarchyprojekt
cd ..\Hierarchyprojekt
hg init hierarchy-multiproj
echo [web] > hierarchy-multiproj\.hg\hgrc
echo description = Hierarchisches Multiprojekt >> hierarchy-multiproj\.hg\hgrc
cd ..
dir
start http://localhost:4419/hgweb/cgi-bin/meinprojekt.cgi
Sie erhalten auf dem hgweb-Server folgende Mercurial-Repositories-Verzeichnisstruktur:
[D:\Tools\hgweb-repos]
|- [Basisprojekt]
| |- [commons]
| | '- [.hg]
| | '- ...
| '- [masterpom]
| '- [.hg]
| '- ...
|- [Flatprojekt]
| |- [flat-bean]
| | '- [.hg]
| | '- ...
| |- [flat-multiproj]
| | '- [.hg]
| | '- ...
| '- [flat-web]
| '- [.hg]
| '- ...
'- [Hierarchyprojekt]
'- [hierarchy-multiproj]
'- [.hg]
'- ...
Und die hgweb-Webseite zeigt:
Verzweigen Sie auf Ihrem Arbeits-PC in Ihr Eclipse-Workspace-Verzeichnis (z.B. D:\MeinWorkspace), clonen Sie die neu angelegten Mercurial-Repositories und bereiten Sie Sourcecode-Verzeichnisse vor (passen Sie Pfade und URLs an):
cd /D D:\MeinWorkspace
hg clone http://localhost:4419/hgweb/cgi-bin/meinprojekt.cgi/Basisprojekt/masterpom
hg clone http://localhost:4419/hgweb/cgi-bin/meinprojekt.cgi/Basisprojekt/commons
hg clone http://localhost:4419/hgweb/cgi-bin/meinprojekt.cgi/Flatprojekt/flat-multiproj
hg clone http://localhost:4419/hgweb/cgi-bin/meinprojekt.cgi/Flatprojekt/flat-bean
hg clone http://localhost:4419/hgweb/cgi-bin/meinprojekt.cgi/Flatprojekt/flat-web
hg clone http://localhost:4419/hgweb/cgi-bin/meinprojekt.cgi/Hierarchyprojekt/hierarchy-multiproj
md commons\src\main\java\de\meinefirma\meinprojekt
md flat-bean\src\main\java\de\meinefirma\meinprojekt
md flat-bean\src\test\java\de\meinefirma\meinprojekt
md flat-web\src\main\webapp\WEB-INF
dir
Legen Sie im masterpom-Projektverzeichnis eine Datei mit den von Mercurial zu ignorierenden Dateien und Verzeichnissen an: .hgignore
syntax: glob .settings CVS logs target *.classpath *.cvsignore *.project Thumbs.db thumbs.db
Kopieren Sie diese Datei auch in die anderen Module:
cd /D D:\MeinWorkspace
copy masterpom\.hgignore commons
copy masterpom\.hgignore flat-bean
copy masterpom\.hgignore flat-multiproj
copy masterpom\.hgignore flat-web
copy masterpom\.hgignore hierarchy-multiproj
Erzeugen Sie im masterpom-Projektverzeichnis die Master-POM-Projektkonfiguration: pom.xml
<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/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>de.meinefirma.meinprojekt</groupId>
<artifactId>masterpom</artifactId>
<version>1.0</version>
<packaging>pom</packaging>
<name>masterpom</name>
<properties>
<hg-proj-path>Basisprojekt</hg-proj-path>
<hg-base-url>http://localhost:4419/hgweb/cgi-bin/meinprojekt.cgi</hg-base-url>
<project.build.sourceEncoding>ISO-8859-1</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<maven.build.timestamp.format>yyyy-MM-dd HH:mm</maven.build.timestamp.format>
</properties>
<build>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.5.1</version>
<configuration>
<source>1.6</source>
<target>1.6</target>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-release-plugin</artifactId>
<version>2.3.2</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-scm-plugin</artifactId>
<version>1.8</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>2.3</version>
<configuration>
<packagingExcludes>WEB-INF/web.xml</packagingExcludes>
<archive>
<manifestEntries>
<Modulname>${project.name}</Modulname>
<Modulversion>${project.version}</Modulversion>
<Maven-Build-Timestamp>${maven.build.timestamp}</Maven-Build-Timestamp>
<VCS-Buildnumber>${buildNumber}</VCS-Buildnumber>
<hg-ChangeSet-ID>${changeSet}, ${changeSetDate}</hg-ChangeSet-ID>
</manifestEntries>
</archive>
</configuration>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>buildnumber-maven-plugin</artifactId>
<version>1.2</version>
<executions>
<execution>
<phase>validate</phase>
<goals>
<goal>create</goal>
<goal>hgchangeset</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>versions-maven-plugin</artifactId>
<version>1.3.1</version>
</plugin>
<plugin>
<groupId>org.mortbay.jetty</groupId>
<artifactId>maven-jetty-plugin</artifactId>
<version>6.1.26</version>
</plugin>
</plugins>
</pluginManagement>
</build>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>de.meinefirma.meinprojekt</groupId>
<artifactId>commons</artifactId>
<version>2.0</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.10</version>
<scope>test</scope>
</dependency>
</dependencies>
</dependencyManagement>
<distributionManagement>
<repository>
<id>DistributionRepo</id>
<url>file:///D:\MeinDistributionRepo</url>
</repository>
<snapshotRepository>
<id>DistributionRepo</id>
<url>file:///D:\MeinDistributionRepo</url>
</snapshotRepository>
</distributionManagement>
<scm>
<url>${hg-base-url}/${hg-proj-path}/${project.artifactId}</url>
<connection>scm:hg:${project.scm.url}</connection>
<developerConnection>scm:hg:${project.scm.url}</developerConnection>
</scm>
</project>
Bitte beachten Sie, dass bei <distributionManagement> normalerweise natürlich nicht einfach ein Verzeichnis, wie in diesem Beispiel, sondern ein Maven-Repository-Manager (z.B. Nexus) eingetragen werden sollte (falls Sie einen installiert haben).
Erzeugen Sie im commons-Projektverzeichnis die commons-Projektkonfiguration: pom.xml
<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/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>de.meinefirma.meinprojekt</groupId>
<artifactId>masterpom</artifactId>
<version>1.0</version>
<relativePath>../masterpom/pom.xml</relativePath>
</parent>
<artifactId>commons</artifactId>
<version>2.0</version>
<packaging>jar</packaging>
<name>commons</name>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
</dependency>
</dependencies>
<scm>
<url>${hg-base-url}/${hg-proj-path}/${project.artifactId}</url>
<connection>scm:hg:${project.scm.url}</connection>
<developerConnection>scm:hg:${project.scm.url}</developerConnection>
</scm>
</project>
Erzeugen Sie im commons\src\main\java\de\meinefirma\meinprojekt-Verzeichnis die Java-Klasse: MeinUtil.java
package de.meinefirma.meinprojekt;
public class MeinUtil
{
public static int meineUtilMethode( int i1, int i2 )
{
return i1 + i2;
}
}
Überprüfen Sie folgendermaßen, dass unter <connection> und <developerConnection> im <scm>-Abschnitt die korrekte Mercurial-hgweb-URI eingetragen ist:
cd /D D:\MeinWorkspace\masterpom
mvn help:effective-pom
<scm>
<connection>scm:hg:http://localhost:4419/hgweb/cgi-bin/meinprojekt.cgi/Basisprojekt/masterpom</connection>
<developerConnection>scm:hg:http://localhost:4419/hgweb/cgi-bin/meinprojekt.cgi/Basisprojekt/masterpom</developerConnection>
<url>http://localhost:4419/hgweb/cgi-bin/meinprojekt.cgi/Basisprojekt/masterpom</url>
</scm>
cd /D D:\MeinWorkspace\commons
mvn help:effective-pom
<scm>
<connection>scm:hg:http://localhost:4419/hgweb/cgi-bin/meinprojekt.cgi/Basisprojekt/commons</connection>
<developerConnection>scm:hg:http://localhost:4419/hgweb/cgi-bin/meinprojekt.cgi/Basisprojekt/commons</developerConnection>
<url>http://localhost:4419/hgweb/cgi-bin/meinprojekt.cgi/Basisprojekt/commons</url>
</scm>
Erzeugen Sie im flat-multiproj-Projektverzeichnis die flat-multiproj-Projektkonfiguration: pom.xml
<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/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>de.meinefirma.meinprojekt</groupId>
<artifactId>masterpom</artifactId>
<version>1.0</version>
<relativePath>../masterpom/pom.xml</relativePath>
</parent>
<artifactId>flat-multiproj</artifactId>
<version>3.0-SNAPSHOT</version>
<packaging>pom</packaging>
<name>flat-multiproj</name>
<modules>
<module>../flat-bean</module>
<module>../flat-web</module>
</modules>
<properties>
<hg-proj-path>Flatprojekt</hg-proj-path>
</properties>
<scm>
<url>${hg-base-url}/${hg-proj-path}/${project.artifactId}</url>
<connection>scm:hg:${project.scm.url}</connection>
<developerConnection>scm:hg:${project.scm.url}</developerConnection>
</scm>
</project>
Erzeugen Sie im flat-bean-Projektverzeichnis die flat-bean-Projektkonfiguration: pom.xml
<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/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>de.meinefirma.meinprojekt</groupId>
<artifactId>flat-multiproj</artifactId>
<version>3.0-SNAPSHOT</version>
<relativePath>../flat-multiproj/pom.xml</relativePath>
</parent>
<artifactId>flat-bean</artifactId>
<packaging>jar</packaging>
<name>flat-bean</name>
<dependencies>
<dependency>
<groupId>de.meinefirma.meinprojekt</groupId>
<artifactId>commons</artifactId>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
</dependency>
</dependencies>
</project>
Erzeugen Sie im flat-web-Projektverzeichnis die flat-web-Projektkonfiguration: pom.xml
<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/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>de.meinefirma.meinprojekt</groupId>
<artifactId>flat-multiproj</artifactId>
<version>3.0-SNAPSHOT</version>
<relativePath>../flat-multiproj/pom.xml</relativePath>
</parent>
<artifactId>flat-web</artifactId>
<packaging>war</packaging>
<name>flat-web</name>
<build>
<finalName>${project.artifactId}</finalName>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>buildnumber-maven-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.mortbay.jetty</groupId>
<artifactId>maven-jetty-plugin</artifactId>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>de.meinefirma.meinprojekt</groupId>
<artifactId>flat-bean</artifactId>
<version>${project.version}</version>
</dependency>
</dependencies>
</project>
Erzeugen Sie im flat-bean\src\main\java\de\meinefirma\meinprojekt-Verzeichnis die Java-Klasse: MeineBean.java
package de.meinefirma.meinprojekt;
public class MeineBean
{
public static int berechne( int i1, int i2 )
{
return MeinUtil.meineUtilMethode( i1, i2 );
}
}
Erzeugen Sie im flat-bean\src\test\java\de\meinefirma\meinprojekt-Verzeichnis den JUnit-Test: MeineBeanTest.java
package de.meinefirma.meinprojekt;
import org.junit.*;
public class MeineBeanTest
{
@Test
public void testMeineBean()
{
Assert.assertEquals( 3, MeineBean.berechne( 1, 2 ) );
}
}
Erzeugen Sie im flat-web\src\main\webapp-Verzeichnis die JSP: index.jsp
<%@ page import="java.io.*" %>
<%@ page import="java.util.*" %>
<%@ page import="java.util.jar.*" %>
<%@ page import="de.meinefirma.meinprojekt.MeineBean" %>
<html>
<body>
<h2>Hello World!</h2>
<%
String pth = getServletConfig().getServletContext().getRealPath( "/" );
if( !pth.endsWith( "/" ) && !pth.endsWith( "\\" ) ) pth += "/";
File mf = new File( pth + "META-INF/MANIFEST.MF" );
if( mf.exists() ) {
out.println( "<h4>Attribute in der META-INF/MANIFEST.MF:</h4>" );
Manifest manifest = new Manifest( new FileInputStream( mf ) );
for( Map.Entry<Object,Object> attr : manifest.getMainAttributes().entrySet() ) {
out.println( attr + "<br>" );
}
}
out.println( "<h4>MeineBean:</h4>MeineBean.berechne( 1, 2 ): " + MeineBean.berechne( 1, 2 ) );
%>
</body>
</html>
Erzeugen Sie im flat-web\src\main\webapp\WEB-INF-Verzeichnis die Webapp-Konfiguration: web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
</web-app>
Erzeugen Sie im flat-multiproj-Projektverzeichnis die Batchdatei: run-webapp.bat
@echo. @pushd . cd ..\masterpom call mvn clean install @echo on if errorlevel 1 goto _Fehler @echo. cd ..\commons call mvn clean install @echo on if errorlevel 1 goto _Fehler @echo. cd ..\flat-multiproj call mvn clean install @echo on if errorlevel 1 goto _Fehler cd ..\flat-web start cmd /C mvn jetty:run-war @ping -n 10 127.0.0.1 >nul start http://localhost:8080/flat-web @echo. type target\work\webapp\META-INF\MANIFEST.MF :_Fehler @popd @echo.
Überprüfen Sie folgendermaßen, dass unter <connection> und <developerConnection> im <scm>-Abschnitt die korrekte Mercurial-hgweb-URI eingetragen ist:
cd /D D:\MeinWorkspace\flat-multiproj
mvn help:effective-pom
<scm>
<connection>scm:hg:http://localhost:4419/hgweb/cgi-bin/meinprojekt.cgi/Flatprojekt/flat-multiproj</connection>
<developerConnection>scm:hg:http://localhost:4419/hgweb/cgi-bin/meinprojekt.cgi/Flatprojekt/flat-multiproj</developerConnection>
<url>http://localhost:4419/hgweb/cgi-bin/meinprojekt.cgi/Flatprojekt/flat-multiproj</url>
</scm>
cd /D D:\MeinWorkspace\flat-bean
mvn help:effective-pom
<scm>
<connection>scm:hg:http://localhost:4419/hgweb/cgi-bin/meinprojekt.cgi/Flatprojekt/flat-bean</connection>
<developerConnection>scm:hg:http://localhost:4419/hgweb/cgi-bin/meinprojekt.cgi/Flatprojekt/flat-bean</developerConnection>
<url>http://localhost:4419/hgweb/cgi-bin/meinprojekt.cgi/Flatprojekt/flat-bean</url>
</scm>
cd /D D:\MeinWorkspace\flat-web
mvn help:effective-pom
<scm>
<connection>scm:hg:http://localhost:4419/hgweb/cgi-bin/meinprojekt.cgi/Flatprojekt/flat-web</connection>
<developerConnection>scm:hg:http://localhost:4419/hgweb/cgi-bin/meinprojekt.cgi/Flatprojekt/flat-web</developerConnection>
<url>http://localhost:4419/hgweb/cgi-bin/meinprojekt.cgi/Flatprojekt/flat-web</url>
</scm>
Überprüfen Sie Ihre Workspace-Verzeichnisse:
cd /D D:\MeinWorkspace
tree /F
[\MeinWorkspace]
|- [commons]
| |- .hgignore
| |- pom.xml
| |- [.hg]
| | '- ...
| '- [src]
| '- [main]
| '- [java]
| '- [de]
| '- [meinefirma]
| '- [meinprojekt]
| '- MeinUtil.java
|- [flat-bean]
| |- .hgignore
| |- pom.xml
| |- [.hg]
| | '- ...
| '- [src]
| |- [main]
| | '- [java]
| | '- [de]
| | '- [meinefirma]
| | '- [meinprojekt]
| | '- MeineBean.java
| '- [test]
| '- [java]
| '- [de]
| '- [meinefirma]
| '- [meinprojekt]
| '- MeineBeanTest.java
|- [flat-multiproj]
| |- .hgignore
| |- pom.xml
| |- run-webapp.bat
| '- [.hg]
| '- ...
|- [flat-web]
| |- .hgignore
| |- pom.xml
| |- [.hg]
| | '- ...
| '- [src]
| '- [main]
| '- [webapp]
| |- index.jsp
| '- [WEB-INF]
| '- web.xml
|- [hierarchy-multiproj]
| |- .hgignore
| '- [.hg]
| '- ...
'- [masterpom]
|- .hgignore
|- pom.xml
'- [.hg]
'- ...
Da bisher nur Module im "Flat Project Layout" angelegt wurden, liegen alle pom.xml-Dateien in direkten Unterverzeichnissen zum Eclipse-Workspace-Verzeichnis. Es gibt noch keine hierarchisch angeordnete "nested" Module.
Der bisherige Entwicklungsstand wird in die Mercurial-Repositories gesichert:
cd /D D:\MeinWorkspace
cd masterpom
hg add
hg commit -m "add: pom.xml"
hg push
cd ..\commons
hg add
hg commit -m "add: pom.xml + MeinUtil.java"
hg push
cd ..\flat-multiproj
hg add
hg commit -m "add: pom.xml"
hg push
cd ..\flat-bean
hg add
hg commit -m "add: pom.xml + MeineBean.java + MeineBeanTest.java"
hg push
cd ..\flat-web
hg add
hg commit -m "add: pom.xml + index.jsp + web.xml"
hg push
cd ..
Testen Sie die Webapp:
cd /D D:\MeinWorkspace\flat-multiproj
run-webapp.bat
Die Module werden compiliert, der JUnit-Test wird ausgeführt, die Ergebnis-Artefakte werden ins lokale Maven-Repository gespeichert, der Jetty-Webserver wird gestartet und es wird die Ergebnis-Webseite angezeigt:
Hello World! Attribute in der META-INF/MANIFEST.MF: Modulname=flat-web Modulversion=3.0-SNAPSHOT VCS-Buildnumber=ba710a8a8d70 hg-ChangeSet-ID=ba710a8a8d70, 2012-02-26 16:04 +0100 Maven-Build-Timestamp=2012-02-26 16:06 ... MeineBean: MeineBean.berechne( 1, 2 ): 3
Die Webseite ruft MeineBean.berechne() aus dem flat-bean-Modul auf und zeigt den Inhalt der in der flat-web\target\flat-web.war gespeicherten MANIFEST.MF-Datei. Darin enthalten sind u.a.: Die Version 3.0-SNAPSHOT, die Mercurial-ChangeSet-ID und der Build-Timestamp.
Zusätzlich zum bisher angelegten Project im Flat-Layout soll dieses Projekt ein zweites Mal angelegt werden, aber diesmal im Hierachical-Layout. Da die Funktionalität dieselbe sein soll, kopieren wir die Sourcedateien vom Flat-Projekt:
cd /D D:\MeinWorkspace
copy flat-multiproj\pom.xml hierarchy-multiproj
xcopy flat-bean\src hierarchy-multiproj\hierarchy-bean\src\ /S
xcopy flat-web\src hierarchy-multiproj\hierarchy-web\src\ /S
cd hierarchy-multiproj
tree /F
Öffnen Sie die hierarchy-multiproj\pom.xml und ersetzen Sie den Abschnitt:
<artifactId>flat-multiproj</artifactId>
<version>3.0-SNAPSHOT</version>
<packaging>pom</packaging>
<name>flat-multiproj</name>
<modules>
<module>../flat-bean</module>
<module>../flat-web</module>
</modules>
<properties>
<hg-proj-path>Flatprojekt</hg-proj-path>
</properties>
durch:
<artifactId>hierarchy-multiproj</artifactId>
<version>4.0-SNAPSHOT</version>
<packaging>pom</packaging>
<name>hierarchy-multiproj</name>
<modules>
<module>hierarchy-bean</module>
<module>hierarchy-web</module>
</modules>
<properties>
<hg-proj-path>Hierarchyprojekt</hg-proj-path>
</properties>
Beachten Sie, dass bei den Untermodulen das vorangestellte "../" entfällt.
Erzeugen Sie im hierarchy-multiproj\hierarchy-bean-Verzeichnis die Projektkonfiguration: pom.xml
<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/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>de.meinefirma.meinprojekt</groupId>
<artifactId>hierarchy-multiproj</artifactId>
<version>4.0-SNAPSHOT</version>
</parent>
<artifactId>hierarchy-bean</artifactId>
<packaging>jar</packaging>
<name>hierarchy-bean</name>
<dependencies>
<dependency>
<groupId>de.meinefirma.meinprojekt</groupId>
<artifactId>commons</artifactId>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
</dependency>
</dependencies>
<scm>
<url>${hg-base-url}/${hg-proj-path}/${project.artifactId}</url>
<connection>scm:hg:${project.scm.url}</connection>
<developerConnection>scm:hg:${project.scm.url}</developerConnection>
</scm>
</project>
Beachten Sie, dass für das Parent-Modul kein <relativePath> angegeben wird.
Erzeugen Sie im hierarchy-multiproj\hierarchy-web-Verzeichnis die Projektkonfiguration: pom.xml
<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/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>de.meinefirma.meinprojekt</groupId>
<artifactId>hierarchy-multiproj</artifactId>
<version>4.0-SNAPSHOT</version>
</parent>
<artifactId>hierarchy-web</artifactId>
<packaging>war</packaging>
<name>hierarchy-web</name>
<build>
<finalName>${project.artifactId}</finalName>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>buildnumber-maven-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.mortbay.jetty</groupId>
<artifactId>maven-jetty-plugin</artifactId>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>de.meinefirma.meinprojekt</groupId>
<artifactId>hierarchy-bean</artifactId>
<version>${project.version}</version>
</dependency>
</dependencies>
<scm>
<url>${hg-base-url}/${hg-proj-path}/${project.artifactId}</url>
<connection>scm:hg:${project.scm.url}</connection>
<developerConnection>scm:hg:${project.scm.url}</developerConnection>
</scm>
</project>
Erzeugen Sie im hierarchy-multiproj-Verzeichnis die Batchdatei: run-webapp.bat
@echo. @pushd . cd ..\masterpom call mvn clean install @echo on if errorlevel 1 goto _Fehler @echo. cd ..\commons call mvn clean install @echo on if errorlevel 1 goto _Fehler @echo. cd ..\hierarchy-multiproj call mvn clean install @echo on if errorlevel 1 goto _Fehler cd hierarchy-web start cmd /C mvn jetty:run-war @ping -n 10 127.0.0.1 >nul start http://localhost:8080/hierarchy-web @echo. type target\work\webapp\META-INF\MANIFEST.MF :_Fehler @popd @echo.
Überprüfen Sie folgendermaßen, dass unter <connection> und <developerConnection> im <scm>-Abschnitt die korrekte Mercurial-hgweb-URI eingetragen ist:
cd /D D:\MeinWorkspace\hierarchy-multiproj
mvn help:effective-pom
<scm>
<connection>scm:hg:http://localhost:4419/hgweb/cgi-bin/meinprojekt.cgi/Hierarchyprojekt/hierarchy-multiproj</connection>
<developerConnection>scm:hg:http://localhost:4419/hgweb/cgi-bin/meinprojekt.cgi/Hierarchyprojekt/hierarchy-multiproj</developerConnection>
<url>http://localhost:4419/hgweb/cgi-bin/meinprojekt.cgi/Hierarchyprojekt/hierarchy-multiproj</url>
</scm>
cd /D D:\MeinWorkspace\hierarchy-multiproj\hierarchy-bean
mvn help:effective-pom
<scm>
<connection>scm:hg:http://localhost:4419/hgweb/cgi-bin/meinprojekt.cgi/Hierarchyprojekt/hierarchy-bean</connection>
<developerConnection>scm:hg:http://localhost:4419/hgweb/cgi-bin/meinprojekt.cgi/Hierarchyprojekt/hierarchy-bean</developerConnection>
<url>http://localhost:4419/hgweb/cgi-bin/meinprojekt.cgi/Hierarchyprojekt/hierarchy-bean</url>
</scm>
cd /D D:\MeinWorkspace\hierarchy-multiproj\hierarchy-web
mvn help:effective-pom
<scm>
<connection>scm:hg:http://localhost:4419/hgweb/cgi-bin/meinprojekt.cgi/Hierarchyprojekt/hierarchy-web</connection>
<developerConnection>scm:hg:http://localhost:4419/hgweb/cgi-bin/meinprojekt.cgi/Hierarchyprojekt/hierarchy-web</developerConnection>
<url>http://localhost:4419/hgweb/cgi-bin/meinprojekt.cgi/Hierarchyprojekt/hierarchy-web</url>
</scm>
Überprüfen Sie Ihre Projektverzeichnisse:
[\MeinWorkspace]
|- [commons]
| '- ...
|- [flat-bean]
| '- ...
|- [flat-multiproj]
| '- ...
|- [flat-web]
| '- ...
|- [hierarchy-multiproj]
| |- .hgignore
| |- pom.xml
| |- run-webapp.bat
| |- [.hg]
| | '- ...
| |- [hierarchy-bean]
| | |- pom.xml
| | '- [src]
| | |- [main]
| | | '- [java]
| | | '- [de]
| | | '- [meinefirma]
| | | '- [meinprojekt]
| | | '- MeineBean.java
| | '- [test]
| | '- [java]
| | '- [de]
| | '- [meinefirma]
| | '- [meinprojekt]
| | '- MeineBeanTest.java
| '- [hierarchy-web]
| |- pom.xml
| '- [src]
| '- [main]
| '- [webapp]
| |- index.jsp
| '- [WEB-INF]
| '- web.xml
'- [masterpom]
'- ...
Während beim Flat-Projekt die Untermodule flat-bean und flat-web parallel zum Parent-Modul flat-multiproj angeordnet sind, sind beim Hierarchy-Projekt die Untermodule hierarchy-bean und hierarchy-web unterhalb zum Parent-Modul hierarchy-multiproj angeordnet. Ein weiterer Unterschied ist, dass die drei Module des Flat-Projekts in drei jeweils eigenen Mercurial-Repositories gesichert sind, während die drei Module des Hierarchy-Projekts in einem einzigen Mercurial-Repositories gesichert sind.
Sichern Sie den Entwicklungsstand ins Mercurial-Repository:
cd /D D:\MeinWorkspace\hierarchy-multiproj
hg add
hg commit -m "add: 3 x pom.xml + MeineBean.java + MeineBeanTest.java + index.jsp + web.xml"
hg push
Testen Sie auch diese Webapp:
cd /D D:\MeinWorkspace\hierarchy-multiproj
run-webapp.bat
Die Module werden compiliert, der JUnit-Test wird ausgeführt, die Ergebnis-Artefakte werden ins lokale Maven-Repository gespeichert, der Jetty-Webserver wird gestartet und es wird wieder die oben erläuterte Ergebnis-Webseite angezeigt.
Mit dem Hierarchyprojekt funktioniert das Maven Release Plugin hervorragend, wie im Folgenden demonstriert wird:
Sehen Sie sich die für einen typischen Release-Prozess benötigten Schritte an.
Überprüfen Sie, dass Ihr hgweb-Webserver für Mercurial-Repositories aktiv ist, zum Beispiel durch Aufruf der hgweb-Webserver-URL,
beispielsweise
http://localhost:4419/hgweb/cgi-bin/meinprojekt.cgi.
Falls er noch nicht gestartet ist, starten Sie ihn, beispielsweise im Falle der oben beschriebenen Installation über:
cd /D D:\Tools\Tomcat-hgweb\bin
startup.bat
Falls Sie Ihr Projekt noch nicht aus dem hgweb-Webserver-Mercurial-Repository kopiert haben, clonen Sie es:
cd /D D:\MeinWorkspace
hg clone http://localhost:4419/hgweb/cgi-bin/meinprojekt.cgi/Hierarchyprojekt/hierarchy-multiproj
Die Änderung der Versionsbezeichnung zu einer Release-Version (ohne "-SNAPSHOT"), der Release-Build mit dieser Release-Version und die Erhöhung der Versionsnummer auf die nächsthöhere Entwicklerversion (wieder mit "-SNAPSHOT") erfolgen im Wesentlichen über die beiden Maven-Release-Plugin-Kommandos:
mvn --batch-mode release:prepare
mvn release:perform
Aber um die Vorgänge besser zu verstehen, werden im Folgenden noch weitere Kommandos ausgeführt. Bitte führen Sie vorher das zu Ihrem lokalen Maven-Repository-Verzeichnis passende set-Kommando aus:
set MEIN_PROJ_REPO=%USERPROFILE%\.m2\repository\de\meinefirma\meinprojekt
bzw.
set MEIN_PROJ_REPO=D:\Tools\Maven3-Repo\de\meinefirma\meinprojekt
Überprüfen Sie die Environmentvariable mit:
tree %MEIN_PROJ_REPO%
| Ausgeführte Kommandos | Version in den POMs im Workspace | Versionen in hg-Repositories (lokal + hgweb) | Versionen im lokalen Maven-Repository | Versionen im Distribution-Repository |
|---|---|---|---|---|
|
cd /D D:\MeinWorkspace\masterpom mvn clean install cd /D D:\MeinWorkspace\commons mvn clean install |
||||
|
cd /D D:\MeinWorkspace\hierarchy-multiproj type pom.xml tree %MEIN_PROJ_REPO% tree D:\MeinDistributionRepo mvn scm:status hg status |
4.0-SNAPSHOT | 4.0-SNAPSHOT | [eventuell 4.0-SNAPSHOT] |
[leer] |
|
mvn release:prepare -DdryRun=true mvn release:clean |
4.0-SNAPSHOT | 4.0-SNAPSHOT | [eventuell 4.0-SNAPSHOT] |
[leer] |
|
mvn --batch-mode release:prepare |
||||
|
type pom.xml hg log hg tags hg status |
4.1-SNAPSHOT | 4.0-SNAPSHOT 4.0 4.1-SNAPSHOT |
[eventuell 4.0-SNAPSHOT] |
[leer] |
|
mvn release:perform |
||||
|
tree %MEIN_PROJ_REPO% tree D:\MeinDistributionRepo hg status |
4.1-SNAPSHOT | 4.0-SNAPSHOT 4.0 4.1-SNAPSHOT |
[eventuell 4.0-SNAPSHOT] 4.0 |
4.0 |
Ergebnis:
Mit dem Flatprojekt funktioniert das Maven Release Plugin nicht zusammen mit Mercurial. Deshalb wird das Versions Maven Plugin eingesetzt:
Sehen Sie sich die für einen typischen Release-Prozess benötigten Schritte an.
Überprüfen Sie, dass Ihr hgweb-Webserver für Mercurial-Repositories aktiv ist, zum Beispiel durch Aufruf der hgweb-Webserver-URL,
beispielsweise
http://localhost:4419/hgweb/cgi-bin/meinprojekt.cgi.
Falls er noch nicht gestartet ist, starten Sie ihn, beispielsweise im Falle der oben beschriebenen Installation über:
cd /D D:\Tools\Tomcat-hgweb\bin
startup.bat
Falls Sie die Module des Flatprojekts noch nicht aus dem hgweb-Webserver-Mercurial-Repository kopiert haben, clonen Sie sie:
cd /D D:\MeinWorkspace
hg clone http://localhost:4419/hgweb/cgi-bin/meinprojekt.cgi/Flatprojekt/flat-multiproj
hg clone http://localhost:4419/hgweb/cgi-bin/meinprojekt.cgi/Flatprojekt/flat-bean
hg clone http://localhost:4419/hgweb/cgi-bin/meinprojekt.cgi/Flatprojekt/flat-web
Führen Sie wieder zuerst das zu Ihrem lokalen Maven-Repository-Verzeichnis passende set-Kommando aus, bevor Sie die weiteren Kommandos ausführen:
set MEIN_PROJ_REPO=%USERPROFILE%\.m2\repository\de\meinefirma\meinprojekt
bzw.
set MEIN_PROJ_REPO=D:\Tools\Maven3-Repo\de\meinefirma\meinprojekt
| Ausgeführte Kommandos | Version in den POMs im Workspace | Versionen in hg-Repositories (lokal + hgweb) | Versionen im lokalen Maven-Repository | Versionen im Distribution-Repository |
|---|---|---|---|---|
|
cd /D D:\MeinWorkspace\masterpom mvn clean install cd /D D:\MeinWorkspace\commons mvn clean install |
||||
|
cd /D D:\MeinWorkspace\flat-multiproj type pom.xml type ..\flat-bean\pom.xml tree %MEIN_PROJ_REPO% tree D:\MeinDistributionRepo |
3.0-SNAPSHOT | 3.0-SNAPSHOT | [eventuell 3.0-SNAPSHOT] |
[leer] |
|
mvn versions:set -DnewVersion=3.0 mvn versions:commit |
||||
|
type pom.xml type ..\flat-bean\pom.xml hg status hg diff |
3.0 | 3.0-SNAPSHOT | [eventuell 3.0-SNAPSHOT] |
[leer] |
|
cd ..\flat-bean hg commit -m "Release 3.0" hg tag TAG_FLAT_3.0 hg push cd ..\flat-web hg commit -m "Release 3.0" hg tag TAG_FLAT_3.0 hg push cd ..\flat-multiproj hg commit -m "Release 3.0" hg tag TAG_FLAT_3.0 hg push |
||||
|
hg log hg tags |
3.0 | 3.0-SNAPSHOT 3.0 |
[eventuell 3.0-SNAPSHOT] |
[leer] |
|
mvn deploy |
||||
|
tree %MEIN_PROJ_REPO% tree D:\MeinDistributionRepo |
3.0 | 3.0-SNAPSHOT 3.0 |
[eventuell 3.0-SNAPSHOT] 3.0 |
3.0 |
|
mvn versions:set -DnewVersion=3.1-SNAPSHOT mvn versions:commit |
||||
|
type pom.xml hg status hg diff |
3.1-SNAPSHOT | 3.0-SNAPSHOT 3.0 |
[eventuell 3.0-SNAPSHOT] 3.0 |
3.0 |
|
cd ..\flat-bean hg commit -m "3.1-SNAPSHOT" hg push cd ..\flat-web hg commit -m "3.1-SNAPSHOT" hg push cd ..\flat-multiproj hg commit -m "3.1-SNAPSHOT" hg push |
||||
|
hg log |
3.1-SNAPSHOT | 3.0-SNAPSHOT 3.0 3.1-SNAPSHOT |
[eventuell 3.0-SNAPSHOT] 3.0 |
3.0 |
Das Importieren in Eclipse von Maven-Multimodulprojekten aus einem Mercurial-Repository kann schon mal etwas knifflig sein. Beachten Sie dabei Folgendes:
Um auch etwas schwierigere Fälle abzudecken, wird ein etwas umständlicher aber dafür oft erfolgreicher Weg beschrieben:
Überprüfen Sie in Eclipse die M2Eclipse-Plugin-Settings unter:
"Window | Preferences | Maven | User Settings", möglicherweise so (passen Sie die Pfade an):
| User Settings File: | C:\Users\User\.m2\settings.xml |
| Local Repository: | C:\Users\User\.m2\repository |
Oder so:
| User Settings File: | D:\Tools\Maven3\conf\settings.xml |
| Local Repository: | D:\Tools\Maven3-Repo |
Importieren Sie in Eclipse zuerst über das MercurialEclipse-Plugin (passen Sie die URL an):
File | Import... | Mercurial | Clone Existing Mercurial Repository |
http://localhost:4419/hgweb/cgi-bin/meinprojekt.cgi/Hierarchyprojekt/hierarchy-multiproj
Anschließend löschen Sie das gerade geladene Projekt im Eclipse Package Explorer wieder, aber nur im Package Explorer und nicht auf der Festplatte (ausgeschaltet: "Delete project contents on disk").
Jetzt importieren Sie über das M2Eclipse-Plugin (passen Sie den Pfad an):
File | Import... | Maven | Existing Maven Projects | D:\MeinWorkspace
Anschließend generieren Sie die Eclipse-Projektkonfiguration:
Im Eclipse Package Explorer die Projekte markieren | rechte Maustaste | Maven | Update Project Configuration.
Kontrollieren Sie die Mercurial-Parameter:
Im Eclipse Package Explorer ein Projekt markieren | rechte Maustaste | Properties | Mercurial.
Sehen Sie sich die in Eclipse verwendeten Mercurial-Repositories an über:
Window | Show View | Mercurial Repositories.
Wenn Sie so nacheinander alle weiter oben erzeugten Projekte importieren, zeigt Eclipse:
Bitte beachten Sie:
Sehen Sie sich bei Problemen die weiteren Hinweise zum M2Eclipse-Plugin an.
Eine alternative Vorgehensweise wird beschrieben unter: Using maven-eclipse-plugin in multi-module projects with WTP.