How to have custom properties for the Maven Assembly Plugin? - maven

I have a Java project that is compiled using Maven and at the end maven-assembly-plugin is used to pack compiled JAR files, DLLs etc into 10 different ZIP files. Every ZIP file is for different environment (has different DLLs), but their content is generally identical.
Now I use 10 different assembly.xml files that are used to create those 10 ZIP files.
Problem is that those XMLs are almost identical, the only difference is 1 word in path of DLLs. Example of such a file: (In reality it is much longer)
<assembly>
<id>{someVariable}</id>
<formats>
<format>zip</format>
</formats>
<fileSets>
<!-- Copying DLLs: -->
<fileSet>
<directory>target/dll/{someVariable}</directory>
<outputDirectory>dll</outputDirectory>
<includes>
<include>*.dll</include>
</includes>
</fileSet>
</fileSets>
</assembly>
As you can see, I would like to use {someVariable} on more places which is the desired functionality but I cannot make it work. Hopefully it is possible and this is the core of my question. I want to use the same assembly.xml file and execute it 10x always with different value of {someVariable} like this:
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<executions>
<execution>
<id>make-the-zip</id>
<goals>
<goal>single</goal>
</goals>
<phase>package</phase>
<configuration>
<descriptors>
<descriptor>src/assembly/myCommonAssembly.xml</descriptor>
</descriptors>
<properties>
<someVariable>my-value</someVariable>
</properties>
</configuration>
</execution>
</executions>
</plugin>
Is it possible? FYI: Section <properties> does not work, I am just trying to show what I would like to do.
I know that I can create the properties in poml.xml and use them in assembly.xml but it does not solve my problem, because I still would have to create 10 different assembly.xml files.
This is the best advice I have found, but it is not the answer.

You can use the iterator-maven-plugin, in order to iterate over all your different property values. This Mojo has an iterator goal which enables to iterate over a set of given properties, and adds them as as Maven property:
The iterator-maven-plugin will inject the current value as a property which means you can use this property to parameterize your build.
In your case, you could have:
<plugin>
<groupId>com.soebes.maven.plugins</groupId>
<artifactId>iterator-maven-plugin</artifactId>
<version>0.4</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>iterator</goal>
</goals>
<configuration>
<items>
<item>my-value-1</item>
<item>my-value-2</item>
<item>my-value-3</item>
</items>
<pluginExecutors>
<pluginExecutor>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.6</version>
</plugin>
<goal>single</goal>
<configuration>
<descriptors>
<descriptor>${project.basedir}/src/assembly/myCommonAssembly.xml</descriptor>
</descriptors>
</configuration>
</pluginExecutor>
</pluginExecutors>
</configuration>
</execution>
</executions>
</plugin>
At the package phase, this configuration will iterate over the 3 given values, my-value-1 to my-value-3, and execute each time the Maven Assembly Plugin. For a given execution, it is possible to retrieve the current iterated value with ${item}. As such, your common assembly descriptor would become:
<assembly>
<id>${item}</id>
<formats>
<format>zip</format>
</formats>
<fileSets>
<!-- Copying DLLs: -->
<fileSet>
<directory>target/dll/${item}</directory>
<outputDirectory>dll</outputDirectory>
<includes>
<include>*.dll</include>
</includes>
</fileSet>
</fileSets>
</assembly>

Related

Can I change the root directory for dir format maven assemblies?

I'm using an assembly descriptor of the "dir" format to produce an exploded distributable. Currently this places the files I include in a directory named "target/${project.build.finalName}".
I would ideally like this directory to be named differently. Ideally "target/${project.artifactId}", essentially dropping the version component.
The reason for wanting this change is that I'm going to need to refer to files in that archive in a discrete pipeline step, and having the version in the path presents maintainability issues.
Simplified version of the assembly descriptor provided:
<assembly>
<id>preparation</id>
<formats>
<format>dir</format>
</formats>
<includeBaseDirectory>false</includeBaseDirectory>
<fileSets>
<fileSet>
<directory>${project.basedir}/src/main/resources</directory>
<outputDirectory/>
</excludes>
</fileSet>
</fileSets>
</assembly>
Where I currently end up with a root dir like:
target/myArtifactId-1.0.0-SNAPSHOT/assembledResources
and I would like to arrive at
target/myArtifactId/assembledResources
baseDirectory and friends only affect the paths within the root directory, still leaving me with a path which includes a version number, like:
target/myArtifactId-1.0.0-SNAPSHOT/myArtifactId/assembledResources
In your maven maven-assembly-plugin configure the <finalName> to be ${project.artifactId}
Note:
In the example below, change the location of <descriptor>src/assembly/dist.xml</descriptor> to your location.
For example:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<version>3.1.0</version>
<configuration>
<descriptors>
<descriptor>src/assembly/dist.xml</descriptor>
</descriptors>
<finalName>${project.artifactId}</finalName>
<appendAssemblyId>false</appendAssemblyId>
</configuration>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
I'm assuming that you don't want the "preparation" appended to the name so I included <appendAssemblyId>false</appendAssemblyId>

