Maven creating flat zip assembly - maven-2

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>

Related

Trouble getting started with maven assembly plugin

I'm sorry to sound ignorant here, but I'm new to Maven, and have been banging my head against something that I'm sure is quite simple.
The docs say:
[...] a project could produce a ZIP assembly which contains a project's JAR artifact in the root directory, the runtime dependencies in a lib/ directory, and a shell script to launch a stand-alone application.
which is exactly what I want to do! But I can't seem to make it happen.
My POM is as follows:
<project>
<modelVersion>4.0.0</modelVersion>
<groupId>com.anearalone</groupId>
<artifactId>myapp</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
[...]
<build>
<finalName>myapp</finalName>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.2.1</version>
<executions>
<execution>
<id>make-assembly</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
<configuration>
<descriptors>
<descriptor>src/main/assemble/dist.xml</descriptor>
</descriptors>
<archive>
<manifest>
<mainClass>com.anearalone.myapp.CLI</mainClass>
<addClasspath>true</addClasspath>
<classpathPrefix>lib/</classpathPrefix>
</manifest>
</archive>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
[...]
</project>
and the referenced dist.xml looks like this:
<assembly>
<id>dist</id>
<formats>
<format>zip</format>
</formats>
<files>
<file>
<outputDirectory>/</outputDirectory>
<source>src/main/bin/arkify.sh</source>
<fileMode>755</fileMode>
</file>
</files>
<dependencySets>
<dependencySet>
<useProjectArtifact>false</useProjectArtifact>
<includes>
<include>*:jar</include>
</includes>
<outputDirectory>/lib</outputDirectory>
</dependencySet>
<dependencySet>
<useProjectArtifact>true</useProjectArtifact>
<includes>
<include>com.anearalone:myapp:jar:0.0.1-SNAPSHOT</include>
</includes>
<outputDirectory>/</outputDirectory>
</dependencySet>
</dependencySets>
</assembly>
This achieves the layout I want in the zip file (though I'm quite sure I'm not getting there in the correct way) but I get two jars in target/ (one in the zip archive, the other in the root), and neither of them includes my mainClass entry in the resultant MANIFEST.MF.
If I change the project.packaging to "pom", which I thought might be correct, of course the extra jar (in the root of target/ goes away, but I get these warning:
[WARNING] Cannot include project artifact: com.anearalone:myapp:pom:0.0.1-SNAPSHOT; it doesn't have an associated file or directory.
[WARNING] The following patterns were never triggered in this artifact inclusion filter:
o 'com.anearalone:myapp'
... and indeed my artifact is not in the archive, and there are still no entries added to MANIFEST.MF.
Anyone have time to help out a beginner?
If I understand your problem correctly, your ZIP is correctly created, but the my-app-0.0.1-SNAPSHOT contained in it (as well as the JAR directly located in target/ directory) does not include your main class in the MANIFEST.MF file?
In fact, the assembly plugin is not dedicated to execute such a task. This is the task of the JAR plugin, which provides a way to indicates, in the MANIFEST.MF the main class of your project. You simply must add this configuration in your current pom.xml:
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
...
<configuration>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<mainClass>my.app.MainClass</mainClass>
</manifest>
</archive>
</configuration>
</plugin>
</plugins>
Regarding your try to change the packaging of the project to a pom packaging: it was a bad idea ;) Indeed, the pom packaging is used for project without any other resources than the pom.xml itself. It is really useful for pom.xml that are defined as the parent of others projects, or to aggregate multiples modules.

building a jar and including it in a zip with maven-assembly-plugin

I have a mavenized java project (Maven2) which I want to build into a jar, which is easy enough by supplying the jar-with-dependencies descriptorRef in the pom.xml.
However I also need to deploy my project in a zip with some .exe and .bat files, among others, from a bin folder that call the jar. (I am using Tanuki but it does not matter for the use case I think)
In other words, I need a build in which first my sources (and dependencies) are packaged into a jar and that jar is then put into a zip with some additional files from the bin folder.
What should I put in my pom.xml and 'assembly'.xml?
Maven-assembly-plugin is the right tool to do that.
You have to declare this plugin in the "build" section of your pom, and to create another configuration file "assembly.xml" at the root of your project. In this file, your will define the content of your zip file.
The configuration options are described on the official site: http://maven.apache.org/plugins/maven-assembly-plugin/
Here is a basic configuration example of this plugin that should suit your needs.
POM config :
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<configuration>
<finalName>zipfile</finalName>
<descriptors>
<descriptor>${basedir}/assembly.xml</descriptor>
</descriptors>
</configuration>
<executions>
<execution>
<id>make-assembly</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
Assembly config :
<assembly>
<formats>
<format>zip</format>
</formats>
<fileSets>
<fileSet>
<directory>to_complete</directory>
<outputDirectory />
<includes>
<include>**/*.jar</include>
<include>**/*.bat</include>
<include>**/*.exe</include>
</includes>
</fileSet>
</fileSets>
</assembly>

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 - how to create nested assemblies

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.

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>