Maven - Using the Assembly plugin to package dependencies from multiple projects into one file - maven

I’m working on a project that is made up of multiple other projects. It has the following structure:
MainProject
--projectA
--projectB
--projectC
--projectD
--parent
--projectE
...
--projectX
As you can see the parent is amongst the others. I’m not sure if this is unusual or not but it is the way it is and I have to just work with it.
I’m looking to use the Assembly plugin to get the dependencies from each of the sub projects and zip them up all within one folder. So for example, I want a zip file containing a folder which contains all of the unpacked dependencies of the children projects.
This is what I have so far:
assembly.xml (this is in the parent project)
[...]
<id>package</id>
<formats>
<format>zip</format>
</formats>
<includeBaseDirectory>false</includeBaseDirectory>
<moduleSets>
<moduleSet>
<includes>
<include>com.example:../one</include>
<include>com.example2:../two</include>
<include>com.exampleX:../three</include>
</includes>
<binaries>
<outputDirectory>/library/jars</outputDirectory>
<unpack>false</unpack>
</binaries>
</moduleSet>
</moduleSets>
<dependencySets>
<dependencySet>
<unpack>false</unpack>
<scope>runtime</scope>
<outputDirectory>library/jars</outputDirectory>
</dependencySet>
</dependencySets>
<fileSets>
<fileSet>
<excludes>
<exclude>**.xml</exclude>
</excludes>
</fileSet>
</fileSets>
</assembly>
and this is in the parent pom.xml
[...]
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.4</version>
<executions>
<execution>
<id>make-assembly</id>
<phase>package</phase>
<goals>
<goal>assembly</goal>
</goals>
</execution>
</executions>
<configuration>
<descriptors>
<descriptor>assembly.xml</descriptor>
</descriptors>
</configuration>
</plugin>
[...]
When I run a mvn clean install from cmd the build is successful. It does not however create a zip file containing my library/jars directory which should then contain all of the dependencies from each of the projects. It simply creates zips in each project. These zips do not contain the directory I want or any dependencies, they are simply zips of the each project directory. Can anyone see what I am doing wrong?

Related

In Maven, can I pack JEE project in Zip archive together SQL scripts?