Maven assembly: generate a resource zip file and include it into the main assembly zip file

How can I proceed to include a generated zip file into a main zip file with the Maven Assembly plugin?
For example, I have the following folder structure:
./folderA/
./file1
and I want to generate a zip file where the content is like this:
folderA.zip
file1
Here my simplified config':
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project >
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<configuration>
<appendAssemblyId>false</appendAssemblyId>
<descriptor>${basedir}/assembly-zipFolderA.xml</descriptor>
<finalName>folderA.zip</finalName>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<configuration>
<appendAssemblyId>false</appendAssemblyId>
<descriptor>${basedir}/assembly.xml</descriptor>
<finalName>${module-zipFinalName}</finalName>
</configuration>
</plugin>
</plugins>
</build>
</project>
assembly-zipFolderA.xml
<assembly>
<id>folderA-zip</id>
<includeBaseDirectory>false</includeBaseDirectory>
<formats>
<format>zip</format>
</formats>
<fileSets>
<fileSet>
<directory>folderA</directory>
<outputDirectory>/</outputDirectory>
</fileSet>
</fileSets>
</assembly>
assembly.xml
<assembly>
<id>main</id>
<includeBaseDirectory>false</includeBaseDirectory>
<formats>
<format>zip</format>
</formats>
<files>
<file>
<source>file1</source>
</file>
<file>
<source>folderA.zip</source>
</file>
</files>
</assembly>
===> with this config, Maven complains that it can't find folderA.zip...
Don't declare the plugin twice; instead, you need to declare two executions of the maven-assembly-plugin.
The first execution will create the first assembly and then, the second execution will use this assembly to create the final one. Both of those executions will be bound to the package phase, and Maven will invoke the plugin's execution in the order of declaration in the POM.
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.6</version>
<executions>
<execution>
<id>make-folderA</id>
<goals>
<goal>single</goal>
</goals>
<phase>package</phase>
<configuration>
<appendAssemblyId>false</appendAssemblyId>
<descriptors>
<descriptor>${basedir}/assembly-zipFolderA.xml</descriptor>
</descriptors>
<finalName>folderA</finalName> <!-- name without extension -->
<attach>false</attach>
</configuration>
</execution>
<execution>
<id>make-assembly</id>
<goals>
<goal>single</goal>
</goals>
<phase>package</phase>
<configuration>
<appendAssemblyId>false</appendAssemblyId>
<descriptors>
<descriptor>${basedir}/assembly.xml</descriptor>
</descriptors>
<finalName>${module-zipFinalName}</finalName>
</configuration>
</execution>
</executions>
</plugin>
A couple of notes:
The <finalName> should not contain the extension, so a finalName of folderA will produce the archive folderA.zip after the ZIP assembly is made.
The first assembly will be created inside the build directory, which is target by default. As such, the second one needs to reference it there with:
<file>
<source>${project.build.directory}/folderA.zip</source>
</file>
in its assembly descriptor.
Since the first assembly is not the final one, you probably don't want it attached, i.e. as an additional artifact produced by your project. You can disable this by setting attach to false. This will make sure only the last final one is considered when deploying or releasing.
descriptor is a deprecated parameter, you should use descriptors instead.
With such a configuration, running mvn clean package will produce the correct archive inside the build folder.

Creating multiple zip files with assembly plugin - no assembly descriptors found

