Maven - Eigene Projekte als Dependecy

Hallo,

ich habe in einem Projekt folgende Strucktur:

|-Gundprojekt
|-Projekt2
|-Projekt3
|-Projekt4

Wie kann ich den Projekten 2 bis 4 das Grundprojekt als Maven Dependency zuordnen?
Und wie bau ich für die Projekte 2 - 4 eigenständige Lauffähige jars, die das Grundprojekt und weitere Dependencys (z.B. log4j) beinhalten?

Ich hoffe ihr könnt mir weiterhelfen oder zumindest auf die richtige Spur bringen.

Danke!

PS: Ich war mir nicht siher ob das Thema hier richtig ist oder ob es zu APIs & Frameworks gehört. Ggf. bitte verschieben.

Als Dependency.

Also hast du verschiedene Projekte oder ein Projekt mit verschiedenen Modulen?

Wenn letzteres, kannst du einfach das Grund- oder Elternprojekt als definieren. Heißt also im Kopfbereich der pom.xml
folgendes:

[XML]
4.0.0

<groupId>de.beispiel</groupId>
<artifactId>beispiel-parent</artifactId>
<packaging>pom</packaging>
<version>1.0</version>
<name>Beispiel Parent Project</name>

<modules>
    <module>beispiel-child1</module>
    <module>beispiel-child2</module>
</modules>

[/XML]

Die Namen kannst du dann entsprechend den Modulen anpassen.
Bei den anderen Modulen kannst du dann das Parent-Modul angeben:

[XML]

de.beispiel
beispiel-parent
1.0

beispiel-child1
jar

<name>Beispiel Child 1 Project</name>

[/XML]

Gerade dazu noch was gefunden (da hatte ich selbst letztens nachgeschaut): TheNEXUS | A Community Project


Im ersten Fall (auch wenn ich nicht sicher bin), geht es wohl nur über das Anlegen eines lokalen Repositorys (oder Upload der Projekte in ein Remote Repository).

EDIT> Etwas zu langsam - aber es sieht auf den ersten Blick aus, als wäre das nicht GANZ falsch, was beruhigend ist :smiley: <EDIT

Ich bin kein Maven-Experte…
… kann aber mal sagen, wie ich das in einer ähnlichen Situation gemacht hatte.

Aber: Warte erstmal, ob nicht jemand anderes aufschreit, und sagt, dass das kompletter Blödfug ist…

Ich hatte für das „Gesamtprojekt“ (Also Grundprojekt+Projekt1…n) eine Parent-POM erstellt, in der das (lokale) Repository angegeben ist, wo der ganze Kram hindeployt werden soll (falls man das nicht alles ohnehin gleich in die Maven Central packt…)

In dieser Parent-POM stand dann ein lokales Verzeichnis als Repository
[xml]

4.0.0

<groupId>my-group</groupId>
<artifactId>my-artifact-parent</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>pom</packaging>

<properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>

<repositories>
    <repository>
        <id>my-group.local</id>
        <name>my-group.local</name>
        <url>file:${project.basedir}/../../Repo</url>
    </repository>
</repositories>

<distributionManagement>
    <repository>
        <id>my-group.local</id>
        <url>file:${project.basedir}/../../Repo</url>
    </repository>
</distributionManagement>

<build>
    ....
