Maven Eltern Pom vs Module Pom

284

Es scheint verschiedene Möglichkeiten zu geben, Eltern-Poms in einem Multiprojekt-Build zu strukturieren, und ich frage mich, ob jemand darüber nachgedacht hat, welche Vor- und Nachteile die einzelnen Aspekte haben.

Die einfachste Methode, einen Eltern-Pom zu haben, besteht darin, ihn in die Wurzel eines Projekts zu legen, d. H.

myproject/
  myproject-core/
  myproject-api/
  myproject-app/
  pom.xml

Dabei ist die Datei pom.xml sowohl das übergeordnete Projekt als auch die Module -core -api und -app

Die nächste Methode besteht darin, das übergeordnete Element wie in in ein eigenes Unterverzeichnis zu unterteilen

myproject/
  mypoject-parent/
    pom.xml
  myproject-core/
  myproject-api/
  myproject-app/

Wo der übergeordnete POM noch die Module enthält, diese aber relativ sind, z. B. ../myproject-core

Schließlich gibt es die Option, bei der die Moduldefinition und das übergeordnete Element wie in getrennt sind

myproject/
  mypoject-parent/
    pom.xml
  myproject-core/
  myproject-api/
  myproject-app/
  pom.xml

Wobei das übergeordnete pom eine "gemeinsam genutzte" Konfiguration enthält (dependencyManagement, Eigenschaften usw.) und myproject / pom.xml die Liste der Module enthält.

Die Absicht ist, auf einen großen Build skalierbar zu sein, sollte also auf eine große Anzahl von Projekten und Artefakten skalierbar sein.

Ein paar Bonusfragen:

  • Wo ist der beste Ort, um die verschiedenen gemeinsam genutzten Konfigurationen wie Quellcodeverwaltung, Bereitstellungsverzeichnisse, allgemeine Plugins usw. zu definieren? eine gemeinsame).
  • Wie gehen das Maven-Release-Plugin, Hudson und Nexus damit um, wie Sie Ihre Multiprojekte einrichten (möglicherweise eine große Frage, es ist mehr, wenn jemand herausgeholt wurde, wann ein Multiprojekt-Build eingerichtet wurde)?

Bearbeiten: Jedes der Unterprojekte hat seine eigene pom.xml, ich habe es weggelassen, um es knapp zu halten.

Jamie McCrindle
quelle
Haben die Module auch jeweils einen eigenen POM? Mein Projekt hat einen übergeordneten Pom, aber die Module haben jeweils auch einen Pom. (Vielleicht ein vierter Weg zu dem, was du beschreibst)
Harschware
Ah, ja, ich werde bearbeiten und aktualisieren. Jedes der Submodule hat auch einen eigenen Pom.
Jamie McCrindle
3
Nur als Update sehe ich einen Vorteil der zweiten Option darin, dass es einfacher ist, in Eclipse zu verwalten, wo die Root-Datei pom.xml im ersten und dritten Beispiel schwer einzuschließen wäre, wenn die Untermodule separate Projekte in Eclipse sind.
Jamie McCrindle

Antworten:

166

Um diese Frage zu beantworten, müssen Sie meiner Meinung nach im Hinblick auf den Projektlebenszyklus und die Versionskontrolle denken. Mit anderen Worten, hat der Eltern-POM einen eigenen Lebenszyklus, dh kann er separat von den anderen Modulen freigegeben werden oder nicht?

Wenn die Antwort ja lautet (und dies ist bei den meisten Projekten der Fall, die in der Frage oder in den Kommentaren erwähnt wurden), benötigt der übergeordnete POM aus VCS- und Maven-Sicht ein eigenes Modul, und Sie werden am Ende sein mit so etwas auf VCS-Ebene:

root
|-- parent-pom
|   |-- branches
|   |-- tags
|   `-- trunk
|       `-- pom.xml
`-- projectA
    |-- branches
    |-- tags
    `-- trunk
        |-- module1
        |   `-- pom.xml
        |-- moduleN
        |   `-- pom.xml
        `-- pom.xml

Dies macht das Auschecken ein bisschen schmerzhaft und eine übliche Art, damit umzugehen, ist die Verwendung svn:externals. Fügen Sie beispielsweise ein trunksVerzeichnis hinzu:

root
|-- parent-pom
|   |-- branches
|   |-- tags
|   `-- trunk
|       `-- pom.xml
|-- projectA
|   |-- branches
|   |-- tags
|   `-- trunk
|       |-- module1
|       |   `-- pom.xml
|       |-- moduleN
|       |   `-- pom.xml
|       `-- pom.xml
`-- trunks

