Maven-Multimodulprojekte
sowie die Zusammenarbeit mit Eclipse und Mercurial

+ andere TechDocs
+ Maven
+ Maven-Multimodulprojekt
+ Eclipse
+ Mercurial (hg)
+


Maven-Multimodulprojekte (= MMP = Multiprojekte) stellen eine besondere Herausforderung dar: Je nach Maven-Multimodulprojekt-Struktur und -Konfiguration funktionieren nicht mehr alle Maven-Plugins, die Zusammenarbeit mit anderen Tools wie Eclipse kann schwierig sein und der Versionierungs- und Release-Prozess kann aufwändig sein.

Wichtig ist, bei Maven-Multimodulprojekten die Unterschiede zwischen dem "Flat Project Layout" und dem "Hierarchical Project Layout" zu kennen, und die Optionen zum Versionierungs- und Release-Prozess zu berücksichtigen.



Inhalt

  1. Maven-Multimodulprojekte: "Flat Project Layout" versus "Hierarchical Project Layout" versus "Mixed Project Layout"
  2. Beispiele für Maven-Multimodulprojekte im "Flat Project Layout" und im "Hierarchical Project Layout"
    Vorbemerkung, Anlage der Module Erzeugung der Master-POM und der Basismodule, Flat Project Layout Hierarchical Project Layout,
  3. Versionierung und Release-Build mit dem "Maven Release Plugin", dem "Versions Maven Plugin" und dem "Maven SCM Plugin"
    Vorbereitung, Hierarchisches Projekt Flat-Projekt, Flat-Projekt: Release per Batch,
  4. Maven-Multimodulprojekt aus einem Mercurial-Repository in Eclipse importieren


Maven-Multimodulprojekte: "Flat Project Layout" versus "Hierarchical Project Layout" versus "Mixed Project Layout"


Weiter unten finden Sie konkrete Beispiele und Erläuterungen für Projekte im "Flat Project Layout" und im "Hierarchical Project Layout". Vorab folgt eine Gegenüberstellung einiger wichtiger Unterschiede:

  Flat Project Layout Hierarchical Project Layout Mixed Project Layout
Optimal für: Optimal für Eclipse
(aber einige Maven-Plugins funktionieren nicht)
Optimal für Maven
(aber etwas umständliche Handhabung in Eclipse)
Funktioniert nur mit bestimmten VCS/SCM-Konstellationen
Besondere Eigenschaft Parallele Verzeichnisstruktur Hierarchische Verzeichnisstruktur Aufteilung der Parent-POM auf zwei POMs:
"Multiprojekt-Root-POM" im Workspace-Root-Verzeichnis und
"Master-Parent-POM" im parallelen Parent-Unterverzeichnis
Verzeichnisstruktur und POMs
MeinWorkspace
 |- Parent-Modul
 |   '- pom.xml (Parent-POM)
 |- Untermodul-1
 |   |- pom.xml (Untermodul-1-POM)
 |   '- src ...
 '- Untermodul-2
     |- pom.xml (Untermodul-2-POM)
     '- src ...
MeinWorkspace
 '- Parent-Modul
     |- pom.xml (Parent-POM)
     |- Untermodul-1
     |   |- pom.xml (Untermodul-1-POM)
     |   '- src ...
     '- Untermodul-2
         |- pom.xml (Untermodul-2-POM)
         '- src ...
MeinWorkspace
 |- pom.xml (Multiprojekt-Root-POM)
 |- Parent-Modul
 |   '- pom.xml (Master-Parent-POM)
 |- Untermodul-1
 |   |- pom.xml (Untermodul-1-POM)
 |   '- src ...
 '- Untermodul-2
     |- pom.xml (Untermodul-2-POM)
     '- src ...
<modules>-Sektion in der
Parent-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>
Zwei Parent-POMs:
a) "Multiprojekt-Root-POM":
Mit <modules>-Sektion wie beim Hierarchical Project Layout, zusätzlich mit <parent>-Sektion.
b) "Master-Parent-POM":
Ohne <modules>-Sektion.
<parent>-Sektion in den
Untermodul-pom.xml
  <parent>
    <artifactId>Parent-Modul</artifactId>
    <relativePath>
      ../Parent-Modul/pom.xml
    </relativePath>
  </parent>
  <artifactId>Untermodul...</artifactId>
  <packaging>jar</packaging>
  <parent>
    <artifactId>Parent-Modul</artifactId>
  </parent>
  <artifactId>Untermodul...</artifactId>
  <packaging>jar</packaging>