In addition to creating a war file in my pom (which works fine) I'm trying to create a couple of ZIP files that include only some of my content. Previously I had just one zip file and created my own assembly descriptor using the zip format, and this worked fine. When I wanted to add a second zip file with different content, I had to change my plugin to multiple executions. Now when I run it I get an error message that says no assembly descriptors found and that the build failed.
What's funny is that it actually is doing everything it needs to do. It creates the war file. It creates the two zip files, even though it says it failed to do so. But this maven build is one of many run by an automated deployment process, and if it gets an error message, that's not going to fly.
This is the plugin section of my pom:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.6</version>
<executions>
<execution>
<id>zip-metricsscnapshot</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
<configuration>
<outputDirectory>src/main/webapp/resources</outputDirectory>
<finalName>metricssnapshot</finalName>
<descriptors>
<descriptor>src/main/assembly/zip.xml</descriptor>
</descriptors>
</configuration>
</execution>
<execution>
<id>zip-metricdetails</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
<configuration>
<outputDirectory>src/main/webapp/resources</outputDirectory>
<finalName>metricdetails</finalName>
<descriptors>
<descriptor>src/main/assembly/details-zip.xml</descriptor>
</descriptors>
</configuration>
</execution>
</executions>
</plugin>
Solved
addendum:
I run maven with clean yuicompressor:compress assembly:assembly package.
My src/main/assembly directory contains two files, zip.xml and details-zip.xml. They are mostly identical except for the element and the filesets. Here's the zip.xml file:
<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>widget</id>
<baseDirectory>/</baseDirectory>
<formats>
<format>zip</format>
</formats>
<fileSets>
<fileSet>
<outputDirectory>/</outputDirectory>
<directory>src/main/webapp/resources/metricssnapshotwidget</directory>
<excludes>
<exclude>**/metricssnapshotwidget.js</exclude>
<exclude>**/metricssnapshotwidget.css</exclude>
</excludes>
</fileSet>
</fileSets>
</assembly>

generate multiple artifacts in maven

I have to create multiple packages for a single application built by Maven. At first I use the -Denv to generate different packages by Maven arguments and I use the resource to include/exclude the resources:
<resources>
<resource>
<directory>src/main/resources</directory>
<includes>
<include>**/*.properties</include>
<include>**/${env}.ini></include>
</includes>
<filtering>true</filtering>
</resource>
</resources>
Then I can use
mvn clean package -Denv=dev
mvn clean package -Denv=prod1
mvn clean package -Denv=prod2
mvn clean package -Denv=prod3
.....
However it seems that different packages have to be packaged one by one, which means Maven will spent too much time to build all the packages since we have almost 22 different environments to deploy the application.
Furthermore, each mvn .. package almost generate the same result like classes,resources except some specified resources like {$env}.ini, I think it is a waste to run the compile again and again.
It would be better if we compile all the sources, and resources to the target directory, then generate different packages accordingly, so I thought the maven-assembly-plugin, generally we will use it like this:
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<configuration>
<descriptors>
<descriptor>/src/main/assembly/env.xml</descriptor>
<descriptor>/src/main/assembly/prod1.xml</descriptor>
<descriptor>/src/main/assembly/prod2.xml</descriptor>
......
</descriptors>
</configuration>
</plugin>
Then we have to create 22 descriptors, however these descriptors are too similar with each other, which means there are too many repeated configuration, and it will be difficult once I want to make some general change to all the descriptors.
So I wonder if there is a good alternative to solve this kind of requirements?
You can use the iterator-maven-plugin to solve this problem like this:
<plugin>
<groupId>com.soebes.maven.plugins</groupId>
<artifactId>iterator-maven-plugin</artifactId>
<version>0.3</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>iterator</goal>
</goals>
<configuration>
<items>
<item>test</item>
<item>prod</item>
<item>dev</item>
</items>
<pluginExecutors>
<pluginExecutor>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.6</version>
</plugin>
<goal>single</goal>
<configuration>
<descriptors>
<descriptor>${project.basedir}/#item#.xml</descriptor>
</descriptors>
</configuration>
</pluginExecutor>
</pluginExecutors>
</configuration>
</execution>
</executions>
</plugin>
If you use the descriptor like this: ${project.basedir}/#item#.xml the name will be replaced by every single iteration step so you can have several descriptors...but in your case i assume that you have very similar descriptors so you have the same descriptors without a placeholder which contains only slight differences which can be solve like this in the descriptor itself:
<assembly
xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2 http://maven.apache.org/xsd/assembly-1.1.2.xsd">
<id>${item}</id>
<formats>
<format>war</format>
</formats>
<includeBaseDirectory>false</includeBaseDirectory>
<dependencySets>
<dependencySet>
<unpack>true</unpack>
<useProjectArtifact>true</useProjectArtifact>
</dependencySet>
</dependencySets>
<fileSets>
<fileSet>
<outputDirectory>WEB-INF</outputDirectory>
<directory>${basedir}/src/main/environment/${item}/</directory>
<includes>
<include>**</include>
</includes>
</fileSet>
</fileSets>
</assembly>
as a result you need only a single descriptor. If you have any issues please create issue requests.

Move a text file into target folder when compiling a Maven project

