maven-assembly plugin - how to create nested assemblies - maven-2

I have a project whereby I'm trying to create a distribution zip file, which contains (amongst other files) an executable jar with dependencies of my java project.
So I sort of want it to look like this:
-wiki-search-1.0.0-dist.zip
-wiki-search.bat
-wiki-search-help.html
-wiki-search-1.0.0-jar-with-dependencies.jar
-jar content...
I'm using the assembly plugin, and the predefined descriptor "jar-with-dependencies" to create my executable jar file.
I'm specifying a separate assembly plugin entry in my pom, referencing a custom descriptor to try and build the distributable zip file.
So the part of my pom looks like this:
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<configuration>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
<archive>
<manifest>
<mainClass>quicksearch.QuickSearchApp</mainClass>
</manifest>
</archive>
</configuration>
<executions>
<execution>
<id>make-assembly</id>
<phase>package</phase>
<goals>
<goal>attached</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<configuration>
<descriptors>
<descriptor>src/main/assembly/dist.xml</descriptor>
</descriptors>
</configuration>
<executions>
<execution>
<id>make-assembly</id>
<phase>package</phase>
<goals>
<goal>attached</goal>
</goals>
</execution>
</executions>
</plugin>
And my custom descriptor looks like this:
<assembly>
<id>dist</id>
<formats>
<format>tar.gz</format>
<format>tar.bz2</format>
<format>zip</format>
</formats>
<fileSets>
<fileSet>
<includes>
<include>${project.basedir}/target/wiki-search-0.0.1-SNAPSHOT-jar-with-dependencies.jar</include>
</includes>
<outputDirectory>.</outputDirectory>
</fileSet>
<fileSet>
<directory>${project.basedir}/src/main/etc</directory>
<includes>
<include>*</include>
</includes>
<outputDirectory></outputDirectory>
</fileSet>
</fileSets>
</assembly>
Everything works fine. The jar-with-dependencies is being built. My dist zip file is being built. But the dist zip file does not contain the jar-with-dependencies file.

With your existing configuration, your two separate configurations for the assembly plugin will be merged, and the configurations will also be merged.
To achieve your goal you should define a single assembly-plugin configuration with multiple nested executions, then define the configuration for each execution inside it. The assembly plugin will then execute each assembly sequentially, so the jar-with-dependencies jar will be available for inclusion in the dist jar. Also note the attached goal is deprecated in favour of the single goal.
Also note that paths in the assembly are relative to the root, and to include a particular file you should use the <files> element rather than the <filesets> element. You can also specify properties in the assembly to make it less fragile to change.
The rearranged configuration and assembly below should do what you're after:
Assembly descriptor:
<assembly>
<id>dist</id>
<formats>
<format>tar.gz</format>
<format>tar.bz2</format>
<format>zip</format>
</formats>
<files>
<file>
<source>
target/${project.artifactId}-${project.version}-jar-with-dependencies.jar
</source>
<outputDirectory>/</outputDirectory>
</file>
</files>
<fileSets>
<fileSet>
<directory>${project.basedir}/src/main/resources</directory>
<includes>
<include>*</include>
</includes>
<outputDirectory>/</outputDirectory>
</fileSet>
</fileSets>
</assembly>
Assembly plugin:
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<executions>
<execution>
<id>jar-with-dependencies</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
<configuration>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
<archive>
<manifest>
<mainClass>quicksearch.QuickSearchApp</mainClass>
</manifest>
</archive>
</configuration>
</execution>
<execution>
<id>dist</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
<configuration>
<descriptors>
<descriptor>src/main/assembly/dist.xml</descriptor>
</descriptors>
</configuration>
</execution>
</executions>
</plugin>

You have two different configurations for the assembly plug-in, and you want them to be run in order (jar before zip), but I don't think Maven implies any order in how this will be resolved. My guess is that the zip file is being generated before the JAR file.
Even if that is not the case, I would suggest you create one module per artifact. Move the JAR assembly into its own module and have the now Zip-only module depend on it. That way Maven's dependency order resolution can kick in and build them in order.