</build>
[/xml] (Ja, so relative Pfade sind häßlich - wenn's bessere Lösungen gibt, nur her damit...)

Diese POM lag dann in einem Verzeichnis „ParentPOM“, parallel zu allen Projekten.

Die einzelnen Projekte (hier project-a) haben dann diese POM als ihr Parent angegeben:
[xml]

4.0.0

<groupId>my-group</groupId>
<artifactId>project-a</artifactId>
<version>0.0.1-SNAPSHOT</version>

<parent>
    <groupId>my-group</groupId>
    <artifactId>my-artifact-parent</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <relativePath>../ParentPOM</relativePath>
</parent>

<dependencies>
    <dependency>
        <groupId>my-group</groupId>
        <artifactId>project-b</artifactId>
        <version>0.0.1-SNAPSHOT</version>
    </dependency>
    <dependency>
        <groupId>my-group</groupId>
        <artifactId>project-c</artifactId>
        <version>0.0.1-SNAPSHOT</version>
    </dependency>
</dependencies>
[/xml]

Das hat zur Folge, dass alle beim Bauen im lokalen Repo landen, und andere Projekte aus diesem lokalen Repo als dependencies angeben können.

Es gibt vermutlich eine „idiomatischere“, „reinere“, „bessere“, „maven-likere“ Lösung, aber so erschien mir das Verhältnis zwischen Aufwand und Ergebnis OK zu sein.

Eine Empfehlung am Rande:

Es gibt noch eine Menge an Open-Source-Projekten auf Github die Maven Nutzen und aus verschiedenen Modulen zusammengebaut werden.

Daher hätte ich an dieser Stelle einen Blick z.B. auf

geworfen und mir dort die Projektstruktur und die einzelnen Poms näher angeschaut.

Hallo,

die Bezeichnungen hören sich schon sehr gut an…aber warum dann die ParentPom in ein paralleles Verzeichnis gepackt wird ist mir nicht klar…

Also einfach:


  pom.xml (parent)
   +--- Grundprojekt (pom.xml)
   +--- Projekt2 (pom.xml)
   +--- Projekt3 (pom.xml)
   +--- Projekt4 (pom.xml)

Dann sieht die parent POM (ich klaue mal bei BinaryLogic):
[XML]
4.0.0

de.beispiel
beispiel-parent
pom
1.0-SNAPSHOT
Beispiel Parent Project

grundprojekt Projekt2 Projekt3 Projekt4 [/XML]

So jetzt kann jedes Child wie folgt aussehen (ich klaue schon wieder BinaryLogic)::

[XML]
4.0.0

de.beispiel beispiel-parent 1.0-SNAPSHOT

grundprojekt
Beispiel Child 1 Project
[/XML]

Man sieht mit einer solchen Struktur (eben Eltern-Kind) entfällt dieses lästige

<relativePath>../parentPom/</relativePath>

schlicht…(Konvention over Configuration).

Der Parent ist hier eine gute Position, um das distributionManagement festzulegen (kann man auch mit einem file:/// Zugriff machen…ABER: Bitte keine repositories festlegen…Abgesehen davon so was:
[XML]


my-group.local
my-group.local
file:${project.basedir}/…/…/Repo


[/XML]

Das bedeutet, dass jedes Projekt auf meiner Platte ein eigenes Repository erzeugt und mir die Platt voll müllt…Einfach weglassen und den Default ${HOME}/.m2/repository verwenden. Wenn der einem nicht gefällt dann in der settings.xml entsprechend anpassen.

In realen Projekten sollte der Parent von einer Corporate oder Company POM erben in der das distributionManagement definiert ist und auf einen Firmen Internen Repository Manager verweist.

Weiterhin ist mir aufgefallen, dass es eventuell günstiger ist als in diesem Beispiel (von Marco13 geklaut):
[XML]

4.0.0

<groupId>my-group</groupId>
<artifactId>project-a</artifactId>
<version>0.0.1-SNAPSHOT</version>

<parent>
    <groupId>my-group</groupId>
    <artifactId>my-artifact-parent</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <relativePath>../ParentPOM</relativePath>
</parent>

<dependencies>
    <dependency>
        <groupId>my-group</groupId>
        <artifactId>project-b</artifactId>
        <version>0.0.1-SNAPSHOT</version>
    </dependency>
    <dependency>
        <groupId>my-group</groupId>
        <artifactId>project-c</artifactId>
        <version>0.0.1-SNAPSHOT</version>
    </dependency>
</dependencies>
[/XML]

Ich würde halt die POM wie folgt strukturieren:

[XML]

4.0.0

<parent>
    <groupId>my-group</groupId>
    <artifactId>my-artifact-parent</artifactId>
    <version>0.0.1-SNAPSHOT</version>
</parent>

<artifactId>project-a</artifactId>

<dependencies>
    <dependency>
        <groupId>my-group</groupId>
        <artifactId>project-b</artifactId>
        <version>0.0.1-SNAPSHOT</version>
    </dependency>
    <dependency>
        <groupId>my-group</groupId>
        <artifactId>project-c</artifactId>
        <version>0.0.1-SNAPSHOT</version>
    </dependency>
</dependencies>
[/XML]

Den Parent immer an den Anfang schreiben, dann sieht man sofort von wem Vererbt wird…nur die Sachen hinschreiben die auch wirklich geändert werden sollen, wie in diesem Fallen nämlich die artifactId. Version und groupId werden von der Vererbung übernommen.

Dann würde ich die Dependencies noch wie folgt anpassen:

[XML]

4.0.0

<parent>
    <groupId>my-group</groupId>
    <artifactId>my-artifact-parent</artifactId>
    <version>0.0.1-SNAPSHOT</version>
</parent>

<artifactId>project-a</artifactId>

<dependencies>
    <dependency>
        <groupId>my-group</groupId>
        <artifactId>project-b</artifactId>
        <version>${project.version}</version>
    </dependency>
    <dependency>
        <groupId>my-group</groupId>
        <artifactId>project-c</artifactId>
        <version>${project.version}</version>
    </dependency>
</dependencies>
[/XML]

Sprich die Versionen hier entsprechend durch Platzhalter ersetzten. Bei den einsamen beiden Dependencies bringt das nicht wirklich was…wenn aber ein Modul mal 10-20 Dependencies hat, dann sieht man sofort, dass diese Dependencies aus dem aktuellen Build sind.

Andere Abhängigkeiten sollte man zuerst in Form des dependencyManagements in den Parent einpflegen und dann in die Module übernehmen…wie z.B. :

[XML]
4.0.0

de.beispiel beispiel-parent 1.0-SNAPSHOT

grundprojekt

Beispiel Child 1 Project

junit junit 4.12 com.google.guava guava 16.0.1 org.mockito mockito-core 1.10.19 log4j log4j 1.2.16
  weitere Dependencies...

</dependencies>

[/XML]

So jetzt in den jeweiligen Projekten die Angaben entsprechend ergänzen. Und hier erst den Scope hinzufügen…Das macht es übersichtlicher…mag bei einem Projekt einfach sein, dass nur aus 5 Modulen besteht…aber überleg das mal mit einem Projekt mit 300+ Module und 5-6 Ebenen…
[XML]

4.0.0

<parent>
    <groupId>my-group</groupId>
    <artifactId>my-artifact-parent</artifactId>
    <version>0.0.1-SNAPSHOT</version>
</parent>

<artifactId>project-a</artifactId>

<dependencies>
    <dependency>
        <groupId>my-group</groupId>
        <artifactId>project-b</artifactId>
        <version>${project.version}</version>
    </dependency>
    <dependency>
        <groupId>my-group</groupId>
        <artifactId>project-c</artifactId>
        <version>${project.version}</version>
    </dependency>

  <dependency>
    <groupId>com.google.guava</groupId>
    <artifactId>guava</artifactId>
  </dependency>

  <dependency>
    <groupId>org.mockito</groupId>
    <artifactId>mockito-core</artifactId>
    <scope>test</test>
  </dependency>
  <dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <scope>test</test>
  </dependency>
</dependencies>
[/XML]

Wenn man konsequent ist, bedient man sich nur aus dem Parent dependencyManagement block und hält so die Versionen im Zaum…

Ein wichtiger Hinweise fehlt noch. In der Parent Pom oder besser in der Corporate POM sollten alle Plugins mit Ihren Versionen festgelegt werden… um einen reproduzierbaren Build zu bekommen.

Eine Corporate POM ist auch der Weg die Größe der POM’s für neue Projekt recht übersichtlich zu halten…

So jetzt zu den Fragen bzgl. eigenständige JAR’s bzw. Lauffähige JARs…

Das kann man durch den Einsatz von maven-assembly-plugin erreichen und damit ein sog. jar-with-dependencies bauen. Wenn man mehr Kontrolle über die Klassen bzw. Überschneidungen etc. benötigt ist hier das maven-shade-plugin das Richtige.
Hierzu sollte man aber ein eigenständiges Module hinzufügen und dort diese Aufgabe erledigen…
Wenn man Skripte zur Ausführung auf der Kommandozeile benötigt wäre hier das appassembler-maven-plugin das richtige.

Gruß
Karl Heinz Marbaise

[QUOTE=kama]Hallo,

die Bezeichnungen hören sich schon sehr gut an…aber warum dann die ParentPom in ein paralleles Verzeichnis gepackt wird ist mir nicht klar…

Also einfach:


  pom.xml (parent)
   +--- Grundprojekt (pom.xml)
   +--- Projekt2 (pom.xml)
   +--- Projekt3 (pom.xml)
   +--- Projekt4 (pom.xml)

Dann sieht die parent POM (ich klaue mal bei BinaryLogic):
[XML]
4.0.0

de.beispiel
beispiel-parent
pom
1.0-SNAPSHOT
Beispiel Parent Project

grundprojekt Projekt2 Projekt3 Projekt4 [/XML] [/QUOTE]

ähm vielleicht steh ich grade auf dem Schlauch, aber…

Wo, bzw. in welchen verzeichnis würde jetzt diese parent-pom liegen?

Ähm…hatte ich doch geschreiben…

in der Verzeichnisebene höher wie hier:


 pom.xml (parent) <=============
   +--- Grundprojekt (pom.xml)
   +--- Projekt2 (pom.xml)
   +--- Projekt3 (pom.xml)
   +--- Projekt4 (pom.xml)

und man würde dann die Struktur auch so in der Versionskontrolle ablegen…wie hier zum Beispiel.

Gruß
Karl Heinz Marbaise``````