2012-05-04 34 views
11

Mi scuso per la lunghezza di questo post, ma ho avuto problemi a renderlo più conciso senza presentare la foto. Di recente ho ereditato il lavoro di build-master per un progetto multi-modulo di maven 3.0. Il problema è che la struttura del progetto/dei moduli è un disastro. Dal modo in cui le cose sono attualmente memorizzate in Source Control (usiamo RTC) alla struttura pom dei moduli, mi sto strappando i capelli cercando di ottenere un ciclo di compilazione completo completato ogni volta.Come ristrutturare il progetto multi-modulo Maven?

Come una gerarchia di progetto, tutti i moduli sono memorizzati "flat"; cioè: tutto è allo stesso livello. Ho un padre genitore e tutti i moduli dipendono dal genitore. Tuttavia, il genitore è allo stesso livello di tutti i miei altri moduli.

Es:

c:\dev\MyEarProject 
+ parent-pom 
    - pom.xml 
+ module1 
    - pom.xml (depends on parent-pom) 
    - src 
    - main 
    -  ... 
+ module2 
    - pom.xml (depends on parent-pom) 
    - src 
    - main 
    -  ... 
+ module3 
    - pom.xml (depends on parent-pom) 
    - src 
    - main 
    -  ... 

Il genitore pom definisce tutti i moduli necessari per costruire il progetto, così come una serie di proprietà di numeri di versione artefatto utilizzati nelle varie sottomoduli:

<modules> 
    <module>../module1</module> 
    <module>../module2</module> 
    <module>../module3</module> 
</modules> 

<properties> 
    <org.springframework.version>3.0.5.RELEASE</org.springframework.version> 
    <slf4j.version>1.6.4</slf4j.version> 
    <repositoryAddress>${snapshots.repo.url}</repositoryAddress> 
    <my.hibernate-module.dao.impl>1.2.3</my.hibernate-module.dao.impl> 
    <my.hibernate-module.dao.api>1.2.3</my.hibernate-module.dao.api> 
</properties> 

Il pom di ogni modulo, a sua volta, dipende dal pom principale tramite il numero di artefatto del pom:

<parent> 
    <groupId>com.cws.cs.lendingsimulationservice</groupId> 
    <artifactId>parent-pom</artifactId> 
    <version>1.0.6</version> 
</parent> 

Per rendere le cose ancora più confuse, il nome effettivo della risorsa può o non può (dipende dal modulo) corrispondere al percorso del modulo. Ad esempio, il modulo1 può trovarsi nel percorso c:\dev\MyEarProject\module1 ma ha il nome di artefatto hibernate-module. Tuttavia, a causa del modo in cui è memorizzato in RTC, la directory viene chiamata module1 quando viene ritirata.

Il modo più semplice per creare tutto, ovviamente, è quello di andare in c:\dev\MyEarProject\parent-pom\ ed eseguire mvn clean deploy. Funziona correttamente quando ci si trova in modalità SNAPSHOT poiché il repository SNAPSHOT consente più implementazioni della stessa versione di artefatto. Ma in modalità di rilascio, questo fallisce.

Questa struttura causa 2 problemi.

  1. Ogni volta che ho bisogno di fare un cambio di versione a una proprietà nel genitore, devo aggiornare il numero di versione genitore-pom, e tutto il bambino moduli della versione del pom genitore, e tutto il bambino moduli versione stessi (dal il genitore è cambiato).
  2. Ogni volta che ho bisogno di distribuire un ciclo di rilascio, mvn genererà un errore se uno dei moduli non è cambiato dall'ultimo ciclo e di conseguenza non può essere ridistribuito allo stesso repository (il repository non consente di sovrascrivere gli artefatti esistenti)