I have a slight different version of the question that I made recently.
I have a Maven project under Netbeans 7.3, which doesn't have any build.xml file to configure building options, while there is the pom.xml that I use to import other libraries. Now, I have a text file (let's say textfile.txt) stored in the project folder in Netbeans 7.3, e.g.
project folder
textfile.txt
src
package
package.subpackage
MyClass.java
When I compile I get a target folder where the jar file is put in, e.g.
project folder
textfile.txt
target
classes
generated-sources
....etc
test-classes
MyProject.jar
src
package
package.subpackage
MyClass.java
How can I make the file textfile.txt being copied under target folder when I compile the Maven project?
A first way is to put the files into src/main/resources that is the folder devoted to store the complied resources, i.e. the resources included into the jar file (e.g. images for the icons).
If you need to make the config file to be distributed with the jar, but separated by it, you must edit the pom.xml file. A possible answer is the to add the following plugin between the <plugins> and </plugins> tags.
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-antrun-plugin</artifactId>
<version>1.8</version>
<executions>
<execution>
<phase>test</phase>
<goals>
<goal>run</goal>
</goals>
<configuration>
<tasks>
<echo>Using env.test.properties</echo>
<copy file="textfile.txt" tofile="${basedir}/target/textfile.txt"/>
</tasks>
</configuration>
</execution>
</executions>
</plugin>
Moreover, as you can read here you can also import all the resources from an "input" directory to an "output" directory inside target by using the dedicated plugin, e.g.:
<plugin>
<artifactId>maven-resources-plugin</artifactId>
<version>3.0.1</version>
<executions>
<execution>
<id>copy-resources</id>
<!-- here the phase you need -->
<phase>validate</phase>
<goals>
<goal>copy-resources</goal>
</goals>
<configuration>
<outputDirectory>${basedir}/target/output</outputDirectory>
<resources>
<resource>
<directory>input</directory>
<filtering>true</filtering>
</resource>
</resources>
</configuration>
</execution>
</executions>
</plugin>
The simplest way, to use some resource as I know (additional information about resources configuration you can find here: https://maven.apache.org/plugins/maven-resources-plugin/):
<build>
<plugins>
<!-- your plugins, including or not maven-resource-plugin -->
</plugins>
<resources>
<resource>
<filtering>true</filtering><!-- if it is neccessary -->
<directory>${project.basedir}</directory><!-- from -->
<targetPath>${project.build.directory}</targetPath><!-- to -->
<includes><!-- what -->
<include>textfile.txt</include>
</includes>
</resource>
</resources>
</build>
For building my setting files and updating production this worked for me:
<build>
<resources>
<resource>
<directory>${project.basedir}</directory><!-- from -->
<targetPath>${project.build.directory}</targetPath><!-- to -->
<includes><!-- what -->
<include>**/*.properties</include>
</includes>
</resource>
</resources>
</build>
To have an absolute control of the output of your build you can use the "Apache Maven Assembly Plugin". You can define pretty much everything (format, subfolders...).
The Assembly Plugin for Maven is primarily intended to allow users to aggregate the project output along with its dependencies, modules, site documentation, and other files into a single distributable archive.
More info
You have to install the plugin in your pom file:
<plugins>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<configuration>
<descriptors>
<descriptor>src/main/assembly/yourassembly.xml</descriptor>
</descriptors>
</configuration>
</plugin>
</plugins>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<version>x.x</version>
<configuration>
<descriptors>
<descriptor>src/main/assembly/yourassembly.xml</descriptor>
</descriptors>
</configuration>
<executions>
<execution>
<id>make-assembly</id> <!-- this is used for inheritance merges -->
<phase>package</phase> <!-- append to the packaging phase. -->
<goals>
<goal>single</goal> <!-- goals == mojos -->
</goals>
</execution>
</executions>
</plugin>
</plugins>
</pluginManagement>
In your case the descriptor "yourassembly.xml" would be as follows:
<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>yourassembly</id>
<formats>
<format>tar.gz</format>
<format>dir</format>
</formats>
<fileSets>
<fileSet>
<directory>${project.basedir}</directory>
<includes>
<include>README*</include>
<include>LICENSE*</include>
<include>NOTICE*</include>
</includes>
<useDefaultExcludes>true</useDefaultExcludes>
</fileSet>
<fileSet>
<directory>${project.build.directory}</directory>
<outputDirectory>/</outputDirectory>
<includes>
<include>*.jar</include>
</includes>
</fileSet>
<fileSet>
<directory>${basedir}</directory>
<outputDirectory>/</outputDirectory>
<includes>
<include>textfile.txt</include>
</includes>
</fileSet>
<dependencySets>
<dependencySet>
<outputDirectory>lib</outputDirectory>
<unpack>false</unpack>
</dependencySet>
</dependencySets>
</fileSets>
</assembly>

Resources