Gestione delle dipendenze multi-module con Plugin di Assembly Maven
-
14-11-2019 - |
Domanda
Io uso MAVEN Plugin Assembly per creare un Assembly per il mio progetto multi-module. Esistono due applicazioni separate costruite da questo progetto multi-module, ciascuna con un insieme separato di dipendenze. Ho effettuato un descrittore di assemblaggio personalizzato che assembla due directory (per ogni applicazione) con le build di moduli e le loro rispettive dipendenze. Fa tutto bene, ma una cosa - mette le dipendenze per entrambi i moduli l'assemblea dell'altro.
Di seguito è riportata una versione semplificata del mio progetto, che ha esattamente lo stesso comportamento.
Considera un progetto costituito da due moduli e un modulo di assemblaggio:
APP
module1
module2
assembly
.
Ho aggiunto le dipendenze puramente 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 genitore POM:
<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>
.
Modulo1 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>
.
Assembly 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 assemblaggio:
<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 puoi vedere, il montaggio è vincolante alla fase del pacchetto. Quindi, quando eseguo
mvn package
.
Dalla directory genitore, ho il seguente assembly
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
.
Fondamentalmente, il problema qui è che il modulo1 non dipende dal daemon comuni, ma il plugin dell'assembly ha incluso la dipendenza. Allo stesso modo, con Module2 e Commons-CLI.
Qualcuno può spiegare perché il plugin dell'assembly si comporta in questo modo?
A quale sarebbe una soluzione?
Soluzione
I've always had similar experiences using the assembly plugin with multi-module projects where the end result wasn't what I expected. I hope someone else can provide a more accurate answer as to why that's happening and how best to use those two concepts in tandem.
That said, a possible work-around would be to have module1 and module2 generate their own assembly artifacts which contain their respective jars and dependencies. Then you can modify the assembly sub-module pom file to have dependencies on the generated distribution artifacts from its sibling modules and then unpack those into a new assembly.
In both Module1 and Module2's pom files you can add an assembly plugin configuration to your package phase much like you did with the assembly sub-module.
<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 would have a src/main/assembly/descriptor.xml like this
<assembly>
<id>distribution</id>
<includeBaseDirectory>false</includeBaseDirectory>
<formats>
<format>zip</format>
</formats>
<dependencySets>
<dependencySet>
<outputDirectory>module1</outputDirectory>
<unpack>false</unpack>
</dependencySet>
</dependencySets>
</assembly>
And Module2 will have a similar src/main/assembly/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>
Then in the assembly/pom.xml you would add the Module 1 and 2 zip artifacts as dependencies
<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>
...and trim up the assembly/src/main/assembly/descriptor.xml file to look like this
<assembly>
<id>distribution</id>
<includeBaseDirectory>false</includeBaseDirectory>
<formats>
<format>dir</format>
</formats>
<dependencySets>
<dependencySet>
<useTransitiveDependencies>false</useTransitiveDependencies>
<unpack>true</unpack>
</dependencySet>
</dependencySets>
</assembly>
Like I said this would be one possible work around and unfortunately adds a significant amount of additional XML configuration to your build process. But it works.