8

Uso il plug-in di assembly Maven per creare un assembly per il mio progetto multi-modulo. Esistono due applicazioni separate create da questo progetto multi-modulo, ognuna con un insieme separato di dipendenze. Ho creato un descrittore di assembly personalizzato che assembla due directory (per ogni applicazione) con le build del modulo e le rispettive dipendenze. Fa tutto bene, ma una cosa: mette le dipendenze per entrambi i moduli l'un l'altro.Gestione delle dipendenze multi-modulo con il plug-in di assembly Maven

Quanto segue è una versione semplificata del mio progetto, che ha esattamente lo stesso comportamento.

consideri un progetto costituito da due moduli e un modulo di montaggio: dipendenze

APP 
    module1 
    module2 
    assembly 

ho aggiunto semplicemente per la dimostrazione:

com.test.app:module1:jar:1.0 
\- commons-cli:commons-cli:jar:1.2:compile 

com.test.app:module2:jar:1.0 
\- commons-daemon:commons-daemon:jar:1.0.8:compile 

Ecco il POM genitore:

<project> 
    <modelVersion>4.0.0</modelVersion> 

    <groupId>com.test</groupId> 
    <artifactId>app</artifactId> 
    <version>1.0</version> 
    <packaging>pom</packaging> 

    <modules> 
    <module>module1</module> 
    <module>module2</module> 
    <module>assembly</module> 
    </modules> 
</project> 

module1 POM:

<project> 
    <parent> 
    <groupId>com.test</groupId> 
    <artifactId>app</artifactId> 
    <version>1.0</version> 
    </parent> 

    <modelVersion>4.0.0</modelVersion> 

    <groupId>com.test.app</groupId> 
    <artifactId>module1</artifactId> 
    <version>1.0</version> 
    <packaging>jar</packaging> 

    <dependencies> 
    <dependency> 
     <groupId>commons-cli</groupId> 
     <artifactId>commons-cli</artifactId> 
     <version>1.2</version> 
    </dependency> 
    </dependencies> 
</project> 

Module2 POM:

<project> 
    <parent> 
    <groupId>com.test</groupId> 
    <artifactId>app</artifactId> 
    <version>1.0</version> 
    </parent> 

    <modelVersion>4.0.0</modelVersion> 

    <groupId>com.test.app</groupId> 
    <artifactId>module2</artifactId> 
    <version>1.0</version> 
    <packaging>jar</packaging> 

    <dependencies> 
    <dependency> 
     <groupId>commons-daemon</groupId> 
     <artifactId>commons-daemon</artifactId> 
     <version>1.0.8</version> 
    </dependency> 
    </dependencies> 
</project> 

assemblaggio POM:

<project> 
    <parent> 
    <groupId>com.test</groupId> 
    <artifactId>app</artifactId> 
    <version>1.0</version> 
    </parent> 

    <modelVersion>4.0.0</modelVersion> 

    <groupId>com.test.app</groupId> 
    <artifactId>assembly</artifactId> 
    <version>1.0</version> 
    <packaging>pom</packaging> 

    <build> 
    <plugins> 
     <plugin> 
     <artifactId>maven-assembly-plugin</artifactId> 
     <version>2.2.2</version> 

     <executions> 
      <execution> 
      <id>make-assembly</id> 
      <phase>package</phase> 

      <goals> 
       <goal>single</goal> 
      </goals> 
      </execution> 
     </executions> 

     <configuration> 
      <appendAssemblyId>false</appendAssemblyId> 

      <descriptors> 
      <descriptor>src/main/assembly/descriptor.xml</descriptor> 
      </descriptors> 
     </configuration> 
     </plugin> 
    </plugins> 
    </build> 
</project> 

E, infine, il descrittore di montaggio:

<assembly> 
    <id>distribution</id> 
    <includeBaseDirectory>false</includeBaseDirectory> 

    <formats> 
    <format>dir</format> 
    </formats> 

    <moduleSets> 
    <moduleSet> 
     <useAllReactorProjects>true</useAllReactorProjects> 

     <includes> 
     <include>com.test.app:module1:jar</include> 
     </includes> 

     <binaries> 
     <outputDirectory>module1</outputDirectory> 
     <unpack>false</unpack> 

     <dependencySets> 
      <dependencySet> 
      <unpack>false</unpack> 
      </dependencySet> 
     </dependencySets> 
     </binaries> 
    </moduleSet> 

    <moduleSet> 
     <useAllReactorProjects>true</useAllReactorProjects> 

     <includes> 
     <include>com.test.app:module2:jar</include> 
     </includes> 

     <binaries> 
     <outputDirectory>module2</outputDirectory> 
     <unpack>false</unpack> 

     <dependencySets> 
      <dependencySet> 
      <unpack>false</unpack> 
      </dependencySet> 
     </dependencySets> 
     </binaries> 
    </moduleSet> 
    </moduleSets> 
</assembly> 

Come si può vedere, il montaggio, è strettamente legato al pacchetto di fase . Così, quando eseguo

mvn package 

dalla directory padre, ho il seguente assemblaggio

module1/ 
    commons-cli-1.2.jar 
    commons-daemon-1.0.8.jar 
    module1-1.0.jar 
module2/ 
    commons-cli-1.2.jar 
    commons-daemon-1.0.8.jar 
    module2-1.0.jar 

In sostanza, il problema qui è che module1 non dipende commons-daemon, ma il plugin di montaggio ha incluso la dipendenza Allo stesso modo, con module2 e commons-cli.

Qualcuno può spiegare perché il plug-in di assembly si comporta in questo modo?

Una soluzione?

