Maven padre pom vs moduli pom

Sembrano esserci diversi modi per strutturare i poms genitore in una build multiprogetto e mi chiedo se qualcuno abbia qualche idea su quali siano i vantaggi / gli svantaggi in ogni modo.

Il metodo più semplice per avere un padre genitore sarebbe metterlo nella radice di un progetto, ad es

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

dove pom.xml è sia il progetto padre che descrive i moduli -core -api e -app

Il prossimo metodo è quello di separare il genitore nella propria sottodirectory come in

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

Dove il pom principale contiene ancora i moduli ma sono relativi, ad es ../myproject-core

Infine, c’è l’opzione in cui la definizione del modulo e il genitore sono separati come in

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

Dove il pom principale contiene una configurazione “condivisa” (dependencyManagement, proprietà ecc.) E il myproject / pom.xml contiene l’elenco dei moduli.

L’intenzione è di essere scalabile su una build su larga scala, quindi dovrebbe essere scalabile per un numero elevato di progetti e artefatti.

Alcune domande bonus:

  • Dov’è il posto migliore per definire le varie configurazioni condivise come nel controllo del codice sorgente, nelle directory di distribuzione, nei plug-in comuni ecc. (Sto assumendo il genitore ma sono stato spesso morso da questo e sono finiti in ogni progetto piuttosto che uno comune).
  • In che modo il plugin di rilascio di maven, hudson e nexus si occupano di come configuri i tuoi multiprogetti (forse una domanda gigantesca, è meglio se qualcuno è stato colto da una configurazione multiprogetto)?

Modifica: Ognuno dei sottoprogetti ha il proprio pom.xml, l’ho lasciato fuori per tenerlo in ordine.

A mio parere, per rispondere a questa domanda, è necessario pensare in termini di ciclo di vita del progetto e controllo della versione. In altre parole, il padre gen ha il suo ciclo di vita, cioè può essere rilasciato separatamente dagli altri moduli o no?

Se la risposta è (e questo è il caso della maggior parte dei progetti che sono stati menzionati nella domanda o nei commenti), allora il genitore ha bisogno del proprio modulo da un VCS e da un punto di vista Maven e finirai per con qualcosa di simile a livello VCS:

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

Questo rende la cassa un po ‘dolorosa e un modo comune per affrontarlo è usare svn:externals . Ad esempio, aggiungi una directory trunks :

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

Con la seguente definizione esterna:

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

Una verifica dei trunks risulterebbe quindi nella seguente struttura locale (schema n. 2):

 root/ parent-pom/ pom.xml projectA/ 

Facoltativamente, puoi anche aggiungere un pom.xml nella directory dei trunks :

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

Questo pom.xml è una sorta di pom “finto”: non viene mai rilasciato, non contiene una versione reale poiché questo file non viene mai rilasciato, contiene solo un elenco di moduli. Con questo file, un checkout risulterebbe in questa struttura (modello n. 3):

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

Questo “hack” permette di lanciare una build di reattori dalla radice dopo un checkout e rendere le cose ancora più pratiche. In realtà, questo è il modo in cui mi piace impostare progetti Maven e un repository VCS per grandi build : funziona, ha una buona scalabilità, offre tutta la flessibilità di cui hai bisogno.

Se la risposta è no (torna alla domanda iniziale), allora penso che puoi vivere con il modello n. 1 (fai la cosa più semplice che potrebbe funzionare).

Ora, riguardo alle domande bonus:

  • Dov’è il posto migliore per definire le varie configurazioni condivise come nel controllo del codice sorgente, nelle directory di distribuzione, nei plug-in comuni ecc. (Sto assumendo il genitore ma sono stato spesso morso da questo e sono finiti in ogni progetto piuttosto che uno comune).

Onestamente, non so come non dare una risposta generale qui (come “usa il livello in cui pensi che abbia senso per mutualizzare le cose”). E comunque, i poms dei bambini possono sempre sovrascrivere le impostazioni ereditate.

  • In che modo il plugin di rilascio di maven, hudson e nexus si occupano di come configuri i tuoi multiprogetti (forse una domanda gigantesca, è meglio se qualcuno è stato colto da una configurazione multiprogetto)?

Il setup che utilizzo funziona bene, niente di particolare da menzionare.

In realtà, mi chiedo come il plugin di rilascio di Maven si occupi del pattern n. 1 (specialmente con la sezione dato che non è ansible avere dipendenze di SNAPSHOT al momento del rilascio). Questo suona come un problema di pollo o uovo, ma non riesco a ricordare se funziona e fosse troppo pigro per provarlo.