Mit folgender externer Definition:

parent-pom http://host/svn/parent-pom/trunk
projectA http://host/svn/projectA/trunk

Ein Auschecken von trunkswürde dann zu der folgenden lokalen Struktur führen (Muster # 2):

root/
  parent-pom/
    pom.xml
  projectA/

Optional können Sie sogar ein pom.xmlim trunksVerzeichnis hinzufügen :

root
|-- parent-pom
|   |-- branches
|   |-- tags
|   `-- trunk
|       `-- pom.xml
|-- projectA
|   |-- branches
|   |-- tags
|   `-- trunk
|       |-- module1
|       |   `-- pom.xml
|       |-- moduleN
|       |   `-- pom.xml
|       `-- pom.xml
`-- trunks
    `-- pom.xml

Dies pom.xmlist eine Art "gefälschter" Pom: Es wird nie veröffentlicht, es enthält keine echte Version, da diese Datei nie veröffentlicht wird, es enthält nur eine Liste von Modulen. Bei dieser Datei würde ein Auschecken zu dieser Struktur führen (Muster 3):

root/
  parent-pom/
    pom.xml
  projectA/
  pom.xml

Dieser "Hack" ermöglicht es, einen Reaktor nach dem Auschecken von der Wurzel aus zu starten und die Dinge noch praktischer zu machen. Auf diese Weise richte ich gerne Maven-Projekte und ein VCS-Repository für große Builds ein : Es funktioniert einfach, lässt sich gut skalieren und bietet die Flexibilität, die Sie möglicherweise benötigen.

Wenn die Antwort nein ist (zurück zur ursprünglichen Frage), dann können Sie mit Muster Nr. 1 leben (tun Sie das Einfachste, was möglicherweise funktionieren könnte).

Nun zu den Bonusfragen:

  • Wo ist der beste Ort, um die verschiedenen gemeinsam genutzten Konfigurationen wie Quellcodeverwaltung, Bereitstellungsverzeichnisse, allgemeine Plugins usw. zu definieren? eine gemeinsame).

Ehrlich gesagt, ich weiß nicht, wie ich hier keine allgemeine Antwort geben soll (wie "Verwenden Sie die Ebene, auf der es Ihrer Meinung nach sinnvoll ist, Dinge zu verinnerlichen"). Außerdem können Kinder-Poms geerbte Einstellungen immer überschreiben.

  • Wie gehen das Maven-Release-Plugin, Hudson und Nexus damit um, wie Sie Ihre Multiprojekte einrichten (möglicherweise eine große Frage, es ist mehr, wenn jemand herausgeholt wurde, wann ein Multiprojekt-Build eingerichtet wurde)?

Das Setup, das ich benutze, funktioniert gut, nichts Besonderes zu erwähnen.

Eigentlich frage ich mich, wie das Maven-Release-Plugin mit Muster Nr. 1 umgeht (insbesondere mit dem <parent>Abschnitt, da Sie zur Release-Zeit keine SNAPSHOT-Abhängigkeiten haben können). Das klingt nach einem Henne-Ei-Problem, aber ich kann mich nicht erinnern, ob es funktioniert und zu faul war, um es zu testen.

