Custom assembly descriptor to create a jar with dependencies - maven-2

I would like to generate a .jar application from a project made in Maven.
I am working in Eclipse, and I made: run as/Maven assembly:assembly
This is the error message:
[ERROR] Failed to execute goal org.apache.maven.plugins:maven-assembly-plugin:2.2-beta-4:assembly (default-cli) on project FeelIndexer: Error reading assemblies: No assembly descriptors found.
This is my assamble.xml
<assembly>
<id>exe</id>
<formats>
<format>jar</format>
</formats>
<includeBaseDirectory>false</includeBaseDirectory>
<dependencySets>
<dependencySet>
<outputDirectory></outputDirectory>
<outputFileNameMapping></outputFileNameMapping>
<unpack>true</unpack>
<scope>runtime</scope>
<includes>
<include>commons-lang:commons-lang</include>
<include>commons-cli:commons-cli</include>
</includes>
</dependencySet>
</dependencySets>
<fileSets>
<fileSet>
<directory>target/classes</directory>
<outputDirectory></outputDirectory>
</fileSet>
</fileSets>
</assembly>
I think i have to include something else for adding the dependencies of muy project, but i don't know how to do it!!
suggestions??
Update: Below my assembly.xml
<assembly>
<id>exe</id>
<formats>
<format>jar</format>
</formats>
<includeBaseDirectory>false</includeBaseDirectory>
<dependencySets>
<dependencySet>
<outputDirectory></outputDirectory>
<outputFileNameMapping></outputFileNameMapping>
<unpack>true</unpack>
<scope>runtime</scope>
<includes>
<include>commons-lang:commons-lang</include>
<include>commons-cli:commons-cli</include>
</includes>
</dependencySet>
</dependencySets>
<fileSets>
<fileSet>
<directory>target/classes</directory>
<outputDirectory></outputDirectory>
</fileSet>
</fileSets>
<plugins>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.2-beta-5</version>
<configuration>
<descriptors>
<descriptor>src/main/assembly/src.xml</descriptor>
</descriptors>
</configuration>
</plugin>
</plugins>
</assembly>
Where could i find my maven-assembly-plugin configuration??
I tried two options you told me:
Using predefined assembly.xml
Inserting plugin
I had the same result :s

To use a custom assembly descriptor, you have to declare it in the plugin configuration:
<project>
[...]
<build>
[...]
<plugins>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.2-beta-5</version>
<configuration>
<descriptors>
<descriptor>src/main/assembly/src.xml</descriptor>
</descriptors>
</configuration>
[...]
</plugin>
</plugins>
</project>
By the way, wouldn't the predefined assembly jar-with-dependencies suit your needs? I don't see much differences with your custom assembly and my suggestion would be to use the predefined one:
<project>
[...]
<build>
[...]
<plugins>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.2-beta-5</version>
<configuration>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
[...]
</plugin>
</plugins>
</project>
Update: I don't understand what you're doing and I'm not sure you understood how the assembly plugin works.
The Maven Assembly Plugin configuration (the above samples, enclosed by <plugin>) goes in the pom.xml, not in the assembly descriptor.
If you configure the Maven Assembly Plugin to use src/main/assembly/src.xml as assembly descriptor, the file must exist (so either rename your assembly descriptor or change the configuration, the above sample was just... an example).
From what I see, you don't need a custom assembly descriptor. You could simply use the second snippet I gave in my initial answer (put it in your pom.xml).

Related

Maven, assembly plugin, multi-module project and module dependencies