Wie beim Flat Project Layout,
in der <parent>-Sektion wird auf die "Master-Parent-POM" verwiesen,
kein Verweis auf die "Multiprojekt-Root-POM"
Lauffähiges Beispiel Beispiel Flat Project Layout Beispiel Hierarchical Project Layout Beispiel bei Branko Juric
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; Untermodule können einzeln aus- und eingecheckt werden Pro Maven-Multimodulprojekt (inkl. aller Unterprojekte) wird nur ein einziges DVCS-Repository verwendet; es werden normalerweise alle Module des Multimodulprojekts ausgecheckt Kann knifflig sein, je nach VCS/SCM kann es Probleme beim clone zum und commit aus dem Workspace-Root-Verzeichnis geben
Import in Eclipse Problemlos, es muss nicht unbedingt ein Plugin verwendet werden Nur mit dem M2Eclipse-Plugin möglich Wie beim Flat Project Layout
Probleme wegen nicht eindeutiger Unterprojektnamen
(z.B. in Eclipse)
Keine Probleme, da Unterprojektnamen zwangsläufig eindeutig sind Unterprojektnamen sind oft nicht eindeutig über verschiedene Maven-Multimodulprojekte: Dann können nicht mehrere Maven-Multimodulprojekte gleichzeitig in Eclipse importiert werden Unterprojektnamen sind zwar zwangsläufig eindeutig, aber mehrere Maven-Multimodulprojekte gleichzeitig in einem Workspace-Verzeichnis ist aufwändig, da es nur eine Root-POM gibt
Maven Release Plugin Funktioniert nicht (abhängig vom VCS/SCM), siehe MRELEASE-261 Funktioniert Kann knifflig sein, je nach VCS/SCM kann es Probleme beim "mvn release:perform"-Kommando geben, weil das Auschecken der Untermodule nicht gelingt
Versionierung und Release-Build etwas aufwändiger einfacher wenn es funktioniert, ist die Ausführung einfacher


Beispiele für Maven-Multimodulprojekte im "Flat Project Layout" und im "Hierarchical Project Layout"

Vorbemerkung

Im Folgenden werden beispielhaft mehrere Maven-Projekte angelegt, um mögliche Vorgehensweisen und die Unterschiede zu erläutern. Dabei wird als Versionskontrollsystem Mercurial (hg) verwendet, aber sie sind leicht übertragbar auf andere VCS/SCM-Systeme.

Die Beispiele wurden unter Windows 7 64 Bit getestet mit JDK 8, Maven 3.3.1, Mercurial 2.0 (hg) und hgweb-Webserver 2.0 für Mercurial-Repositories.

Anlage der Module im hgweb-Webserver für Mercurial-Repositories

  1. 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):

    set CATALINA_HOME=D:\Tools\Tomcat-hgweb

    call %CATALINA_HOME%\bin\startup.bat

    start http://localhost:4419/hgweb/cgi-bin/meinprojekt.cgi

  2. Folgende Mercurial-Repositories-Struktur soll eingerichtet werden: Mercurial-Repos-Flat-vs-Hierarchy

    Die beiden Basismodule "masterpom" und "commons" sind stellvertretend für "externe Module", welche von den eigentlichen Projekten "Flat" und "Hierarchy" referenziert werden.

  3. Zum besseren Verständnis sollten die Schritte wie im Folgenden beschrieben durchlaufen werden. Sie können auch abkürzen, indem Sie die Projektdateien downloaden.

  4. Verzweigen Sie auf dem hgweb-Server in das Verzeichnis für Mercurial-Repositories (z.B. D:\Tools\hgweb-repos) und erzeugen Sie dort folgende Batchdatei zum Anlegen eines neuen Mercurial-Repository im hgweb-Mercurial-Repositories-Verzeichnis: run-hg-init-neuesModul.bat

    @echo Batchdatei zum Anlegen eines neuen Mercurial-Repository im hgweb-Mercurial-Repositories-Verzeichnis
    @echo hgweb-repos-Root:      %CD%
    @echo hgweb-Repo-Gruppe:     %1
    @echo Name des neuen Moduls: %2
    @echo Modul-Beschreibung:    %~3
    @if "%~3" == "" goto _Fehler
    @if exist %1\%2 goto _Fehler
    @if not exist %1 md %1
    cd %1
    call hg init %2
    @echo on
    echo [web] > %2\.hg\hgrc
    echo description = %~3 >> %2\.hg\hgrc
    echo contact = ich ^<Meine@Email.Adresse^> >> %2\.hg\hgrc
    cd ..
    type %1\%2\.hg\hgrc
    
  5. 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

    call run-hg-init-neuesModul.bat Basisprojekt masterpom "Zentrale Maven-Master-POM"

    call run-hg-init-neuesModul.bat Basisprojekt commons "Zentrale Common-Utilities"

    call run-hg-init-neuesModul.bat Flatprojekt flat-multiproj "Flat-Multiprojekt-Parent-POM"

    call run-hg-init-neuesModul.bat Flatprojekt flat-bean "Flat-Multiprojekt-Bean-Modul"

    call run-hg-init-neuesModul.bat Flatprojekt flat-web "Flat-Multiprojekt-Web-Modul"

    call run-hg-init-neuesModul.bat Hierarchyprojekt hierarchy-multiproj "Hierarchisches Multiprojekt"

    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:

    Mercurial-Repos-Flat-vs-Hierarchy-hgweb.png

