Maven Parent Pom vs Moduły Pom

284

Wydaje się, że istnieje kilka sposobów na zbudowanie poms nadrzędnych w kompilacji z wieloma projektami i zastanawiam się, czy ktoś miał jakieś przemyślenia na temat zalet / wad każdego z nich.

Najprostszą metodą posiadania rodzica pom byłoby umieszczenie go w katalogu głównym projektu, tj

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

gdzie pom.xml jest zarówno projektem nadrzędnym, jak i opisuje moduły -core -api i -app

Następną metodą jest oddzielenie elementu nadrzędnego do własnego podkatalogu, jak w

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

Gdzie pom pom nadal zawiera moduły, ale są względne, np. ../Myproject-core

Wreszcie istnieje opcja, w której definicja modułu i element nadrzędny są oddzielone jak w

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

Gdzie pom nadrzędny zawiera dowolną konfigurację „współdzieloną” (dependenceManagement, właściwości itp.), A plik myproject / pom.xml zawiera listę modułów.

Zamiarem jest skalowalność do kompilacji na dużą skalę, dlatego powinna być skalowalna do dużej liczby projektów i artefaktów.

Kilka dodatkowych pytań:

  • Gdzie jest najlepsze miejsce do zdefiniowania różnych wspólnych konfiguracji, takich jak kontrola źródła, katalogi wdrażania, wspólne wtyczki itp. (Zakładam, że nadrzędny, ale często mnie to gryzie i kończą w każdym projekcie, a nie w każdym projekcie wspólny).
  • W jaki sposób wtyczka maven-release, Hudson i Nexus radzą sobie z konfiguracją wielu projektów (być może gigantyczne pytanie, to bardziej, jeśli ktoś został przyłapany na tym, jak skonfigurowano kompilację wielu projektów)?

Edycja: Każdy z podprojektów ma swój własny plik pom.xml, pominąłem go, aby był zwięzły.