Related

can we delete the target folder which is generating in executable jar in maven2

<plugin>
<artifactId>maven-clean-plugin</artifactId>
<version>2.2</version>
<executions>
<execution>
<id>auto-clean</id>
<phase>install</phase>
<goals>
<goal>clean</goal>
</goals>
<configuration>
<filesets>
<fileset>
<directory>${project.build.Directory}</directory>
<includes>
<include>**/*.jar</include>
</includes>
</fileset>
</filesets>
</configuration>
</execution>
</executions>
</plugin>
i am using this plugin to delete the target folder which is coming in executable jar of module after build , which shouldn't came.
is there any other way to get rid of this type of things during build.By normal way it shouldn't came.
in the pom i have added so many resources from so many different module.

Maven - Include dependent libs in jar without unpacking dependencies?

We're trying to build a client jar that includes unpacked dependent jar's. And the manifest should have class-path entries to the dependent jars. The snippet below works but the jars are unpacked - how can we stop the jars from being unpacked?
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<configuration>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
<archive>
<manifest>
<addClasspath>true</addClasspath>
</manifest>
</archive>
</configuration>
<executions>
<execution>
<id>make-assembly</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
Indeed, assembling using jar-with-dependencies causes maven to unpack all the dependencies as ${assembly.dependencySets.dependency.unpack} is set to true in the corresponding assembly descriptor.
A simple fix would be to provide an assembly descriptor similar to the jar-with-dependencies.xml and modify ${assembly.dependencySets.dependency.unpack} to false, like this:
EDIT: For an unknown reason, the behavior when using <unpack>false</unpack> is not exactly the same and it seems necessary to add <outputDirectory>/</outputDirectory> to the fileSet or you don't get the expected result.
<assembly>
<id>uberjar</id>
<formats>
<format>jar</format>
</formats>
<includeBaseDirectory>false</includeBaseDirectory>
<dependencySets>
<dependencySet>
<unpack>false</unpack>
<scope>runtime</scope>
</dependencySet>
</dependencySets>
<fileSets>
<fileSet>
<directory>${project.build.outputDirectory}</directory>
<outputDirectory>/</outputDirectory>
</fileSet>
</fileSets>
</assembly>
You can add your dependencies as jar files to your jar:
assembly-descriptor.xml
<assembly>
<id>uberjar</id>
<formats>
<format>jar</format>
</formats>
<includeBaseDirectory>false</includeBaseDirectory>
<dependencySets>
<dependencySet>
<unpack>false</unpack>
<scope>runtime</scope>
<useProjectArtifact>false</useProjectArtifact>
</dependencySet>
</dependencySets>
<fileSets>
<fileSet>
<directory>${project.build.outputDirectory}</directory>
<outputDirectory>.</outputDirectory>
</fileSet>
</fileSets>
</assembly>
pom.xml
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.6</version>
<executions>
<execution>
<id>make-uberjar</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
<configuration>
<descriptor>src/main/assemble/assembly-descriptor.xml</descriptor>
</configuration>
</execution>
</executions>
</plugin>
But unfortunately you can't use the Class-Path header in manifest.mf, see Adding Classes to the JAR File's Classpath:
Note: The Class-Path header points to classes or JAR files on the local network, not JAR files within the JAR file or classes accessible over Internet protocols. To load classes in JAR files within a JAR file into the class path, you must write custom code to load those classes. For example, if MyJar.jar contains another JAR file called MyUtils.jar, you cannot use the Class-Path header in MyJar.jar's manifest to load classes in MyUtils.jar into the class path.
The solution proposed by Pascal Thivent defines a new assembly for the Maven assembly plugin. The Maven assembly plugin offers defaults assemblies which are 'bin', 'jar-with-dependencies', 'project' and 'src' producing various predefined bundles.
A new assembly has to be defined in a new xml file, most of the time located in src/assemble. Then it will be loaded instead of the predefined one, this way:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.2-beta-5</version>
<configuration>
<!-- disabled predefined assembly -->
<!--
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
-->
<descriptors>
<descriptor>src/assemble/myAssembly.xml</descriptor>
</descriptors>
</configuration>
</plugin>

Maven assembly plugin support Jar format?

I have configured my assembly descriptor to have an assembly of type jar by
<formats>
<format>jar</format>
</formats>
However,on running mvn install getting zip files instead of jar.Where I have gone wrong?
This configuration produces a jar assembly with the classifier jar-assembly containing only the contents of target/classes. You can add additional filesets if needed to add other content to the jar. To ensure you don't have zip archives from any previous runs in your target directory, you can delete it or run mvn clean.
<assembly>
<id>jar-assembly</id>
<formats>
<format>jar</format>
</formats>
<includeBaseDirectory>false</includeBaseDirectory>
<fileSets>
<fileSet>
<directory>${project.build.outputDirectory}</directory>
<outputDirectory>/</outputDirectory>
</fileSet>
</fileSets>
</assembly>
The plugin configuration should look something like this. Note setting appendAssemblyId to false will cause the default jar to be replaced by the jar from the assembly, remove that element if this is not the desired behaviour:
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.2-beta-2</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
<configuration>
<appendAssemblyId>false</appendAssemblyId>
<descriptors>
<descriptor>src/main/assembly/archive.xml</descriptor>
</descriptors>
</configuration>
</execution>
</executions>
</plugin>
Why don't you use the pre-defined assembly jar-with-dependencies? Below the descriptor file:
<assembly>
<id>jar-with-dependencies</id>
<formats>
<format>jar</format>
</formats>
<includeBaseDirectory>false</includeBaseDirectory>
<dependencySets>
<dependencySet>
<unpack>true</unpack>
<scope>runtime</scope>
</dependencySet>
</dependencySets>
<fileSets>
<fileSet>
<directory>${project.build.outputDirectory}</directory>
</fileSet>
</fileSets>
</assembly>
To use assembly:assembly using a predefined descriptor, run:
mvn assembly:assembly -DdescriptorId=jar-with-dependencies
To produce the assembly as part of the normal build cycle, bind the single or single-directory mojo to the package phase (see Usage):
<project>
[...]
<build>
[...]
<plugins>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.2-beta-5</version>
<configuration>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</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>
[...]
</project>

Maven-assembly-plugin: custom jar filenames

I use the assembly plugin to create several jars with some classes in it. I need custom names for the resulting jars: app_business.jar app_gui.jar core.jar etc.
Currently I have to following configuration:
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<configuration>
<appendAssemblyId>false</appendAssemblyId>
<finalName>app_business</finalName>
<descriptors>
<descriptor>assembly.xml</descriptor>
</descriptors>
<attach>true</attach>
</configuration>
<executions>
<execution>
<id>make-assembly</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
an the assembly.xml file:
<assembly>
<id>app_business</id>
<formats>
<format>jar</format>
</formats>
<baseDirectory>target</baseDirectory>
<includeBaseDirectory>false</includeBaseDirectory>
<fileSets>
<fileSet>
<directory>${project.build.outputDirectory}</directory>
<outputDirectory></outputDirectory>
<includes>
<include>org/xyz/**</include>
</includes>
</fileSet>
</fileSets>
</assembly>
this creates a file app_business.jar which is perfect. But i have no idea how to create my other files. The option appendAssemblyId doesn't help me, as it creates filenames in the format AppName-app_business.jar. I really need the exact filesname app_business.jar.
Any Idea? Thank you very much!
You can move the configuration element below the execution element of the plugin declaration. This means the configuration will only be applied to that execution. You can then add additional executions of the assembly plugin for your other assemblies.
Here is an example of the modified configuration with two executions, each referencing a different assembly:
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<executions>
<execution>
<id>make-business-assembly</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
<configuration>
<appendAssemblyId>false</appendAssemblyId>
<finalName>app_business</finalName>
<descriptors>
<descriptor>src/main/assembly/business-assembly.xml</descriptor>
</descriptors>
<attach>true</attach>
</configuration>
</execution>
<execution>
<id>make-gui-assembly</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
<configuration>
<appendAssemblyId>false</appendAssemblyId>
<finalName>app_gui</finalName>
<descriptors>
<descriptor>src/main/assembly/gui-assembly.xml</descriptor>
</descriptors>
<attach>true</attach>
</configuration>
</execution>
</executions>
</plugin>
With this configuration, two additional jars (app _business.jar and app _gui.jar) will be created in the target directory, though be aware if you install the project, only the last artifact assembled will be installed (this could of course be a problem).
To avoid this you would need to change the appendAssemblyId properties to true. The closest you can get in this case is to change the finalNames to "app" and the IDs to "gui" and "business", resulting in app-gui.jar and app-business.jar being packaged and all artifacts being installed.
The standard maven plugins are meant for general, repetitive work. They gather all information from the POM and they are smart (in the sense that you don't need to configure much).
If you need special tasks, then I suggest to use the ant plugin which allows you to embed a piece of Ant code in the POM. This allows you to run the jar task.

Maven creating flat zip assembly

To Maven gurus out there:
I'm trying to package non-java project artifacts (.NET) into a single zip file. I'm having 2 problems:
If I change packaging in my POM to zip <packaging>zip</packaging>, I get this error message: [INFO] Cannot find lifecycle mapping for packaging: 'zip'.
Component descriptor cannot be found in the component repository: org.apache.mav
en.lifecycle.mapping.LifecycleMappingzip. OK, no big deal - I changed it to <packaging>pom</packaging> to get rid of useless jar that is otherwise created in the target dir
My main problem is that files I'm packaging into ZIP are nested within few directories but I need put these into top directory of ZIP. Here's my assembly file:
<assembly>
<id>bin</id>
<formats>
<format>zip</format>
</formats>
<fileSets>
<fileSet>
<directory>${basedir}/${project.artifactId}</directory>
<includes>
<include>**/Bin/Release/*.dll</include>
<include>**/Bin/Release/*.pdb</include>
</includes>
</fileSet>
</fileSets>
</assembly>
When I run this - I'll get ZIP file but files will be nested starting with C:\ followed by full path. To give you idea - project dumps it's binaries into the following structure
ProjectFoo\ProjectFoo\subproject1\Bin\Release\foo.dll and I need ZIP\foo.dll
Here's assembly plugin configuration:
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<configuration>
<descriptors>
<descriptor>assembly.xml</descriptor>
</descriptors>
</configuration>
<executions>
<execution>
<id>zip</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
Maybe I just need to use antrun and execute ant zip task?
As you've seen, there isn't a zip packaging type, so it makes sense to use pom packaging as you've chosen to.
You've encountered a bit of a hole in the assembly plugin's processing. You could resolve this by specifying multiple fileSets in the assembly with <outputDirectory>/<outputDirectory>, one for each directory you want to include, this is obviously a PITA, and probably not an acceptable solution.
An alternative approach is to use the Ant copy task to copy all the DLLs into a staging directory, then include that directory in the assembly.
The following configuration should do what you're after:
The antrun-plugin configuration:
<plugin>
<artifactId>maven-antrun-plugin</artifactId>
<version>1.3</version>
<executions>
<execution>
<phase>process-resources</phase>
<configuration>
<tasks>
<copy todir="${project.build.directory}/dll-staging">
<fileset dir="${basedir}/${project.artifactId}">
<include name="**/Bin/Release/*.dll"/>
<include name="**/Bin/Release/*.pdb"/>
</fileset>
<flattenmapper/>
</copy>
</tasks>
</configuration>
<goals>
<goal>run</goal>
</goals>
</execution>
</executions>
</plugin>
The assembly:
<assembly>
<id>bin</id>
<formats>
<format>zip</format>
</formats>
<fileSets>
<fileSet>
<directory>${project.build.directory}/dll-staging</directory>
<outputDirectory>/</outputDirectory>
<includes>
<include>*.dll</include>
<include>*.pdb</include>
</includes>
</fileSet>
</fileSets>
</assembly>