+0

Non mi aspetterei questo strano comportamento da 'maven-assembly-plugin' ... Sei sicuro che non ci siano dipendenze trasferite dal tuo genitore al tuo progetto di assemblaggio? Mostraci l'albero delle dipendenze generato per il progetto di assemblaggio. –

+0

L'albero delle dipendenze per il modulo di assemblaggio è ovviamente vuoto, poiché il suo POM non ha dichiarazioni di dipendenza. – sertsy

risposta

10

Ho sempre avuto esperienze simili utilizzando il plug-in di assembly con progetti multi-modulo in cui il risultato finale non era quello che mi aspettavo. Spero che qualcun altro possa fornire una risposta più precisa sul motivo per cui sta accadendo e su come utilizzare al meglio questi due concetti in tandem.

Detto questo, una possibile soluzione sarebbe quella di fare in modo che module1 e module2 generino i propri artefatti di assembly che contengono i rispettivi jar e dipendenze. Quindi è possibile modificare il file pom del sottomodulo dell'assieme per avere dipendenze dalle risorse generate dalla distribuzione dai suoi moduli fratelli e quindi decomprimerli in un nuovo assieme.

In entrambi i file pom di Module1 e Module2 è possibile aggiungere una configurazione di plug-in di assembly alla fase del pacchetto in modo analogo a quanto fatto con il sottomodulo di assemblaggio.

<build> 
    <plugins> 
     <plugin> 
     <artifactId>maven-assembly-plugin</artifactId> 
     <version>2.2.2</version> 

     <executions> 
      <execution> 
      <id>make-assembly</id> 
      <phase>package</phase> 
      <goals> 
       <goal>single</goal> 
      </goals> 
      </execution> 
     </executions> 

     <configuration> 
      <descriptors> 
      <descriptor>src/main/assembly/descriptor.xml</descriptor> 
      </descriptors> 
     </configuration> 
     </plugin> 
    </plugins> 
    </build> 

Module1 avrebbe uno src/main/montaggio/descriptor.xml come questo

<assembly> 
    <id>distribution</id> 
    <includeBaseDirectory>false</includeBaseDirectory> 

    <formats> 
    <format>zip</format> 
    </formats> 

    <dependencySets> 
    <dependencySet> 
     <outputDirectory>module1</outputDirectory> 
     <unpack>false</unpack> 
    </dependencySet> 
    </dependencySets> 
</assembly> 

E Module2 avrà un simile src/main/montaggio/descriptor.xml

<assembly> 
    <id>distribution</id> 
    <includeBaseDirectory>false</includeBaseDirectory> 

    <formats> 
    <format>zip</format> 
    </formats> 

    <dependencySets> 
    <dependencySet> 
     <outputDirectory>module2</outputDirectory> 
     <unpack>false</unpack> 
    </dependencySet> 
    </dependencySets> 
</assembly> 

Quindi nell'assembly/pom.xml dovresti aggiungere gli artefatti del modulo 1 e 2 come dipendenze

<dependencies> 
    <dependency> 
     <groupId>com.test.app</groupId> 
     <artifactId>module1</artifactId> 
     <version>1.0</version> 
     <type>zip</type> 
     <classifier>distribution</classifier> 
    </dependency> 
    <dependency> 
     <groupId>com.test.app</groupId> 
     <artifactId>module2</artifactId> 
     <version>1.0</version> 
     <type>zip</type> 
     <classifier>distribution</classifier> 
    </dependency> 
    </dependencies> 

... e tagliare il montaggio/src file/montaggio/descriptor.xml/principale a guardare come questo

<assembly> 
    <id>distribution</id> 
    <includeBaseDirectory>false</includeBaseDirectory> 

    <formats> 
    <format>dir</format> 
    </formats> 

    <dependencySets> 
    <dependencySet> 
     <useTransitiveDependencies>false</useTransitiveDependencies> 
     <unpack>true</unpack> 
    </dependencySet> 
    </dependencySets> 

</assembly> 

Come ho detto questo sarebbe un possibile lavoro intorno e aggiunge purtroppo una quantità significativa di configurazione XML aggiuntiva per il processo di compilazione. Ma funziona.

+1

Grazie, per una risposta, Keith. Per quanto ho capito, nell'esempio che hai mostrato, se eseguo 'mvn package' dal padre POM, prima assemblerebbe module1, quindi module2 e il modulo assembly di assemblaggio metterebbe insieme i primi due assembly. Tuttavia, questo divora lo scopo di un modulo di assemblaggio separato. L'idea alla base di un modulo separato per un assembly è assicurarsi che tutti i moduli siano stati creati al momento dell'assemblaggio. – sertsy

+0

Suppongo di avere un altro modulo - module3 che è una dipendenza per module1. Se nella fase del pacchetto di module1, module3 non è ancora stato creato, module1 non sarà in grado di produrre un assembly (poiché l'assembly è legato a una fase del pacchetto). Questo è il motivo per cui il modulo di assemblaggio è sempre posizionato per ultimo, per assicurarsi che altri moduli siano già stati creati. Quello che suggerisci dovrebbe funzionare nell'esempio che ho dato, ma, credo, non è la strada giusta. Spero di aver chiarito i miei pensieri. – sertsy

+1

L'ordine dei moduli elencati nel pom principale non è rilevante. Il reattore Maven costruirà tutte le dipendenze nell'ordine di compilazione corretto, che sa come fare perché l'assembly pom ha module1 e module2 elencati come dipendenze. Anche se si aggiunge module3 come dipendenza per module1, verrà prima creato module3, quindi module1, module2, terminando con assembly. – Keith