Clonen der Repositories ins Arbeitsverzeichnis und Erzeugung der Master-POM und der Basismodule

  1. 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

  2. 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

  3. 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>
        <scm.project.url>${hg-base-url}/${hg-proj-path}/${project.artifactId}</scm.project.url>
        <scm.project.connection>scm:hg:${scm.project.url}</scm.project.connection>
        <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>3.3</version>
              <configuration>
                <source>1.7</source>
                <target>1.7</target>
              </configuration>
            </plugin>
            <plugin>
              <groupId>org.apache.maven.plugins</groupId>
              <artifactId>maven-release-plugin</artifactId>
              <version>2.5.1</version>
            </plugin>
            <plugin>
              <groupId>org.apache.maven.plugins</groupId>
              <artifactId>maven-scm-plugin</artifactId>
              <version>1.9.4</version>
              <configuration>
                <tag>Tag-${project.version}</tag>
              </configuration>
            </plugin>
            <plugin>
              <groupId>org.apache.maven.plugins</groupId>
              <artifactId>maven-war-plugin</artifactId>
              <version>2.6</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.3</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>2.1</version>
            </plugin>
            <plugin>
              <groupId>org.eclipse.jetty</groupId>
              <artifactId>jetty-maven-plugin</artifactId>
              <version>9.2.10.v20150310</version>
              <configuration>
                <webAppConfig>
                  <contextPath>/${project.artifactId}</contextPath>
                </webAppConfig>
              </configuration>
            </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.12</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>${scm.project.url}</url>
        <connection>${scm.project.connection}</connection>
        <developerConnection>${scm.project.connection}</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).

  4. 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>${scm.project.url}</url>
        <connection>${scm.project.connection}</connection>
        <developerConnection>${scm.project.connection}</developerConnection>
      </scm>
    </project>
    
  5. 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;
       }
    }
    
  6. Überprüfen Sie folgendermaßen, dass <connection> und <developerConnection> im <scm>-Abschnitt zu korrekten Mercurial-hgweb-URIs aufgelöst wird:

    cd /D D:\MeinWorkspace\masterpom

    mvn help:effective-pom

    mvn help:effective-pom | find /I "connection"

        <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>
    

    cd /D D:\MeinWorkspace\commons

    mvn help:effective-pom | find /I "connection"

        <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>
    