Jamie McCrindle
źródło
Czy każdy z modułów ma również swój własny pom? Mój projekt ma pompę nadrzędną, ale każdy z modułów ma również pompę. (być może czwarty sposób na to, co
opisujesz
Ach, tak, zmienię i zaktualizuję. Każda z podmodułów również ma swoją pompę.
Jamie McCrindle
3
Zaletą drugiej opcji jest aktualizacja, ponieważ łatwiej jest zarządzać w środowisku Eclipse, w którym root pom.xml w pierwszym i trzecim przykładzie trudno byłoby dołączyć, jeśli podmoduły są osobnymi projektami w środowisku Eclipse.
Jamie McCrindle

Odpowiedzi:

166

Moim zdaniem, aby odpowiedzieć na to pytanie, należy pomyśleć o cyklu życia projektu i kontroli wersji. Innymi słowy, czy pom rodzicielski ma swój własny cykl życia, tj. Czy można go wypuścić oddzielnie od innych modułów, czy nie?

Jeśli odpowiedź brzmi tak (i tak jest w przypadku większości projektów, które zostały wspomniane w pytaniu lub w komentarzach), to pom rodzicielski potrzebuje własnego modułu z VCS i z punktu widzenia Maven, a skończysz z czymś takim na poziomie VCS:

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

To sprawia, że ​​kasa jest nieco bolesna i powszechnym sposobem radzenia sobie z tym jest użycie svn:externals. Na przykład dodaj trunkskatalog:

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

Z następującą definicją czynników zewnętrznych:

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

Wyewidencjonowanie trunksskutkowałoby wówczas następującą strukturą lokalną (wzór nr 2):

root/
  parent-pom/
    pom.xml
  projectA/

Opcjonalnie możesz nawet dodać pom.xmlw trunkskatalogu:

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

Jest pom.xmlto rodzaj „fałszywego” pomu: nigdy nie został wydany, nie zawiera prawdziwej wersji, ponieważ ten plik nigdy nie został wydany, zawiera tylko listę modułów. W przypadku tego pliku kasa spowodowałaby następującą strukturę (wzór nr 3):

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

Ten „hack” umożliwia uruchomienie kompilacji reaktora od korzenia po kasie i sprawia, że ​​rzeczy są jeszcze bardziej przydatne. Tak właśnie lubię konfigurować projekty maven i repozytorium VCS dla dużych kompilacji : po prostu działa, dobrze się skaluje, daje całą elastyczność, jakiej możesz potrzebować.

Jeśli odpowiedź brzmi „ nie” (wróć do pierwotnego pytania), to myślę, że możesz żyć według wzoru nr 1 (zrób najprostszą rzecz, która może działać).

Teraz na temat dodatkowych pytań:

  • Gdzie jest najlepsze miejsce do zdefiniowania różnych wspólnych konfiguracji, takich jak kontrola źródła, katalogi wdrażania, wspólne wtyczki itp. (Zakładam, że nadrzędny, ale często mnie to gryzie i kończą w każdym projekcie, a nie w każdym projekcie wspólny).

Szczerze mówiąc, nie wiem, jak nie udzielić tutaj ogólnej odpowiedzi (np. „Użyj poziomu, na którym Twoim zdaniem sensowne jest mutualizowanie rzeczy”). W każdym razie poms dzieci zawsze mogą zastąpić odziedziczone ustawienia.

  • W jaki sposób wtyczka maven-release, Hudson i Nexus radzą sobie z konfiguracją wielu projektów (być może gigantyczne pytanie, to bardziej, jeśli ktoś został przyłapany na tym, jak skonfigurowano kompilację wielu projektów)?

Konfiguracja, której używam, działa dobrze, nie wspominając o niczym szczególnym.

Właściwie zastanawiam się, jak wtyczka maven-release-plugin radzi sobie ze wzorem nr 1 (szczególnie z tą <parent>sekcją, ponieważ nie można mieć zależności SNAPSHOT w czasie wydania). To brzmi jak problem z kurczakiem lub jajkiem, ale po prostu nie pamiętam, czy działa i był zbyt leniwy, aby go przetestować.

Pascal Thivent
źródło
To bardzo dobrze, jak widzę, jak się skaluje. Svn: externals odpowiada na moje obawy związane z nieporęcznością.
Jamie McCrindle,
@jamie Cieszę się, że jest to pomocne.
Pascal Thivent,
1
Czy mógłbyś opisać, jak sprawić, by „hack” zadziałał? Mam projekt pni i przewiduję, że celujesz na opcję -pl z „uruchomieniem kompilacji reaktora”, ale stanowi to problem podczas wykonywania wydania struktury, ponieważ ta opcja nie przechodzi z kompilacji na poziomie root czy mogę umieścić go w opcji <arguments /> wtyczki Release. Dlatego uwolnienie: wykonać failes ponieważ stara się pracy na poziomie root-pom ...
sty
Hack svn: externals to najbardziej użyteczny hack svn, jaki widziałem od dłuższego czasu. Bardzo pomocne w przypadku projektów, które mają rozgałęzienia dla poszczególnych projektów w tym samym repozytorium.
omerkudat
1
Cześć Pascal, Jak poradziłbyś sobie z wersją #, jeśli projekty wymienione w sekcji modułów nie używają elementu nadrzędnego jako elementu <parent>, ale jakiegoś innego projektu nadrzędnego? Jakie wersje # otrzymamy za artefakt takich projektów (wersja # artefaktu w sekcji <parent> tych projektów LUB wersja # projektu, w którym wymieniono te projekty jako moduły)? stackoverflow.com/questions/25918593/…
AKS
34

Z mojego doświadczenia i najlepszych praktyk Maven są dwa rodzaje „poms” dla rodziców

  • „firma” nadrzędna pom - ta pom zawiera informacje i konfigurację specyficzne dla twojej firmy, które dziedziczą każdą pompę i nie trzeba jej kopiować. Te informacje to:

    • repozytoria
    • sekcje zarządzania dystrybucją
    • popularne konfiguracje wtyczek (takie jak wersja źródłowa i docelowa wtyczki kompilatora maven)
    • organizacja, programiści itp

    Przygotowywanie tego pom-pom musi być wykonane ostrożnie, ponieważ wszystkie poms w twojej firmie odziedziczą po nim, więc ten pom musi być dojrzały i stabilny (wydanie wersji pom-pom nie powinno wpłynąć na uwolnienie wszystkich projektów twojej firmy!)

  • drugim rodzajem pom jest rodzic wielomodułowy. Wolę twoje pierwsze rozwiązanie - jest to domyślna konwencja maven dla projektów wielomodułowych, bardzo często reprezentująca strukturę kodu VCS

Zamiarem jest skalowalność do kompilacji na dużą skalę, dlatego powinna być skalowalna do dużej liczby projektów i artefaktów.

Mutliprojects mają strukturę drzew - więc nie jesteś przyzwyczajony do jednego poziomu pom-rodzica. Spróbuj znaleźć odpowiednią strukturę projektu dla swoich potrzeb - klasyczny przykład to, jak rozbić projekty wielomodułowe

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

Kilka dodatkowych pytań:

  • Gdzie jest najlepsze miejsce do zdefiniowania różnych wspólnych konfiguracji, takich jak kontrola źródła, katalogi wdrażania, wspólne wtyczki itp. (Zakładam, że nadrzędny, ale często mnie to gryzie i kończą w każdym projekcie, a nie w każdym projekcie wspólny).

Tę konfigurację należy mądrze rozdzielić na „pom” nadrzędne „pom” i nadrzędne „pom” nad projektem. Rzeczy związane ze wszystkim, co projektują, trafiają do rodzica „firmy”, a to związane z bieżącym projektem przechodzi do projektu własnego.

  • W jaki sposób wtyczka maven-release, Hudson i Nexus radzą sobie z konfiguracją wielu projektów (być może gigantyczne pytanie, to bardziej, jeśli ktoś został przyłapany na tym, jak skonfigurowano kompilację wielu projektów)?

Najpierw należy wypuścić macierzystą spółkę. W przypadku wielu projektów obowiązują standardowe zasady. Serwer CI musi wiedzieć wszystko, aby poprawnie zbudować projekt.

cetnar
źródło
1
Tak, że istnieją dwa rodzaje projektów nadrzędnych / poms. Jeden bez deklaracji <modules>. Ten jest używany do dziedziczenia. I projekt nadrzędny z deklaracją <multimodule>. Ten, z którego podmoduły nie dziedziczą, służy jedynie zarządzaniu budową projektu wstrzymania. Czy mam rację ?
lisak
22
  1. Niezależny element nadrzędny to najlepsza praktyka do udostępniania konfiguracji i opcji między niepołączonymi komponentami. Apache ma nadrzędny projekt pom, który udostępnia informacje prawne i niektóre typowe opcje pakowania.

  2. Jeśli twój projekt najwyższego poziomu ma w sobie prawdziwą pracę, taką jak agregacja javadoc lub pakowanie wydania, będziesz mieć konflikty między ustawieniami potrzebnymi do wykonania tej pracy a ustawieniami, które chcesz udostępnić przez rodzica. Projekt tylko dla rodziców unika tego.

  3. Powszechnym wzorcem (na razie ignorując # 1) jest to, że projekty z kodem używają projektu nadrzędnego jako nadrzędnego i używają najwyższego poziomu jako nadrzędnego. Pozwala to wszystkim dzielić się podstawowymi rzeczami, ale pozwala uniknąć problemu opisanego w punkcie 2.

  4. Wtyczka witryny będzie bardzo zdezorientowana, jeśli struktura nadrzędna nie będzie taka sama jak struktura katalogów. Jeśli chcesz zbudować zagregowaną witrynę, musisz zrobić trochę majstrowania, aby obejść ten problem.

  5. Apache CXF jest przykładem wzorca z # 2.

bmargulies
źródło
2
Rzuciłem okiem na ibilio i wydaje się, że wiele projektów woli „niezależnego” rodzica pom. Hibernacja, ActiveMQ, Jetty, XStream itp. Co sugeruje, że jest to mechanizm defacto.
Jamie McCrindle
2
Kolejnym minusem niezależnego rodzica wydaje się być to, że wtyczka maven wydaje się chcieć, aby rodzic był przypięty do wersji przed wydaniem. Prawdopodobnie nie stanowi większego problemu, ponieważ rodzic nie powinien zbytnio się zmieniać.
Jamie McCrindle
9

W trzecim podejściu jest jeden mały haczyk. Ponieważ agregowane POM (myproject / pom.xml) zwykle nie mają w ogóle elementu nadrzędnego, nie współużytkują konfiguracji. Oznacza to, że wszystkie te POM będą mieć tylko domyślne repozytoria.

Nie stanowi to problemu, jeśli korzystasz tylko z wtyczek z centralnej wersji, ale to się nie powiedzie, jeśli uruchomisz wtyczkę przy użyciu formatu wtyczki: cel z wewnętrznego repozytorium. Na przykład możesz mieć foo-maven-pluginparametr groupId org.examplezapewniający cel generate-foo. Jeśli spróbujesz uruchomić go z katalogu głównego projektu za pomocą polecenia podobnego mvn org.example:foo-maven-plugin:generate-foo, nie będzie działać na modułach agregujących (patrz uwaga dotycząca zgodności ).

Możliwych jest kilka rozwiązań:

  1. Wdróż wtyczkę w Maven Central (nie zawsze jest to możliwe).
  2. Określ sekcję dotyczącą repozytorium we wszystkich swoich agregatach POM (łamie zasadę DRY ).
  3. Skonfiguruj to wewnętrzne repozytorium w pliku settings.xml (w ustawieniach lokalnych w ~ / .m2 / settings.xml lub w ustawieniach globalnych w /conf/settings.xml). Sprawi, że kompilacja nie powiedzie się bez tych ustawień. Xml (może być OK dla dużych projektów wewnętrznych, które nigdy nie powinny być budowane poza firmą).
  4. Użyj rodzica z ustawieniami repozytoriów w swoich zagregowanych POM-ach (może to być zbyt wiele nadrzędnych POM-ów?).
Ivan Dubrov
źródło