Quindi sto cercando il modo migliore per ristrutturare questo progetto per evitare questi problemi. Per il padre gen, so che posso usare un percorso relativo per indicare invece il genitore. Tuttavia, data la struttura "piatta" dei moduli, questo è un approccio raccomandato (es .: il percorso relativo del genitore dovrebbe essere ../parent-pom/pom.xml - mi sembra un po 'strano)? Inoltre, dato che il controllo delle versioni del genitore è indipendente dai moduli, l'utilizzo di un percorso relativo non solo apre la porta a ulteriori confusioni (ovvero: non ci sarebbe modo di sapere quale versione del padre principale è associata a quale versione del sottomodulo).

In secondo luogo, come posso costruire l'intero orecchio senza incontrare gli errori di distribuzione che sto avendo? Poiché l'artefatto esiste già nel repository, non è necessario ricostruirlo e ridistribuirlo. Ho provato a usare --projects ma con il numero di moduli coinvolti, diventa estremamente difficile da gestire.

risposta

12

La prima cosa che consiglio veramente è di ristrutturare le cartelle dei progetti ... il che significa che la cartella dei progetti rappresenta la struttura che significa NON appiattire la struttura.

+-- parent-pom (pom.xml) 
     +--- module1 (pom.xml) 
     +--- module2 (pom.xml) 
     +--- module3 (pom.xml) 

Come risultato di tale sezione, i moduli di un genitore sarà semplificato in questo modo:

<modules> 
    <module>module1</module> 
    <module>module2</module> 
    <module>module3</module> 
</modules> 

Inoltre le voci madri nei moduli possono essere semplificati e in questo modo:

<parent> 
    <groupId>com.cws.cs.lendingsimulationservice</groupId> 
    <artifactId>parent-pom</artifactId> 
    <version>1.0.6</version> 
</parent> 

... che mi porta al punto successivo:

Se tutto il tuo progetto attuale d efine il loro genitore come sopra questo è semplicemente sbagliato, perché cercherà di trovare il genitore all'interno del repository e non in una cartella di livello superiore. In altre parole, questo è causa di gran parte dei vostri problemi con il rilascio ecc

Se vogliamo risolvere questo problema che deve assomigliare a questo che non posso raccomandare:

<parent> 
    <groupId>com.cws.cs.lendingsimulationservice</groupId> 
    <artifactId>parent-pom</artifactId> 
    <version>1.0.6</version> 
    <relativePath>../parent-pom/pom.xml</relativePath> 
</parent> 

Un'altra cosa che ho osservare che non si usa SNAPTSHOT che sarà sostituito dal plugin di rilascio durante la fase di rilascio. E in rapporto a quella cambierà automaticamente tutte le versioni nei genitori appropriate ecc

Nel caso ideale i moduli dovrebbe essere simile a questo:

<parent> 
    <groupId>com.cws.cs.lendingsimulationservice</groupId> 
    <artifactId>parent-pom</artifactId> 
    <version>1.0.6</version> 
</parent> 

<artifactId>module-1</artifactId> 
<!-- No Version or groupId --> 

Causa tutti i moduli erediteranno la versione e groupId dal loro genitore . A volte è utile o necessario modificare un modulo groupId ma è un'eccezione.

Su cosa rileggo riguarda la versione separata del genitore. Questo semplicemente non ha senso, perché è il genitore dei loro moduli quindi mettilo nella stessa struttura e, naturalmente, lo stesso VCS.

Se si vuole fare in alcune versioni di configurazione/plugins, dipendenze, che dovrebbero essere utilizzate per altri progetti, nonché di fare un separato aziendale pom.xml che è un progetto separato e sarà rilasciato separatamente ecc

Dopo aver finito la tua struttura cambia puoi semplicemente andare nella directory genitore-pom e fare mvn clean package o mvn release:prepare release:perform da quella cartella e tutto sarà più semplice.

+2

Sfortunatamente, la ristrutturazione per avere una struttura ad albero non è un'opzione, dato il modo in cui RTC e i componenti/moduli sono stati impostati per questo progetto. Quindi devo vivere con l'attuale strcuture/layout e sfruttare al meglio la situazione. Inserire la versione a livello genitore da ereditare da tutti i moduli figlio significa essenzialmente la ricostruzione/ripetizione/ridistribuzione di tutti i moduli (che possono essere costosi) anche se c'era solo una modifica in un singolo modulo. Essenzialmente, perdo la possibilità di eseguire in versione indipendente un modulo. Sebbene io sia d'accordo; risolverebbe il mio problema di implementazione. –

+1

Se ti piace continuare a combattere contro il tuo è il tuo turno, ma ti consiglio di cambiare la struttura perché ti renderà la vita più facile. Ma se l'idea di distribuire ogni modulo separatamente non ha senso. O sono imparentati, non lo sono. Se non lo sono, dovresti renderli veramente separati e non usare una build multi-modulo. – khmarbaise

+1

Non riesco a capire come eseguire questa operazione con il numero di versione definito solo nell'editoriale. Nella mia attuale configurazione, posso cambiare l'interfaccia in un modulo senza influenzare il resto della build fino a quando non è il momento di reintegrare la nuova versione. Con la versione solo nel genitore, la modifica dell'interfaccia di un modulo interromperà il resto della compilazione poiché tutti i moduli si baseranno sull'albero di origine e non su un binario pre-distribuito. Come evito questo problema? Ho ancora bisogno di una versione individuale di ogni modulo, no? –

2

Se pubblichi il tuo POM, dovrai rilasciare qualsiasi aggiornamento ma non devi modificare manualmente le versioni POM: puoi aggiornare le versioni automaticamente utilizzando il plug-in di versioni o il plugin di rilascio. Tendo a preferire il plug-in di rilascio poiché si impegnerà anche su SCM.

mvn versions:set 

http://mojo.codehaus.org/versions-maven-plugin/

mvn release:prepare release:perform 

http://maven.apache.org/plugins/maven-release-plugin/

tuo repository manager possono inoltre consentire sovrascrivendo una versione esistente, ma è meglio la pratica di rilasciare solo una nuova versione.

Tendo a preferire la struttura del modulo piatto in quanto consente l'utilizzo della cartella principale per memorizzare file comuni, ad es. configurazione stile check. Trovo anche utile condividere l'id di gruppo in tutti i moduli, quindi denominare la directory del modulo come l'artefatto.

+0

Non ho usato il plugin di rilascio da un po 'di tempo, ma non capisco come risolverà il mio problema quando avrò bisogno di far progredire un singolo modulo in una nuova versione. Se il modulo3 necessita di aggiornamento (va da 1.1 a 1.2-SNAPSHOT), e module1 dipende da module3, quindi aggiorno module3 pom, parent-pom property, parent-pom version, module3 parent e infine module1 parent-version e module1 version. Come può il plugin di rilascio realizzare tutto questo per me? Si noti che a questo punto non è necessario modificare il modulo2. –

+0

Il plug-in delle versioni dovrebbe essere in grado di aggiornare le dipendenze per te, quindi puoi semplicemente eseguire il commit e distribuire le nuove risorse. – cvanes

2

Si stanno presentando requisiti contraddittori. Vuoi ristrutturare il tuo progetto ma non puoi spostare le cose. Si desidera semplificare i cicli di distribuzione e rilascio ma non si desidera utilizzare una singola versione.

Dato che i cambiamenti in un modulo avranno inevitabilmente effetto su tutti i moduli dipendenti, utilizzerei uno schema di versioning semplice in cui tutti i sottomoduli ereditano la versione del genitore. rilascio di esperti: i cicli di preparazione e rilascio diventano semplici. Utilizzare le note di rilascio per tenere traccia delle modifiche e giustificare l'eliminazione dei test non necessari dei moduli non modificati (le modifiche a una versione non modificano l'output di build/binario del processo di compilazione in modo da poterlo utilizzare come argomento principale).

Buona fortuna per il tuo progetto.

Problemi correlati