Flat Project Layout

  1. 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>${scm.project.url}</url>
        <connection>${scm.project.connection}</connection>
        <developerConnection>${scm.project.connection}</developerConnection>
      </scm>
    </project>
    
  2. 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>
    
  3. 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.eclipse.jetty</groupId>
            <artifactId>jetty-maven-plugin</artifactId>
          </plugin>
        </plugins>
      </build>
      <dependencies>
        <dependency>
          <groupId>de.meinefirma.meinprojekt</groupId>
          <artifactId>flat-bean</artifactId>
          <version>${project.version}</version>
        </dependency>
      </dependencies>
    </project>
    
  4. 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 );
       }
    }
    
  5. 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 ) );
       }
    }
    
  6. 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>
    
  7. 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>
    
  8. 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\flat-web\META-INF\MANIFEST.MF
    :_Fehler
    @popd
    @echo.
    
  9. Überprüfen Sie folgendermaßen, dass <connection> und <developerConnection> im <scm>-Abschnitt zu korrekten Mercurial-hgweb-URIs aufgelöst wird:

    cd /D D:\MeinWorkspace\flat-multiproj

    mvn help:evaluate -Dexpression=pom.scm.connection | findstr /V [

    scm:hg:http://localhost:4419/hgweb/cgi-bin/meinprojekt.cgi/Flatprojekt/flat-multiproj
    

    cd /D D:\MeinWorkspace\flat-bean

    mvn help:evaluate -Dexpression=pom.scm.connection | findstr /V [

    scm:hg:http://localhost:4419/hgweb/cgi-bin/meinprojekt.cgi/Flatprojekt/flat-bean
    

    cd /D D:\MeinWorkspace\flat-web

    mvn help:evaluate -Dexpression=pom.scm.connection | findstr /V [

    scm:hg:http://localhost:4419/hgweb/cgi-bin/meinprojekt.cgi/Flatprojekt/flat-web
    
  10. Ü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, wie auch das folgende Kommando zeigt:

    cd /D D:\MeinWorkspace

    dir pom.xml /B /S

    D:\MeinWorkspace\commons\pom.xml
    D:\MeinWorkspace\flat-bean\pom.xml
    D:\MeinWorkspace\flat-multiproj\pom.xml
    D:\MeinWorkspace\flat-web\pom.xml
    D:\MeinWorkspace\masterpom\pom.xml
    
  11. 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 ..

  12. 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.

Hierarchical Project Layout

  1. Zusätzlich zum bisher angelegten Project im Flat-Layout wird dieses Projekt ein zweites Mal angelegt, aber diesmal im Hierarchical-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

  2. Ö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.

  3. 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>${scm.project.url}</url>
        <connection>${scm.project.connection}</connection>
        <developerConnection>${scm.project.connection}</developerConnection>
      </scm>
    </project>
    

    Beachten Sie, dass für das Parent-Modul kein <relativePath> angegeben wird.

  4. 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.eclipse.jetty</groupId>
            <artifactId>jetty-maven-plugin</artifactId>
          </plugin>
        </plugins>
      </build>
      <dependencies>
        <dependency>
          <groupId>de.meinefirma.meinprojekt</groupId>
          <artifactId>hierarchy-bean</artifactId>
          <version>${project.version}</version>
        </dependency>
      </dependencies>
      <scm>
        <url>${scm.project.url}</url>
        <connection>${scm.project.connection}</connection>
        <developerConnection>${scm.project.connection}</developerConnection>
      </scm>
    </project>
    
  5. 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\hierarchy-web\META-INF\MANIFEST.MF
    :_Fehler
    @popd
    @echo.
    
  6. Überprüfen Sie folgendermaßen, dass <connection> und <developerConnection> im <scm>-Abschnitt zu korrekten Mercurial-hgweb-URIs aufgelöst wird:

    cd /D D:\MeinWorkspace\hierarchy-multiproj

    mvn help:evaluate -Dexpression=pom.scm.connection | findstr /V [

    scm:hg:http://localhost:4419/hgweb/cgi-bin/meinprojekt.cgi/Hierarchyprojekt/hierarchy-multiproj
    

    cd /D D:\MeinWorkspace\hierarchy-multiproj\hierarchy-bean

    mvn help:evaluate -Dexpression=pom.scm.connection | findstr /V [

    scm:hg:http://localhost:4419/hgweb/cgi-bin/meinprojekt.cgi/Hierarchyprojekt/hierarchy-bean
    

    cd /D D:\MeinWorkspace\hierarchy-multiproj\hierarchy-web

    mvn help:evaluate -Dexpression=pom.scm.connection | findstr /V [

    scm:hg:http://localhost:4419/hgweb/cgi-bin/meinprojekt.cgi/Hierarchyprojekt/hierarchy-web
    
  7. Überprüfen Sie Ihre Projektverzeichnisse:

    cd /D D:\MeinWorkspace\hierarchy-multiproj

    tree /F

    [\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. Sehen Sie sich die Verzeichnisse der pom.xml-Dateien an:

    cd /D D:\MeinWorkspace

    dir pom.xml /B /S

    D:\MeinWorkspace\commons\pom.xml
    D:\MeinWorkspace\flat-bean\pom.xml
    D:\MeinWorkspace\flat-multiproj\pom.xml
    D:\MeinWorkspace\flat-web\pom.xml
    D:\MeinWorkspace\hierarchy-multiproj\pom.xml
    D:\MeinWorkspace\hierarchy-multiproj\hierarchy-bean\pom.xml
    D:\MeinWorkspace\hierarchy-multiproj\hierarchy-web\pom.xml
    D:\MeinWorkspace\masterpom\pom.xml
    
  8. 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

  9. 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.



Versionierung und Release-Build mit dem "Maven Release Plugin", dem "Versions Maven Plugin" und dem "Maven SCM Plugin"

Vorbereitung

  1. Sehen Sie sich die für einen typischen Release-Prozess benötigten Schritte an.

  2. Sehen Sie sich die Dokus zu den drei Maven-Plugins Maven SCM Plugin, Maven Release Plugin und Versions Maven Plugin an.

  3. Voraussetzung für die folgenden Beispiele sind die beiden in den letzten Beispielen angelegten Projekte "Flat Project Layout" und "Hierarchical Project Layout". Falls Sie abkürzen wollen, können Sie die Projektdateien downloaden.

  4. Ü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:

    set CATALINA_HOME=D:\Tools\Tomcat-hgweb

    call %CATALINA_HOME%\bin\startup.bat

  5. Bitte führen Sie zuerst 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%

    Falls Sie bereits alle Projekte vollständig gebaut haben, erhalten Sie:

    ...\de\meinefirma\meinprojekt
    |- commons
    |  '- 2.0
    |- flat-bean
    |  '- 3.0-SNAPSHOT
    |- flat-multiproj
    |  '- 3.0-SNAPSHOT
    |- flat-web
    |  '- 3.0-SNAPSHOT
    |- hierarchy-bean
    |  '- 4.0-SNAPSHOT
    |- hierarchy-multiproj
    |  '- 4.0-SNAPSHOT
    |- hierarchy-web
    |  '- 4.0-SNAPSHOT
    '- masterpom
       '- 1.0
    

    Um die Übersichtlichkeit zu erhöhen, sollten Sie die bisherigen Artefakte löschen:

    rd /S /Q %MEIN_PROJ_REPO%

  6. Erstellen Sie das leere Distributionsverzeichnis (so wie in der masterpom-pom.xml unter <distributionManagement> deklariert, als Test-Ersatz für einen Maven-Repository-Manager) und setzen Sie eine entsprechende Environmentvariable:

    set MEIN_DISTRIBUTION_REPO=D:\MeinDistributionRepo

    md %MEIN_DISTRIBUTION_REPO%

  7. Bauen Sie die beiden verwendeten Basisprojekte:

    cd /D D:\MeinWorkspace\masterpom

    mvn clean install

    cd /D D:\MeinWorkspace\commons

    mvn clean install

    tree %MEIN_PROJ_REPO%

  8. Falls Sie bei den folgenden Schritten auf diese Fehlermeldung stoßen:

    [ERROR] Failed to execute goal org.apache.maven.plugins:maven-release-plugin:2.5.1:prepare (default-cli) on project ...: Failed to invoke Maven build. Error configuring command-line. Reason: Maven executable not found at: ...\bin\mvn.bat

    Dann prüfen Sie, ob sich in Ihrem Maven-bin-Verzeichnis eine mvn.bat-Datei befindet. Falls nicht, führen Sie aus:

    cd /D %M2_HOME%\bin

    dir mvn.*

    if not exist mvn.bat copy mvn.cmd mvn.bat

  9. Falls Sie das Versionskontrollsystem CVS verwenden und Maven-SCM-Kommandos Probleme mit der Authentifizierung haben, z.B. mit einer Fehlermeldung ähnlich zu:

    [ERROR] Didn't find password ...
    org.netbeans.lib.cvsclient.connection.AuthenticationException: Wrong Password
    org.apache.maven.scm.ScmException: password is required

    Dann überprüfen Sie Ihre .cvspass-Datei.
    Eventuell hilft auch: -Dmaven.scm.provider.cvs.implementation=cvs_native.

Hierarchisches Projekt

Mit dem Hierarchyprojekt funktioniert das Maven Release Plugin hervorragend, wie im Folgenden demonstriert wird. Falls Sie nicht Mercurial verwenden, sondern ein anderes VCS/SCM-System, müssen Sie lediglich die "hg ..."-Kommandos durch entsprechende "mvn scm:..."-Kommandos ersetzen.

  1. Führen Sie die obigen Vorbereitungen durch, inklusive des Setzens der MEIN_PROJ_REPO- und MEIN_DISTRIBUTION_REPO-Umgebungsvariablen.

  2. 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

  3. 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.

  4. Führen Sie folgende Kommandos aus und beobachten Sie die Ergebnisse:

    Ausgeführte KommandosVersion in den POMs im WorkspaceVersionen in hg-Repositories (lokal + hgweb) Versionen im lokalen Maven-RepositoryVersionen im
    Distribution-Repository

    cd /D D:\MeinWorkspace\hierarchy-multiproj

    type pom.xml

    tree %MEIN_PROJ_REPO%

    tree %MEIN_DISTRIBUTION_REPO%

    mvn scm:status

    hg status

    4.0-SNAPSHOT 4.0-SNAPSHOT [eventuell
    4.0-SNAPSHOT]
    [leer]

    mvn release:prepare -DdryRun=true

    Bestätigen Sie 7 mal die Vorgabewerte oder Ihre Eingaben.

    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 %MEIN_DISTRIBUTION_REPO%

    hg status

    4.1-SNAPSHOT 4.0-SNAPSHOT
    4.0
    4.1-SNAPSHOT
    [eventuell
    4.0-SNAPSHOT]
    4.0
    4.0
  5. Ergebnis:

Flat-Projekt

Mit dem Flatprojekt funktioniert das Maven Release Plugin nicht zusammen mit Mercurial. Deshalb wird das Versions Maven Plugin eingesetzt. Falls Sie nicht Mercurial verwenden, sondern ein anderes VCS/SCM-System, müssen Sie auch hier wieder lediglich die "hg ..."-Kommandos durch entsprechende "mvn scm:..."-Kommandos ersetzen (siehe hierzu auch das anschließend folgende Beispiel).

  1. Führen Sie die obigen Vorbereitungen durch, inklusive des Setzens der MEIN_PROJ_REPO- und MEIN_DISTRIBUTION_REPO-Umgebungsvariablen.

  2. 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

  3. Führen Sie folgende Kommandos aus und beobachten Sie die Ergebnisse:

    Ausgeführte KommandosVersion in den POMs im WorkspaceVersionen in hg-Repositories (lokal + hgweb) Versionen im lokalen Maven-RepositoryVersionen im
    Distribution-Repository

    cd /D D:\MeinWorkspace\flat-multiproj

    type pom.xml

    type ..\flat-bean\pom.xml

    tree %MEIN_PROJ_REPO%

    tree %MEIN_DISTRIBUTION_REPO%

    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 %MEIN_DISTRIBUTION_REPO%

    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

Flat-Projekt: Release per Batch

Wie das letzte Beispiel zeigt, sind anders als beim "Hierarchical Project Layout" beim "Flat Project Layout" mehr einzelne Schritte notwendig. Insbesondere müssen das Einchecken und das Tag-Setzen in jedem Untermodulverzeichnis einzeln erfolgen. Hierzu wird im Folgenden eine unter Windows lauffähige Batchdatei vorgestellt, die das in einem einzigen Aufruf bewerkstelligt.

Diese Batchdatei ist nicht auf Mercurial festgelegt, sondern für beliebige VCS/SCM-Systeme ausgelegt. Voraussetzung sind korrekte an Ihr VCS/SCM-System angepasste SCM-Konfigurationseinträge in den <SCM>-Rubriken in der masterpom-pom.xml und den Modulen.

Die Batchdatei funktioniert auch dann, wenn es außer den zum Multimodul-Projekt gehörenden Modulverzeichnissen noch weitere Verzeichnisse gibt, die nicht modifiziert werden dürfen. Hierzu wird geprüft, ob die Module die artifactId der Parent-POM entweder enthalten oder darauf verweisen.

  1. Erstellen Sie im Parent-Verzeichnis, also im Flatprojekt-Beispiel in \MeinWorkspace\flat-multiproj, die Batchdatei: run-createRelease.bat

    cls
    @title %~n0
    @pushd .
    @echo.
    @echo ----------------------------------------------------------------------------------------
    @echo Batchdatei fuer Release-Prozess fuer Maven-Multimodulprojekte im "Flat Project Layout".
    @echo Folgende Schritte werden ausgefuehrt:
    @echo 1. Setzen der neuen Release-Versionsnummer
    @echo 2. Commit ins VCS/SCM
    @echo 3. Setzen eines Tags im VCS/SCM
    @echo 4. Erstellen und deployen der Ergebnis-Artefakte
    @echo 5. Setzen der neuen Entwicklungs-Snapshot-Versionsnummer
    @echo 6. Commit ins VCS/SCM
    @echo ----------------------------------------------------------------------------------------
    @echo Diese Batchdatei muss im Parent-Modul-Verzeichnis ausgefuehrt werden.
    @echo Als Parameter muessen uebergeben werden:
    @echo 1. Parameter: die neue Release-Versionsnummer (ohne -SNAPSHOT),     z.B.: 1.2.3
    @echo 2. Parameter: die neue Entwicklungs-Versionsnummer (mit -SNAPSHOT), z.B.: 1.2.4-SNAPSHOT
    @echo ----------------------------------------------------------------------------------------
    @echo.
    @echo.
    @echo -------- Parameter ueberpruefen:
    @set _startDir=%CD%
    @if "%2" == "" goto _Fehler
    @for /f "delims=" %%a in ('call mvn help:evaluate -Dexpression^=pom.artifactId ^| findstr /V [') do @set _mmp_afid=%%a
    @set _mmp_afid_tag=^^^<artifactId^^^>%_mmp_afid%^^^</artifactId^^^>
    @echo Neue Release-Versionsnummer:      %1
    @echo Neue Entwicklungs-Versionsnummer: %2
    @echo Startverzeichnis:                 %_startDir%
    @echo MMP-artifactId:                   %_mmp_afid%
    @echo MMP-Tag-Suchstring:               %_mmp_afid_tag%
    @echo.
    call mvn scm:validate
    @if errorlevel 1 goto _Fehler
    @echo.
    @echo.
    @echo -------- Setzen der neuen Release-Versionsnummer %1 fuer alle Module gemeinsam
    @echo.
    call :setzeVersion %1
    @if errorlevel 1 goto _Fehler
    @echo.
    @echo.
    @echo -------- Die Module mit Version %1 einzeln einchecken und taggen
    @echo.
    cd ..
    call :checkinAndTag %1 tag
    @if errorlevel 1 goto _Fehler
    cd %_startDir%
    @echo.
    @echo.
    @echo -------- Erstellen und deployen der Ergebnis-Artefakte mit Version %1
    @echo.
    call mvn clean deploy
    @if errorlevel 1 goto _Fehler
    @echo.
    @echo.
    @echo -------- Setzen der neuen Entwicklungs-Versionsnummer %2 fuer alle Module gemeinsam
    @echo.
    call :setzeVersion %2
    @if errorlevel 1 goto _Fehler
    @echo.
    @echo.
    @echo -------- Die Module mit Version %2 einzeln einchecken (ohne Tag)
    @echo.
    cd ..
    call :checkinAndTag %2
    @if errorlevel 1 goto _Fehler
    cd %_startDir%
    @echo.
    @echo.
    @echo -------- changelog und status
    @echo.
    call mvn scm:changelog | findstr /V [
    @echo.
    call mvn scm:status | findstr /V [
    @echo.
    @echo ---------------------------
    @echo ++++    Erfolgreich    ++++
    @echo ---------------------------
    @echo 
    @goto _fertig
    
    :setzeVersion
    @echo.
    call mvn help:evaluate -Dexpression=pom.version | findstr /V [
    call mvn versions:set -DnewVersion=%1
    @if errorlevel 1 exit /B 1
    call mvn versions:commit
    @if errorlevel 1 exit /B 1
    @echo.
    call mvn help:evaluate -Dexpression=pom.version | findstr /V [
    @echo.
    exit /B 0
    
    :checkinAndTag
    @echo off
    @echo.
    FOR /F %%i in ('dir /B /A:D') DO (
      @echo.
      cd %%i
      @echo Aktuelles Unterverzeichnis: %%i
      if not exist pom.xml (
        @echo --- Info: %%i enthaelt keine 'pom.xml', deshalb keine Aktion.
      ) else (
        findstr %_mmp_afid_tag% pom.xml > nul
        if errorlevel 1 (
          @echo --- Info: Die pom.xml in %%i enthaelt nicht den String %_mmp_afid_tag%, deshalb keine Aktion.
        ) else (
          @echo.
          @echo --- Info: %%i wird eingecheckt
          call mvn scm:checkin -Dmessage="Version %1"
          @if errorlevel 1 exit /B 1
          if not "%2" == "" (
            @echo --- Info: %%i erhaelt ein Tag
            call mvn scm:tag
            @if errorlevel 1 exit /B 1
          )
        )
      )
      @echo off
      cd ..
    )
    exit /B 0
    
    :_Fehler
    @echo.
    @echo ######################
    @echo ####    FEHLER    ####
    @echo ######################
    @echo 
    pause
    
    :_fertig
    cd %_startDir%
    @popd
    @title %~dp0
    
  2. Führen Sie die obigen Vorbereitungen durch, inklusive des Setzens der MEIN_PROJ_REPO- und MEIN_DISTRIBUTION_REPO-Umgebungsvariablen (die Umgebungsvariablen werden nicht für die Batchdatei benötigt, aber im folgenden Beispiel für die zusätzlichen Test-Kommandos).

  3. Führen Sie folgende Kommandos aus und beobachten Sie die Ergebnisse:

    Ausgeführte KommandosVersion in den POMs im WorkspaceVersionen in hg-Repositories (lokal + hgweb) Versionen im lokalen Maven-RepositoryVersionen im
    Distribution-Repository

    Überprüfen Sie die Ausgangssituation:

    cd /D D:\MeinWorkspace\flat-multiproj

    type pom.xml

    type ..\flat-bean\pom.xml

    tree %MEIN_PROJ_REPO%

    tree %MEIN_DISTRIBUTION_REPO%

    3.1-SNAPSHOT 3.0-SNAPSHOT
    3.0
    3.1-SNAPSHOT
    3.0 3.0

    cd /D D:\MeinWorkspace\flat-multiproj

    run-createRelease.bat 3.5 3.6-SNAPSHOT

           

    tree %MEIN_PROJ_REPO%

    tree %MEIN_DISTRIBUTION_REPO%

    type pom.xml

    hg log

    hg tags

    (Führen Sie die letzten drei Kommandos auch
    in den anderen Projektunterverzeichnissen aus)

    3.6-SNAPSHOT 3.0-SNAPSHOT
    3.0
    3.1-SNAPSHOT
    3.5
    3.6-SNAPSHOT
    3.0
    3.5
    3.0
    3.5


Maven-Multimodulprojekt aus einem Mercurial-Repository in Eclipse importieren

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:

  1. Ü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
  2. 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

  3. 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").

  4. Jetzt importieren Sie über das M2Eclipse-Plugin (passen Sie den Pfad an):
    File | Import... | Maven | Existing Maven Projects | D:\MeinWorkspace

  5. Anschließend generieren Sie die Eclipse-Projektkonfiguration:
    Im Eclipse Package Explorer die Projekte markieren | rechte Maustaste | Maven | Update Project Configuration.

  6. Kontrollieren Sie die Mercurial-Parameter:
    Im Eclipse Package Explorer ein Projekt markieren | rechte Maustaste | Properties | Mercurial.

  7. Sehen Sie sich die in Eclipse verwendeten Mercurial-Repositories an über:
    Window | Show View | Mercurial Repositories.

  8. Wenn Sie so nacheinander alle weiter oben erzeugten Projekte importieren, zeigt Eclipse:

    Mercurial-Repos-Flat-vs-Hierarchy-Eclipse.png

    Bitte beachten Sie:

  9. 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.





Weitere Themen: andere TechDocs | Maven | Maven-Multimodulprojekt | Eclipse | Mercurial (hg)
© 2012 Torsten Horn, Aachen