I'm building a multi-module Maven project whose major product is a WAR file, and I'm trying to assemble that file together with associated release-related artifacts (README, release notes, license file, etc.) into a ZIP for distribution. But when I try to build a distribution file, it fails. What am I doing wrong? Note that I have already checked that the foo-bar.1.0.war artifact exists at the point that the foo-distribution module is asked to build the distribution file; I'm aware that putting everything in foo's POM won't work. (I have a workaround; I can use relative paths to point directly to the location of the files distributed relative to the foo-distribution module root. This isn't a solution I like as it has bad code-smell.)
Note also that I always build from the root project, and that I'm using assembly:single in the distribution builder (as recommended in the Maven documentation).
Project Layout
foo
+ src
| + README.txt
+ foo-bar
| + target
| + foo-bar.1.0.war
+ foo-distribution
+ src
+ assemble
+ dist.xml
foo and foo-distribution have pom packaging, and foo-bar has war packaging. (There are other modules in the real code, but they're also constructed correctly before the foo-distribution module.)
foo POM
<project xmlns="http://maven.apache.org/POM/4.0.0">
<modelVersion>4.0.0</modelVersion>
<groupId>foobar</groupId>
<artifactId>foo</artifactId>
<packaging>pom</packaging>
<version>0.0.1-SNAPSHOT</version>
<modules>
<module>foo-bar</module>
<module>foo-distribution</module>
</modules>
</project>
foo-distribution POM
<project xmlns="http://maven.apache.org/POM/4.0.0">
<modelVersion>4.0.0</modelVersion>
<version>0.0.1-SNAPSHOT</version>
<parent>
<artifactId>foo</artifactId>
<groupId>foobar</groupId>
<version>0.0.1-SNAPSHOT</version>
<relativePath>..</relativePath>
</parent>
<groupId>foobar</groupId>
<artifactId>foo-distribution</artifactId>
<packaging>pom</packaging>
<dependencies>
<dependency>
<groupId>foobar</groupId>
<artifactId>foo-bar</artifactId>
<version>1.0</version>
<type>war</type>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.2-beta-5</version>
<configuration>
<finalName>foobar</finalName>
<descriptors>
<descriptor>src/assemble/dist.xml</descriptor>
</descriptors>
</configuration>
<executions>
<execution>
<id>make-t2server-distribution</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
dist.xml
<assembly
xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0">
<id>distribution</id>
<formats>
<format>zip</format>
</formats>
<moduleSets>
<moduleSet>
<includes>
<include>foobar:foo</include>
</includes>
<sources>
<fileSets>
<fileSet>
<directory>src</directory>
<includes>
<include>*.txt</include>
</includes>
</fileSet>
</fileSets>
</sources>
</moduleSet>
<moduleSet>
<includes>
<include>foobar:foo-bar</include>
</includes>
<binaries />
</moduleSet>
</moduleSets>
</assembly>
Workaround dist.xml
This is the workaround that I mentioned above. It produces exactly the artifact that I want.
<assembly
xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0">
<id>distribution</id>
<formats>
<format>zip</format>
</formats>
<fileSets>
<fileSet>
<directory>${project.basedir}/../src</directory>
<includes>
<include>*.txt</include>
</includes>
</fileSet>
<fileSet>
<directory>${project.basedir}/../foo-bar/target</directory>
<includes>
<include>*.war</include>
</includes>
<outputDirectory>.</outputDirectory>
</fileSet>
</fileSets>
</assembly>
You should use a dependencySet in your assembly descriptor
<assembly>
<id>dist</id>
<formats>
<format>zip</format>
</formats>
<includeBaseDirectory>true</includeBaseDirectory>
<dependencySets>
<dependencySet>
<useTransitiveDependencies>false</useTransitiveDependencies>
<useProjectArtifact>false</useProjectArtifact>
<unpack>false</unpack>
<scope>runtime</scope>
<fileMode>0644</fileMode>
</dependencySet>
</dependencySets>
<fileSets>
<fileSet>
with all supplemental files you need
</fileSet>
</fileSets>
instead of referencing the files via file system (relative paths). And on the other hand a descriptor for source does exists already from the assembly plugin (take a look into the docs).
What order are the modules being build, I had a similar problem and declaring what the parent was in the child module helped with the build order. Not sure if using could help with this.

Maven Assembly: include a dependency with a different classifier

I would like to build two different versions of a WAR in Maven (I know that's a no-no, that's just the way it is given the current situation). In the version of a WAR depicted by an assembly, I want to replace a dependency by the same dependency with a different classifier. For example, I was expecting this assembly to work:
<assembly>
<id>end-user</id>
<formats>
<format>war</format>
</formats>
<dependencySets>
<dependencySet>
<excludes>
<exclude>group:artifact:jar:${project.version}</exclude>
</excludes>
<includes>
<include>group:artifact:jar:${project.version}:end-user</include>
</includes>
</dependencySet>
</dependencySets>
</assembly>
This doesn't work, but am I heading in the right direction? I've already read all the pages on the Maven assembly page and the section on the Maven Definitive Guide that seems relevant. Any pointers would be helpful.
Personally, I think that the cleanest solution would be to use two profiles (one of them depending on the artifact with the classifier, the other on the "regular" artifact). But you can indeed achieve what you want with a custom assembly. I just don't think you're heading in the right direction. Here is how I would do it...
First, create a specific project for the assembly and declare both the webapp and the artifact with the classifier as dependencies. Something like this:
<project>
...
<dependencies>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>artifact</artifactId>
<version>${project.version}</version>
<classifier>end-user<classifier>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>zewebapp</artifactId>
<version>${project.version}</version>
<type>war</type>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.2-beta-5</version>
<configuration>
<descriptors>
<descriptor>src/main/assembly/end-user.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>
</build>
</project>
Then, in your assembly descriptor:
<assembly>
<id>end-user</id>
<formats>
<format>war</format>
</formats>
<includeBaseDirectory>false</includeBaseDirectory>
<dependencySets>
<dependencySet>
<unpack>true</unpack>
<unpackOptions>
<excludes>
<exclude>**/artifact-*.jar</exclude>
</excludes>
</unpackOptions>
<includes>
<include>*:war</include>
</includes>
</dependencySet>
<dependencySet>
<unpack>false</unpack>
<outputDirectory>WEB-INF/lib</outputDirectory>
<includes>
<include>group:artifact:jar:*:end-user</include>
</includes>
</dependencySet>
</dependencySets>
</assembly>
Basically, this tells the assembly plugin to get the war for zewebapp and to unpack it but to exclude the unwanted artifact while unpacking. Then, the assembly plugin get the artifact with the classifier and place it in WEB-INF/lib (so we substitute it to the original). Finally, the whole thing is packaged as a war.
I tested this on a simplified example, it should work.
The "version" information is not required when specifying artifact coordinates for includes/include*.
This should work:
<assembly>
<id>end-user</id>
<formats>
<format>war</format>
</formats>
<dependencySets>
<dependencySet>
<includes>
<include>group:artifact:jar:end-user</include>
</includes>
</dependencySet>
</dependencySets>
</assembly>
I think the maven assembly documentation for the includes/include* section is incorrect. It says "Artifact coordinatess may be given in simple groupId:artifactId form, or they may be fully qualified in the form groupId:artifactId:type:version[:classifier]." However, from my testing, the "version" is not required. I got the hint from here.
Took me while to find out, thought might be useful to others in the future.

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>

How can I include unit tests in maven assembly?

Reason: Our project is using Ant as commandline interface. After making a new assembly with maven's assembly plugin, I want to make initial tests to see if all has been properly assembled. Therefore I need to include the unit tests in the final assembly. After assembling, the initial tests would then be called sth like
> ant initTest
build.xml:
<target="initTest">
<junit>
<test class="MyTest" />
</junit>
</target>
Problem is:
I want to keep my Unit tests in src/test/java and not move them to src/main/java.
Is there a way to tell the assembly plugin to include my unit tests? A simple include in the assembly descriptor does not do it ...
There are two steps:
Package the tests into a jar as well as the main code.
Depend on that "-tests" jar in the module that makes the assembly.
To package up the tests, you need to bin the jar:test-jar goal. e.g.
<build>
<plugins>
<plugin>
<artifactId>maven-jar-plugin</artifactId>
<executions>
<execution>
<id>test-jar</id>
<phase>package</phase>
<goals>
<goal>test-jar</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
Then in the assembly module, you can depend on the resulting artifact.
<dependencies>
<dependency>
<groupid>${project.groupId}</groupId>
<artifactId>some-artifact</artifactId>
<version>${project.version}</version>
<classifier>tests</classifier>
</dependency>
</dependencies>
The key bit is the "classifier".
The answer from #Dominic-Mitchell did not work for me at all. What finally worked was adding a fileSet for the test classes to my assembly xml. Note that the fileSet directories are different! That stumped me for the longest time.
Use ${project.build.directory} for the test classes and ${project.build.outputDirectory} for the main:
<?xml version='1.0' encoding='UTF-8'?>
<assembly>
<id>toolbar-test</id>
<formats>
<format>jar</format>
</formats>
<includeBaseDirectory>false</includeBaseDirectory>
<fileSets>
<fileSet>
<directory>${project.build.directory}/test-classes</directory>
<outputDirectory>/</outputDirectory>
</fileSet>
<fileSet>
<directory>${project.build.outputDirectory}</directory>
<outputDirectory>/</outputDirectory>
</fileSet>
</fileSets>
<dependencySets>
<dependencySet>
<scope>runtime</scope>
<unpack>true</unpack>
<unpackOptions>
<excludes>
<exclude>**/LICENSE*</exclude>
<exclude>**/README*</exclude>
</excludes>
</unpackOptions>
</dependencySet>
<dependencySet>
<scope>test</scope>
<unpack>true</unpack>
</dependencySet>
</dependencySets>
</assembly>
Credit where credit is due - I found this solution within this blog post here: http://alexgaddie.blogspot.com/2010/02/creating-uber-jar-with-maven.html
I did not need the profile part of the blog post.
The following works for us.
pom.xml snippet:
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>2.6</version>
<executions>
<execution>
<goals>
<goal>test-jar</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
assembly.xml snippet:
<dependencySets>
<dependencySet>
<outputDirectory>/lib</outputDirectory>
<useProjectArtifact>true</useProjectArtifact>
<useProjectAttachments>true</useProjectAttachments>
<scope>runtime</scope>
</dependencySet>
</dependencySets>
The key is the useProjectAttachments tag.