generate multiple artifacts in maven - 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.

Related

How to have custom properties for the Maven Assembly Plugin?

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>

java.lang.NoClassDefFoundError: org/apache/accumulo/core/client/Instance

I'm using small program to write data into Accumulo.
Program worked when added jars manually. But, when build with maven, with the same version's used from manual it throws:
java.lang.NoClassDefFoundError:
org/apache/accumulo/core/client/Instance.
How would I resolve it?
Your job is going to be run on all of the nodes in your MR network. You'll need the appropriate jars on all of the nodes in order for it to work.
Another approach, as you have noticed, is to just include everything into one uber jar, which contains everything that you need. That way when your job gets shipped to each node, you'll have everything you need. One way to accomplish this with maven is through the use of plugins:
<build>
<plugins>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.2.1</version>
<configuration>
<descriptors>
<descriptor>src/main/assembly/hadoop-job.xml</descriptor>
</descriptors>
</configuration>
<executions>
<execution>
<id>make-assembly</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
Inside of your hadoop-job.xml you might have
<assembly>
<id>job</id>
<formats>
<format>jar</format>
</formats>
<includeBaseDirectory>false</includeBaseDirectory>
<dependencySets>
<dependencySet>
<unpack>false</unpack>
<scope>runtime</scope>
<outputDirectory>lib</outputDirectory>
<excludes>
<exclude>${groupId}:${artifactId}</exclude>
</excludes>
</dependencySet>
<dependencySet>
<outputDirectory></outputDirectory>
<unpack>true</unpack>
<includes>
<include>${groupId}:${artifactId}</include>
</includes>
</dependencySet>
</dependencySets>
</assembly>
More information about this plugin may be found at http://maven.apache.org/plugins/maven-assembly-plugin/
You have to download the accumulo-core.jar and add it to your classpath.

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>

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

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?

Creating output dir structure with Maven

I have a java project XXX
src/main/java
src/main/config
src/main/scripts
I want output structure like
C:/target/XXX.jar
C:/target/scripts
I tried to use resource plugin but it is packing everything inside jar.
<build>
<directory>target</directory>
<outputDirectory>target/classes</outputDirectory>
<finalName>${artifactId}-${version}</finalName>
<sourceDirectory>src/main/java</sourceDirectory>
<scriptSourceDirectory>src/main/scripts</scriptSourceDirectory>
<resources>
<resource>
<directory>src/main/config</directory>
</resource>
<resource>
<directory>src/main/scripts</directory>
<targetPath>/scripts</targetPath>
</resource>
</resources>
</build>
The maven-assembly-plugin is great for this sort of thing. You can create a descriptor something like this (in src/main/assemble/scripts.xml):
<assembly>
<id>scripts</id>
<formats>
<format>dir</format>
</formats>
<fileSets>
<fileSet>
<outputDirectory>/scripts</outputDirectory>
<includes>
<include>*.*</include>
</includes>
</fileSet>
</fileSets>
</assembly>
Wire this into your build like so:
<build>
<plugins>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.3</version>
<configuration>
<descriptors>
<descriptor>src/main/assemble/scripts.xml</descriptor>
</descriptors>
</configuration>
<executions>
<execution>
<id>copy-scripts</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
This will bind the execution of the assembly to the package phase of the build.
This method will give you the flexibility to change how you package up the scripts in the future, or copy more resources in the build.

Resources