Dalla mia esperienza e dalle migliori pratiche di Maven ci sono due tipi di “genitori poms”

  • “company” gen pom: questo pom contiene informazioni e configurazioni specifiche della tua azienda che ereditano tutti i pom e non devono essere copiati. Queste informazioni sono:

    • repository
    • sezioni di gestione della distribuzione
    • configurazioni di plugin comuni (come le versioni di origine e destinazione di maven-compiler-plugin)
    • organizzazione, sviluppatori, ecc

    Preparare questo genitore deve essere fatto con caucanvas, perché tutti i tuoi poms aziendali ne erediteranno, quindi questo pom deve essere maturo e stabile (rilasciando una versione di padre pom non dovrebbe influire sul rilascio di tutti i tuoi progetti aziendali!)

  • il secondo tipo di genitore genitore è un genitore multimodulo. Preferisco la tua prima soluzione: questa è una convenzione di maven predefinita per i progetti a più moduli, molto spesso rappresenta la struttura del codice VCS

L’intenzione è di essere scalabile su una build su larga scala, quindi dovrebbe essere scalabile per un numero elevato di progetti e artefatti.

I mutliproject hanno una struttura di alberi – quindi non sei cresciuto fino a un livello di pom genitore. Prova a trovare un progetto adatto per le tue esigenze: un esempio classico è come disintendere progetti mutimodule

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

Alcune domande bonus:

  • Dov’è il posto migliore per definire le varie configurazioni condivise come nel controllo del codice sorgente, nelle directory di distribuzione, nei plug-in comuni ecc. (Sto assumendo il genitore ma sono stato spesso morso da questo e sono finiti in ogni progetto piuttosto che uno comune).

Questa configurazione deve essere saggiamente suddivisa in un pom genitore “aziendale” e in un pom principale del progetto. Le cose relative a tutto il tuo progetto vanno al genitore della “compagnia” e questo relativo al progetto attuale va a proiettarne uno.

  • In che modo il plugin di rilascio di maven, hudson e nexus si occupano di come configuri i tuoi multiprogetti (forse una domanda gigantesca, è meglio se qualcuno è stato colto da una configurazione multiprogetto)?

Il padre genitore dell’azienda deve essere rilasciato per primo. Per i multiprogetti si applicano le regole standard. Il server CI deve sapere tutto per build correttamente il progetto.

  1. Un genitore indipendente è la procedura migliore per condividere la configurazione e le opzioni tra componenti altrimenti disgiunti. Apache ha un progetto padre per condividere le note legali e alcune opzioni di imballaggio comuni.

  2. Se il tuo progetto di primo livello ha un vero lavoro in esso, come l’aggregazione di javadoc o il confezionamento di una versione, allora avrai dei conflitti tra le impostazioni necessarie per fare quel lavoro e le impostazioni che vuoi condividere via genitore. Un progetto solo per genitori lo evita.

  3. Un modello comune (ignorando il n. 1 per il momento) prevede che i progetti con codice utilizzino un genitore come genitore e utilizzino il livello principale come genitore. Ciò consente di condividere le cose principali, ma evita il problema descritto al punto # 2.

  4. Il plug-in del sito sarà molto confuso se la struttura del genitore non è la stessa della struttura della directory. Se vuoi creare un sito aggregato, dovrai fare qualche giocherellando per aggirare questo problema.

  5. Apache CXF è un esempio del pattern in # 2.

C’è una piccola presa con il terzo approccio. Poiché le POM aggregate (myproject / pom.xml) di solito non hanno affatto un genitore, non condividono la configurazione. Ciò significa che tutte le POM aggregate avranno solo repository predefiniti.

Questo non è un problema se si usano solo plugin da Central, tuttavia, questo fallirà se si esegue il plug-in usando il plug-in: formato objective dal proprio repository interno. Ad esempio, puoi avere foo-maven-plugin con groupId di org.example fornisce goal generate-foo . Se provi ad eseguirlo dal root del progetto usando il comando mvn org.example:foo-maven-plugin:generate-foo , non funzionerà sui moduli aggregati (vedi nota di compatibilità ).

Sono possibili diverse soluzioni:

  1. Distribuire il plugin su Maven Central (non sempre ansible).
  2. Specifica la sezione del repository in tutte le tue POM aggregate (interrompe il principio DRY ).
  3. Avere questo repository interno configurato in settings.xml (nelle impostazioni locali in ~ / .m2 / settings.xml o nelle impostazioni globali in /conf/settings.xml). Farà fallire la build senza quelle settings.xml (potrebbe andare bene per i grandi progetti interni che non dovrebbero mai essere costruiti al di fuori dell’azienda).
  4. Utilizza le impostazioni padre con repository nelle tue POM aggregate (potrebbero essere troppe POM padre?).