Hello everyone first of all,
Suppose I have a JEE project contents some modules and a 'sql' folder inside:
I build all modules to a 'integration-version.ear' archive file.
There is the content of my target:
Using Maven, can I build something like this:
There is the ‘3.15’ folder includes some SQL files from the same folder of my project.
Is it possible? What is configuration of Maven needed?
Note:
The original question was like: "In Maven, can I pack JEE project in RAR archive together SQL scripts?" but now the question is changed because RAR is a proprietary format and each tools that create RAR files must be commercially licensed.
Solution:
Using build-helper-maven-plugin
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>build-helper-maven-plugin</artifactId>
<version>3.0.0</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>parse-version</goal>
</goals>
<configuration>
<propertyPrefix>parsedVersion</propertyPrefix>
</configuration>
</execution>
...
Using maven-assembly-plugin
pom.xml
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.6</version>
<inherited>false</inherited>
<configuration>
<descriptors>
<descriptor>${project.basedir}/../assembly.xml</descriptor>
</descriptors>
</configuration>
...
assembly.xml
<assembly xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0 http://maven.apache.org/xsd/assembly-1.1.0.xsd">
<id>release</id>
<baseDirectory>${file.separator}</baseDirectory>
<formats>
<format>zip</format>
</formats>
<fileSets>
<fileSet>
<directory>${project.basedir}/../sql/migrates/${parsedVersion.majorVersion}.${parsedVersion.minorVersion}</directory>
<outputDirectory>/scripts-${parsedVersion.majorVersion}.${parsedVersion.minorVersion}</outputDirectory>
<includes>
<include>**/*.sql</include>
</includes>
</fileSet>
</fileSets>
<dependencySets>
<dependencySet>
<outputFileNameMapping>${build.finalName}.${packaging}</outputFileNameMappin>
<includes>
<include>*:ear</include>
</includes>
</dependencySet>
</dependencySets>
</assembly>
There are 2 Maven plugins which can do that: maven-assembly-plugin and maven-rar-plugin
If you want to use maven-rar-plugin, i would create a new module with packaging rar and configure the plugin.
I personally think maven-assembly-plugin is easier to use.

Maven Create Jar and exclude Files

I am trying to create a runnable Jar file. I have to create a Jar of only one single java class (MyClass which is under the folder structure src/main/java/org/miso/mcs/util/MyClass) and exclude others. I am able to create to JAR but it has everything.
I am using mvn clean package assembly:single command to create Jar.
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<configuration>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
<archive>
<manifest>
<mainClass>org.miso.mcs.util.MyClass</mainClass>
</manifest>
</archive>
<resources>
<resource>
<classesDirectory>src/main/java/org/miso/mcs/util</classesDirectory>
<includes>
<include>/*MyClass*</include>
</includes>
<excludes>
<exclude>/*</exclude>
</excludes>
</resource>
</resources>
</configuration>
</plugin>
You won't be able to do that by using the predefined jar-with-dependencies descriptor. However, we can make our own assembly descriptor for that:
<assembly xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.3"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.3 http://maven.apache.org/xsd/assembly-1.1.3.xsd">
<id>jar-with-dependencies</id>
<formats>
<format>jar</format>
</formats>
<includeBaseDirectory>false</includeBaseDirectory>
<dependencySets>
<dependencySet>
<outputDirectory>/</outputDirectory>
<useProjectArtifact>false</useProjectArtifact>
<unpack>true</unpack>
</dependencySet>
<dependencySet>
<outputDirectory>/</outputDirectory>
<useProjectArtifact>false</useProjectArtifact>
<useProjectAttachments>true</useProjectAttachments>
<includes>
<include>${project.groupId}:${project.artifactId}:jar:classes:${project.version}</include>
</includes>
<unpack>true</unpack>
<unpackOptions>
<excludes>
<exclude>%regex[org\/miso\/(?!mcs\/util\/MyClass).*]</exclude>
</excludes>
</unpackOptions>
</dependencySet>
</dependencySets>
</assembly>
unpackOptions allows to control the content the unpacked dependencies in the JAR. In this case, we are excluding everything under the org.miso package (which I assume are the classes of your project) and we're only including the class you're interested in (org.miso.mcs.util.MyClass). This will result in a runnable JAR with only the specified class of your project.
Since your project is a WAR, it is a little more complicated. The first dependency set declares all the dependencies of the project and unpacks them. The second only uses the projects attachments and includes only the classes attachment built by the maven-war-plugin.
If you save that snippet into a file called assembly.xml located under src/assembly, your POM will then look like:
<plugin>
<artifactId>maven-war-plugin</artifactId>
<version>2.6</version>
<configuration>
<attachClasses>true</attachClasses>
</configuration>
</plugin>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.6</version>
<executions>
<execution>
<id>make-assembly</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
<configuration>
<descriptors>
<descriptor>src/assembly/assembly.xml</descriptor>
</descriptors>
<archive>
<manifest>
<mainClass>org.miso.mcs.util.MyClass</mainClass>
</manifest>
</archive>
</configuration>
</execution>
</executions>
</plugin>
With such a configuration, you just need to invoke Maven with mvn clean install and it will correctly generate the JAR. Then, you can launch that JAR with java -jar name-of-jar.jar.

How to zip only specific directories using maven assembly plugin

I am using maven-assembly-plugin to create a zip file of the project when building the project. It is successful. Now what I want is to zip only specific directories in the project.
This is the code for plugin in my pom which I used previously.
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<executions>
<execution>
<id>make shared resources</id>
<goals>
<goal>single</goal>
</goals>
<phase>package</phase>
<configuration>
<descriptors>
<descriptor>resource.xml</descriptor>
</descriptors>
</configuration>
</execution>
</executions>
</plugin>
And the resource.xml file is as follows.
<assembly>
<id>resources</id>
<formats>
<format>zip</format>
</formats>
<includeBaseDirectory>false</includeBaseDirectory>
<fileSets>
<fileSet>
<!-- Since it bundles all the units -->
<directory></directory>
<outputDirectory>/project</outputDirectory>
<excludes>
<exclude>pom.xml</exclude>
<exclude>*.iml</exclude>
<exclude>*.jar</exclude>
<exclude>**/src/**</exclude>
<exclude>**/target/**</exclude>
<exclude>resource.xml</exclude>
</excludes>
</fileSet>
</fileSets>
</assembly>
I want to zip only some directories of the project in the maven build.
As an example I have following folder structure in the project.
project
|_directories
|_dir1
|_ ....
|_dir2
|_ ....
|_dir3
|_ ....
|_pom.xml
What I want is make zip file which only include the directories folder. When extracting my zip file that should only contain the four directories in it.
How can I achieve this?
Does the maven-assembly-plugin is enough to do this or should I create a mojo?
You misused directory and outputDirectory.
directory is the path in your project where the files to be zipped are taken from (so it should be directories in your case), outputDirectory the folder inside the generate zip file, where the fileset is place (since you do not want the toplevel directory, it should be /):
<assembly>
<id>resources</id>
<formats>
<format>zip</format>
</formats>
<includeBaseDirectory>false</includeBaseDirectory>
<fileSets>
<fileSet>
<!-- Take everything inside the directories folder -->
<directory>directories</directory>
<!-- And place it inside the root of the zip file -->
<outputDirectory>/</outputDirectory>
</fileSet>
</fileSets>
</assembly>

Assembly plugin generating 2 jars. One with classfiles. One with dependencies

I am having trouble building a jar using the assembly plugin. I have a bunch of system jar files that I want bundled alongside class files of the project.
I was looking to do something like:
final
- lib
- system.jar
- system1.jar
- com
- servlet
-- etc
I have tried to use the assembly plugin but it generates 2 jars. One with just the lib with my jars and another with the class files.
I have read through the assembly docs but I must be missing something.
Here is the build element I have in my pom.xml
<dependency>
<groupId>jackson-mapper-asl</groupId>
<artifactId>jackson-mapper-asl</artifactId>
<version>1.9.4</version>
<scope>system</scope>
<systemPath>${project.basedir}/lib/jackson-mapper-asl-1.9.4-sc1.jar</systemPath>
</dependency>
//... etc
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.4</version>
<executions>
<execution>
<id>final-jar</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
<configuration>
<descriptors>
<descriptor>assembly.xml</descriptor>
</descriptors>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
This is my assembly file (assembly.xml)
<assembly>
<id>distribution</id>
<formats>
<format>jar</format>
</formats>
<includeBaseDirectory>false</includeBaseDirectory>
<dependencySets>
<dependencySet>
<useProjectArtifact>false</useProjectArtifact>
<useTransitiveDependencies>true</useTransitiveDependencies>
<unpack>false</unpack>
<scope>system</scope>
<outputDirectory>lib</outputDirectory>
<includes />
</dependencySet>
</dependencySets>
</assembly>
Any idea how I can merge these jars together?
You would usually have a much simpler layout, such as:
final
- lib
-system.jar
-system1.jar
-project.jar
I.e. the project itself is a jar too, and included in the lib. In this case just add <useProjectArtifact>true/>useProjectArtifact> to the dependencySet.
If you really, really want to have classes copied in directly, try adding a fileset to the assembly, copying from target/classes into your root location
<fileSets>
<fileSet>
<directory>${project.build.directory}</directory>
<outputDirectory>/</outputDirectory>
</fileSet>
</fileSets>

How to package an assembly in Maven by moving resources out of the war?

Our project is set up to package a WAR and this works great for local development:
<plugin>
<artifactId>maven-war-plugin</artifactId>
<version>2.3</version>
<executions>
<execution>
<id>package-war</id>
<phase>package</phase>
<goals>
<goal>war</goal>
</goals>
...
Included in this war, is a mapper file and logback file used by the application, which lives under: src/main/resources/logback.xml and /src/main/resources/mappers/our-mapper.xml.
In building the war, these files get sent where we expect and want them to be, under our.war/WEB-INF/classes/logback.xml and our.war/WEB-INF/classes/mappers/our-mapper.xml
When we package our assembly to hand off for deployment, we need to have these files separated out of the war, which we do using our assembly descriptor:
<assembly>
<formats>
<format>tar.gz</format>
</formats>
<includeBaseDirectory>false</includeBaseDirectory>
<files>
<file>
<source>target/${build.finalName}.war</source>
<outputDirectory>${tomcat-instance}/webapps</outputDirectory>
</file>
<file>
<source>src/main/resources/logback.xml</source>
<outputDirectory>${tomcat-instance}/resources/</outputDirectory>
</file>
</files>
<fileSets>
<fileSet>
<directory>src/main/resources/mapper</directory>
<outputDirectory>${tomcat-instance}/resources/mapper/</outputDirectory>
<includes>
<include>**/*</include>
</includes>
</fileSet>
</fileSets>
</assembly>
And configured in Maven with:
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<configuration>
<descriptors>
<descriptor>src/main/resources/our-assembly.xml</descriptor>
</descriptors>
</configuration>
<executions>
<execution>
<id>make-assembly</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
This constructs the assembly, but my concern is the logback.xml and mappers/our-mapper.xml files are still contained inside the war which is contained inside the assembly.tar.gz.
Is it possible to keep the configuration where the war outside the assembly contains the .xml files as it already does, but also have the war that goes inside the assembled .tar.gz assembly exclude these same files so they don't appear twice on the classpath?
Thanks in advance for any help.
You've probably found a solution or workaround to this problem now - however, I was intrigued to know whether this was possible so I created a small test project with the same file structure as you described.
I managed to get this project to build out the two war files - with the one outside the assembly containing the .xml files, and the one inside the assembly excluding the .xml files. I achieved this by creating an additional assembly that builds a second temporary war file which explicitly excludes the .xml files. Then the existing assembly includes this new war file, rather than the default war.
The new assembly war-assembly.xml looks like this:
<assembly>
<id>temp</id>
<formats>
<format>war</format>
</formats>
<includeBaseDirectory>false</includeBaseDirectory>
<fileSets>
<fileSet>
<directory>target/${build.finalName}</directory>
<outputDirectory>/</outputDirectory>
<includes>
<include>**/*</include>
</includes>
<excludes>
<exclude>**/logback.xml</exclude>
<exclude>**/mapper/*</exclude>
</excludes>
</fileSet>
</fileSets>
</assembly>
The existing assembly is then modified to include the new war file:
<assembly>
<formats>
<format>tar.gz</format>
</formats>
<includeBaseDirectory>false</includeBaseDirectory>
<files>
<file>
<source>target/${build.finalName}-temp.war</source>
<outputDirectory>${tomcat-instance}/webapps</outputDirectory>
<destName>target/${build.finalName}.war</destName>
</file>
<file>
<source>src/main/resources/logback.xml</source>
<outputDirectory>${tomcat-instance}/resources/</outputDirectory>
</file>
</files>
<fileSets>
<fileSet>
<directory>src/main/resources/mapper</directory>
<outputDirectory>${tomcat-instance}/resources/mapper/</outputDirectory>
<includes>
<include>**/*</include>
</includes>
</fileSet>
</fileSets>
</assembly>
And then the pom.xml is modified to reference the new assembly before the existing assembly.
<descriptors>
<descriptor>src/main/resources/war-assembly.xml</descriptor>
<descriptor>src/main/resources/our-assembly.xml</descriptor>
</descriptors>
That seemed to work ok. It did leave the -temp war file lying around in the target folder which could potentially be removed to save any confusion.

Resources