Pascal Thivent
quelle
Das ist sehr gut, da ich sehen kann, wie es skaliert. Das svn: externals beantwortet meine Besorgnis darüber, dass es umständlich ist.
Jamie McCrindle
@ Jamie Ich bin froh, dass du es hilfreich findest.
Pascal Thivent
1
Könnten Sie näher erläutern, wie der "Hack" funktioniert? Ich habe das Trunks-Projekt und gehe davon aus, dass Sie die Option -pl mit "Start eines Reaktor-Builds" als Ziel festlegen. Dies stellt jedoch ein Problem dar, wenn Sie eine Freigabe für die Struktur durchführen, da diese Option auch nicht von einem Build auf Root-Ebene übergeben wird Kann ich es in die Option <Argumente /> des Release-Plugins einfügen? Deshalb ist die Freisetzung: führen failes , weil es an die Arbeit auf der pom root-Ebene versucht ...
Jan
Der svn: externals-Hack ist der nützlichste svn-Hack, den ich seit langer Zeit gesehen habe. Sehr hilfreich bei Projekten, bei denen pro Projekt innerhalb desselben Repositorys verzweigt wird.
Omerkudat
1
Hallo Pascal, wie würden Sie mit Version # umgehen, wenn Projekte, die im Modulabschnitt erwähnt werden, nicht Parent-Pom als <Element> verwenden, sondern ein anderes Projekt-Parent-Pom? Welche Versionen # erhalten wir für ein Artefakt solcher Projekte (Version # des Artefakts im Abschnitt <parent> dieser Projekte ODER Version # des Projekts, in der diese Projekte als Module aufgeführt sind)? stackoverflow.com/questions/25918593/…
AKS
34

Nach meiner Erfahrung und den Best Practices von Maven gibt es zwei Arten von "Eltern-Poms".

  • "Unternehmen" übergeordnetes POM - Dieses POM enthält Ihre unternehmensspezifischen Informationen und Konfigurationen, die jedes POM erben und nicht kopiert werden müssen. Diese Informationen sind:

    • Repositories
    • Verteilungsmanagementabschnitte
    • gängige Plugin-Konfigurationen (wie Quell- und Zielversionen von Maven-Compiler-Plugins)
    • Organisation, Entwickler usw.

    Die Vorbereitung dieses übergeordneten Poms muss mit Vorsicht erfolgen, da alle Poms Ihres Unternehmens davon erben. Daher muss dieser Pom ausgereift und stabil sein (die Veröffentlichung einer Version des übergeordneten Poms sollte sich nicht auf die Freigabe aller Ihrer Unternehmensprojekte auswirken!)

  • Die zweite Art von Eltern-Pom ist ein multimodulierter Elternteil. Ich bevorzuge Ihre erste Lösung - dies ist eine Standard-Maven-Konvention für Projekte mit mehreren Modulen, die sehr oft die VCS-Codestruktur darstellt

Die Absicht ist, auf einen großen Build skalierbar zu sein, sollte also auf eine große Anzahl von Projekten und Artefakten skalierbar sein.

Mutliprojekte haben eine Baumstruktur - Sie sind also nicht auf eine Ebene des Eltern-Poms beschränkt. Versuchen Sie, eine geeignete Projektstruktur für Ihre Bedürfnisse zu finden - ein klassisches Beispiel ist die Verteilung von Mutimodul-Projekten

distibution/
documentation/
myproject/
  myproject-core/
  myproject-api/
  myproject-app/
  pom.xml
pom.xml

Ein paar Bonusfragen:

  • Wo ist der beste Ort, um die verschiedenen gemeinsam genutzten Konfigurationen wie Quellcodeverwaltung, Bereitstellungsverzeichnisse, allgemeine Plugins usw. zu definieren? eine gemeinsame).

Diese Konfiguration muss mit Bedacht in einen "Firmen" -Eltern-Pom und einen Projekt-Eltern-Pom (s) aufgeteilt werden. Dinge, die sich auf alles beziehen, was Sie projektieren, gehen an die Muttergesellschaft des Unternehmens, und dies bezieht sich auf das aktuelle Projekt.

  • Wie gehen das Maven-Release-Plugin, Hudson und Nexus damit um, wie Sie Ihre Multiprojekte einrichten (möglicherweise eine große Frage, es ist mehr, wenn jemand herausgeholt wurde, wann ein Multiprojekt-Build eingerichtet wurde)?

Die Muttergesellschaft des Unternehmens muss zuerst freigelassen werden. Für Multiprojekte gelten Standardregeln. CI-Server müssen alle wissen, um das Projekt korrekt zu erstellen.

cetnar
quelle
1
Damit gibt es zwei Arten von übergeordneten Projekten / Poms. Eine ohne <Module> -Deklaration. Dies ist diejenige, die für die Vererbung verwendet wird. Und ein übergeordnetes Projekt mit der Deklaration <multimodule>. Dies ist dasjenige, von dem Submodule nicht erben. Es dient lediglich zur Verwaltung der Erstellung des Hold-Projekts. Habe ich recht ?
Lisak
22
  1. Ein unabhängiges übergeordnetes Element ist die beste Vorgehensweise für die gemeinsame Nutzung von Konfiguration und Optionen für ansonsten entkoppelte Komponenten. Apache hat ein übergeordnetes POM-Projekt, um rechtliche Hinweise und einige gängige Verpackungsoptionen zu teilen.

  2. Wenn in Ihrem Projekt der obersten Ebene echte Arbeit enthalten ist, z. B. das Zusammenfassen von Javadoc oder das Packen einer Version, treten Konflikte zwischen den für diese Arbeit erforderlichen Einstellungen und den Einstellungen auf, die Sie über das übergeordnete Element freigeben möchten. Ein Projekt nur für Eltern vermeidet dies.

  3. Ein gängiges Muster (das momentan die Nummer 1 ignoriert) besteht darin, dass die Projekte mit Code ein übergeordnetes Projekt als übergeordnetes Projekt und die oberste Ebene als übergeordnetes Projekt verwenden. Dies ermöglicht die gemeinsame Nutzung von Kernsachen, vermeidet jedoch das in Nr. 2 beschriebene Problem.

  4. Das Site-Plugin wird sehr verwirrt, wenn die übergeordnete Struktur nicht mit der Verzeichnisstruktur übereinstimmt. Wenn Sie eine aggregierte Site erstellen möchten, müssen Sie ein wenig herumspielen, um dies zu umgehen.

  5. Apache CXF ist ein Beispiel für das Muster in # 2.

bmargulies
quelle
2
Ich habe mir ibilio angesehen und viele Projekte scheinen den "unabhängigen" Eltern-Pom zu bevorzugen. Ruhezustand, ActiveMQ, Jetty, XStream usw. Dies deutet darauf hin, dass es sich um den Defacto-Mechanismus handelt.
Jamie McCrindle
2
Ein weiterer Nachteil des unabhängigen übergeordneten Elements scheint zu sein, dass das Maven-Release-Plugin anscheinend möchte, dass das übergeordnete Element an eine Version angeheftet wird, bevor es veröffentlicht wird. Wahrscheinlich kein großes Problem, da sich die Eltern nicht zu sehr ändern sollten.
Jamie McCrindle
9

Beim dritten Ansatz gibt es einen kleinen Haken. Da aggregierte POMs (myproject / pom.xml) normalerweise überhaupt keine übergeordneten Elemente haben, teilen sie die Konfiguration nicht. Das bedeutet, dass alle diese aggregierten POMs nur Standard-Repositorys haben.

Dies ist kein Problem, wenn Sie nur Plugins von Central verwenden. Dies schlägt jedoch fehl, wenn Sie das Plugin mit dem Plugin: Goal-Format aus Ihrem internen Repository ausführen. Beispielsweise können Sie foo-maven-pluginmit der groupId org.exampledas Ziel angeben generate-foo. Wenn Sie versuchen, es mit dem Befehl like vom Projektstamm aus auszuführen mvn org.example:foo-maven-plugin:generate-foo, kann es nicht auf den Aggregatmodulen ausgeführt werden (siehe Kompatibilitätshinweis ).

Es sind mehrere Lösungen möglich:

  1. Stellen Sie das Plugin in Maven Central bereit (nicht immer möglich).
  2. Geben Sie den Repository-Abschnitt in allen Ihren aggregierten POMs an (verstößt gegen das DRY- Prinzip).
  3. Lassen Sie dieses interne Repository in der Datei settings.xml konfigurieren (entweder in den lokalen Einstellungen unter ~ / .m2 / settings.xml oder in den globalen Einstellungen unter /conf/settings.xml). Der Build schlägt ohne diese settings.xml fehl (kann für große interne Projekte in Ordnung sein, die niemals außerhalb des Unternehmens erstellt werden sollen).
  4. Verwenden Sie die übergeordneten Einstellungen für Repositorys in Ihren aggregierten POMs (möglicherweise zu viele übergeordnete POMs?).
Ivan Dubrov
quelle