So I have a parent module with a bunch of sub-modules, and I'm trying to generate a zip file with all of the module jars and all of their dependencies. My assembly descriptor looks like (similar to this question):
<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>bin</id>
<formats>
<format>zip</format>
</formats>
<moduleSets>
<moduleSet>
<useAllReactorProjects>true</useAllReactorProjects>
<binaries>
<outputDirectory>/</outputDirectory>
<unpack>false</unpack>
<dependencySets>
<dependencySet>
<outputDirectory>lib</outputDirectory>
<unpack>false</unpack>
<scope>runtime</scope>
</dependencySet>
</dependencySets>
</binaries>
</moduleSet>
</moduleSets>
</assembly>
Now in both maven 2 and maven 3 I'm seeing hundreds of messages that look like:
[INFO] distribution-0.5.1-SNAPSHOT/lib/commons-lang-2.4.jar already added, skipping
[INFO] distribution-0.5.1-SNAPSHOT/lib/spring-core-3.0.3.RELEASE.jar already added, skipping
[INFO] distribution-0.5.1-SNAPSHOT/lib/commons-logging-1.0.4.jar already added, skipping
[INFO] distribution-0.5.1-SNAPSHOT/lib/args4j-2.0.12.jar already added, skipping
[INFO] distribution-0.5.1-SNAPSHOT/lib/collections-generic-4.01.jar already added, skipping
I gather these are happening because many of my sub-modules share dependencies (and some sub-modules depend on other sub-modules) and maven is copying all transitive dependencies for each sub-module independently so there's a ton of repetition in there.
Is there a way I can keep maven from trying to copy the same dependencies multiple times? Or at least hide these "already added, skipping" messages when it tries to?
I doubt if there exist anything that allows Maven Assembly plug-in to mute. This would be a good option to provide.
On other hand, you can ask Maven to suppress all output and run in quiet mode.
mvn -h
usage: mvn [options] [<goal(s)>] [<phase(s)>]
Options:
-q,--quiet Quiet output - only show errors
E.g.
mvn -q clean package
But, you will loose all the other build time information as well.
Related
I've multi module project and using maven's assembly plugin to zip the project's artifact.
Proj
+Module A
pom.xml
+Module B
pom.xml
pom.xml
When i build main module, it will produce following things
Proj
+Module A
target\A.jar
target\A-source.jar
target\A-javadoc.jar
+Module B
target\B.jar
target\B-source.jar
target\B-javadoc.jar
1) I've added assembly plugin under ModuleB pom file and I'm using ModuleSet in assembly discriptor file
<moduleSets>
<moduleSet>
<useAllReactorProjects>true</useAllReactorProjects>
<includes>
<include>groupA:A:jar</include>
<include>groupA:A:javadoc</include>
<include>groupA:A:source</include>
</includes>
<binaries>
<outputDirectory>moduleA</outputDirectory>
<unpack>false</unpack>
</binaries>
</moduleSet>
<moduleSet>
<useAllReactorProjects>true</useAllReactorProjects>
<includes>
<include>groupB:B:jar</include>
<include>groupB:B:javadoc</include>
<include>groupB:B:source</include>
</includes>
<binaries>
<outputDirectory>moduleB</outputDirectory>
<unpack>false</unpack>
</binaries>
</moduleSet>
</moduleSets>
But i'm getting only A.jar and B.Jar under zip file. I'm not getting javadoc and source in zip file. Is it downloading it from m2 repo, i'm suspecting if it does so, because sources and java doc wouldn't be there in maven reporee artifact. How can i add all three artifact in a zip file ?
2) I want to add assembly plugin in my parent pom rather than in ModuleB's pom but if i do so, i get an exception "Please ensure the package phase is run before the assembly is generated". After googling, i found few suggetion to add assembly as module. Is there any other way to handle this ?
I used dependecySet to solve this problem, we can use wildcard to add all binaries.
<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>bin</id>
<includeBaseDirectory>false</includeBaseDirectory>
<formats>
<format>zip</format>
</formats>
<dependencySets>
<dependencySet>
<includes>
<include>groupA:*:*:*</include>
</includes>
</dependencySet>
</dependencySets>
</assembly>
This will add all binary artifacts of project. One more thing to note is the id used in assembly descriptor. It should be bin for binary artifact.
Posting here in case if anybody runs into similar kind of issue, this might help.
I have a hierarchical maven project, from which I am trying to build a native installer for several of the sub-modules. I am using my product name as a prefix: <finalName>xyz-${artifactId}</finalName> in the parent POM so that all my artifact jars have a standard naming convention.
xyz-parent
+-- util
+--- target/xyz-util.jar
+-- core
+--- target/xyz-core.jar
+-- app1 <--- "builds an installer as part of the package phase"
+--- target/xyz-app1.jar
+-- app2 <--- "builds an installer as part of the package phase"
...
I need to materialize all the dependent jars into a directory (since inno setup knows nothing about maven). So for each submodule which is an installer I plan to use maven-assembly-plugin, then use something like the following in my inno setup:
Source: "target\pkg\lib\*.jar"; DestDir: "{app}\external"; Flags: ignoreversion;
When I run mvn clean package, I get a target/xyz-app1-bin/xyz-app1/lib directory with all of the dependent jars, however none of the jars produced by my sibling projects have their correct final names (e.g. I have util-0.0.1-SNAPSHOT.jar instead of xyz-util.jar)
This problem seems similar to this post, but I have no idea what "attach" is (perhaps deprecated).
I was unable to use finalName directly, however, I did manage to re-implement the finalName logic I wanted using dependency sets -- thus partitioning my dependencies into an external and internal set (based on the groupId):
<assembly>
<id>bin</id>
<formats>
<format>dir</format>
</formats>
<dependencySets>
<dependencySet>
<outputDirectory>external</outputDirectory>
<outputFileNameMapping>
${artifact.artifactId}.${artifact.extension}
</outputFileNameMapping>
<excludes>
<exclude>com.xyz:*</exclude>
</excludes>
</dependencySet>
<dependencySet>
<outputDirectory>lib</outputDirectory>
<outputFileNameMapping>
xyz-${artifact.artifactId}.${artifact.extension}
</outputFileNameMapping>
<includes>
<include>com.xyz:*</include>
</includes>
</dependencySet>
</dependencySets>
</assembly>
You should be able to use finalName directly using (this worked for me) :
<outputFileNameMapping>
${artifact.build.finalName}.${artifact.extension}
</outputFileNameMapping>
I have several sub module (say A, B + C) that each generate an assembly tar.gz and a module (X) that will bundle them all together by extracting the tarballs into the target directory.
Right now setting up my dependency on A, B + C using the classifier and type in module X POM and using an assembly file with dependencySets the module does not seem to be pulling the tarball from my local repo, rather rebuilding it.
This is causing issues because A, B + C each has it's own filters. When X rebuilds A it leaves it unfiltered. I want maven to just either get the A-distro.tar.gz from my repo or if not present rebuild A, put it in the repo then have X use this.
Here is the assembly.xml file I'm using. I couldn't get moduleSets to work when using the coordinates so went for this:
<assembly>
<id>distro</id>
<formats>
<format>dir</format>
<format>tar.gz</format>
</formats>
<baseDirectory>${project.version}</baseDirectory>
<includeBaseDirectory>false</includeBaseDirectory>
<dependencySets>
<dependencySet>
<useTransitiveFiltering>true</useTransitiveFiltering>
<useProjectArtifact>false</useProjectArtifact>
<unpack>false</unpack>
<outputDirectory>/lib</outputDirectory>
<excludes>
<exclude>*:tar.gz</exclude>
</excludes>
</dependencySet>
<dependencySet>
<useTransitiveFiltering>true</useTransitiveFiltering>
<useProjectArtifact>false</useProjectArtifact>
<unpack>true</unpack>
<outputDirectory>/</outputDirectory>
<includes>
<include>*:tar.gz</include>
</includes>
</dependencySet>
</dependencySets>
</assembly>
And POM for project X:
<project>
<parent>
<artifactId>parent_project</artifactId>
<groupId>org.myorg</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>org.myorg</groupId>
<artifactId>X</artifactId>
<packaging>pom</packaging>
<name>X</name>
<version>1.0-SNAPSHOT</version>
<build>
<plugins>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>org.myorg</groupId>
<artifactId>A</artifactId>
<classifier>distro</classifier>
<type>tar.gz</type>
</dependency>
</dependencies>
</project>
(RS moved content from OP's answer)
ok thanks for replying.
I've created a test project using the principle you describe of having one module for assembly, one for aggregator:
./pom.xml
./bundle
./bundle/pom.xml
./bundle/src
./bundle/src/main
./bundle/src/main/assembly
./bundle/src/main/assembly/assembly-files.xml
./bundle/src/main/assembly/assembly.xml
./module1
./module1/pom.xml
./module1/src
./module1/src/main
./module1/src/main/assembly
./module1/src/main/assembly/assembly-files.xml
./module1/src/main/assembly/assembly.xml
./module1/src/main/conf
./module1/src/main/java
./module1/src/main/java/org
./module1/src/main/java/org/test
./module1/src/main/java/org/test/Test.java
./module2
./module2/pom.xml
./module2/src
./module2/src/main
./module2/src/main/java
./module2/src/main/java/org
./module2/src/main/java/org/test
./module2/src/main/java/org/test/Test.java
Module 1 produces an assembly file of the following coordinates:
<dependency>
<groupId>org.test</groupId>
<artifactId>module1</artifactId>
<version>1.0-SNAPSHOT</version>
<classifier>distro</classifier>
<type>tar.gz</type>
</dependency>
The following file is produced:
~/mvnrepos/org/test/module1/1.0-SNAPSHOT/module1-1.0-SNAPSHOT-distro.tar.gz
When building the bundle with the following assembly the tar.gz is pulled in and used:
<assembly>
<id>distro</id>
<formats>
<format>dir</format>
<format>tar.gz</format>
</formats>
<baseDirectory>${project.version}</baseDirectory>
<includeBaseDirectory>false</includeBaseDirectory>
<dependencySets>
<dependencySet>
<includes>
<include>org.test:module1:tar.gz</include>
</includes>
<useTransitiveFiltering>true</useTransitiveFiltering>
<useProjectArtifact>false</useProjectArtifact>
<unpack>true</unpack>
<unpackOptions>
<excludes>
<exclude>lib/</exclude>
</excludes>
</unpackOptions>
<outputDirectory>lib/</outputDirectory>
</dependencySet>
</dependencySets>
<!-- just includes conf and bin dirs -->
<componentDescriptors>
<componentDescriptor>src/main/assembly/assembly-files.xml</componentDescriptor>
</componentDescriptors>
</assembly>
However if I cleardown my repository and clean the project at the root so the tar.gz is removed completely, when I change into the bundle dir and mvn install it fails as maven cannot work out it needs to rebuild module 1 in the absence of the tar.gz in order to get it. Here is my bundle pom:
<project>
<parent>
<artifactId>test_parent</artifactId>
<groupId>org.test</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>org.test</groupId>
<artifactId>bundle</artifactId>
<packaging>pom</packaging>
<name>bundle</name>
<version>1.0-SNAPSHOT</version>
<url>http://maven.apache.org</url>
<build>
<plugins>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>org.test</groupId>
<artifactId>module1</artifactId>
</dependency>
<dependency>
<groupId>org.test</groupId>
<artifactId>module2</artifactId>
</dependency>
<dependency>
<groupId>org.test</groupId>
<artifactId>module1</artifactId>
<version>1.0-SNAPSHOT</version>
<classifier>distro</classifier>
<type>tar.gz</type>
<scope>runtime</scope>
</dependency>
</dependencies>
</project>
How can I get maven to realize that the assembly must be rebuilt by rebuilding module 1?
I'm trying to keep each assembly within a separate module so each module can be built and tested as a separate unit rather than having an aggregator which needs to be rebuilt in order to run any of the modules. Then if the a full run is required the bundle can be built by simply untarring each assembly tarball into a directory under bundle/target.
Perhaps the above is going against the grain - but this seems to be the thrust of the maven assembly chapter in the Sonotype book:
http://www.sonatype.com/books/maven-book/reference/assemblies-sect-assembling-via-depend.html
Unfortunately the examples zip provided by sonotype has nothing under chapter 12 :-(
Of course I could just break out into ant and use this but would like to implement purely in maven if at all possible.
btw maven-assembly-plugin version is 2.2-beta-2.
I'm not sure I understand your problem so let me try to rephrase it.
You have 4 projects, A, B, C and X. You have A, B, and C defined as sub-projects of X
When you build project X you want to include the tar.gz files for projects A, B and C.
The problem is that you want to build A only if required, and download it from the project
repository if it is already present?
Assuming I understand the problem correctly, I'm still not clear how you expect the children to be conditionally built. If X declares the others as modules Maven will always build them along with the parent. If X declares the others as dependencies they will only ever be treated as dependencies, so the build will fail unless the artifacts exist in the repository (i.e. you've already built them).
If you want to be able to exercise flexibility over the build, I'd recommend separating the responsibilities of assembly and aggregator into different projects.
The aggregator simply declares the projects as modules so you can conveniently build all the projects in one command.
The assembly project (your project X) declares dependencies on projects A, B and C. When you build project X it is required that the others have already been built, but if built in the aggregator, the reactor will have built them first. Whereas if you build it standalone, you know the others are up to date.
Some additional points on Maven usage that should clarify this approach.
The Maven repository is a record of all the artifacts you've developed. You don't need to clear the local repository between builds. It is intended to act as a repository of all the artifacts. So if you install project A, that is the version that will always be used (unless and until you rebuild project A).
If you do have to clear the local repository, you should deploy your artifacts to a remote repository (see the relevant section of the Nexus book for guidance on getting started) so they can be incorporated into your build for project X even if the local repository is cleared.
So the workflow for building the projects is:
Run mvn install on the aggregator project or the relevant project (A,B, or C).
Projects are installed to the local repository.
Don't clear the local repository!
Run mvn install on project X, Maven will retrieve the dependencies from the repository and package them into your assembly.
If you use mvn deploy, the same principles apply, but because the artifacts are in the remote repository you have freedom to clear the local repository.
To emphasise my earlier points:
There is no mechanism to conditionally build modules. They either build or they don't (however some steps of the build might be skipped if they are not needed, e.g. compilation might have already been done in a previous build)
There is no need to purge the local repository (and if you do, you should have the modules deployed to a remote repository so they can be retrieved).
ok I should have been more clear on why I was clearing down the local repo - I understand this is not a normal step as part of the build cycle.
I was clearing down my local repo to emulate what would happen if I tried a build for the very first time and nothing exists on a remote repo. This is because on checking out the parent + modules all the code I need is present.
Parent
\----module1 (includes assembly classifier)
|
\----module2
|
\----bundle
eg build with empty repo from parentbuilds module1, module2 then bundle. All works well in this order:
parent, module1, module2, bundle
however if I have an empty repos and cd to X then build maven cannot work out that it needs to build the parent which depends on module1 and module2, so if possible I'd like it to build in this order:
parent, module1, module2, bundle
I think this is not possible in maven as you say there is no mechanism for conditional module builds! I thought maven would support this as it has info on the parent and the parent has info on the children, but I think I was inferring too much.
Many thanks for your replies Rich. Getting there with maven but it is like pulling teeth, in large part due to the style of the sonotype manual.
ps editing of questions looses context. I didn't realise stackoverflow did this. usenet style had it right first time, write your own reply, include references to former replies if required, post at the bottom. Editing prior posts IMHO erases the flow of a conversation - for some issues the journey to the solution is as instructive as the destination! this last paragraph is 400 chars :-)
eg I could not put this comment in as recommended because it goes over the technical sound barrier of 600 characters.
I am using Assembly plugin for maven to create an installation package.
For my packaging requirement, I need to split artifacts generated during the build and all dependencies into separate folders.
My current Assembly manifest is as follows:
<moduleSets>
<moduleSet>
<includes>
<include>test:test</include>
</includes>
<binaries>
<includeDependencies>false</includeDependencies>
<outputDirectory>lib/custom/${artifactId}</outputDirectory>
<unpack>false</unpack>
</binaries>
</moduleSet>
<moduleSet>
<includes>
<include>test:test</include>
</includes>
<binaries>
<includeDependencies>true</includeDependencies>
<excludes>
<exclude>test:test</exclude>
</excludes>
<outputDirectory>lib/thirdParty/</outputDirectory>
<unpack>false</unpack>
</binaries>
</moduleSet>
</moduleSets>
First moduleset correctly generates only currently built assembly.
However, thirdParty includes the currently built assembly as well. How would I go about excluding the files already included in the first set?
Thanks
What about using dependency:copy-dependencies? I use that to copy all deps to target/lib .
One kludgy way to do it is with the maven-antrun-plugin and an ant task. Iterate the contents of lib/custom/${artifactId} and remove any files from lib/thirdParty.
You might want to look at appassembler-maven-plugin. It lets you dump all your runtime dependency jars in a directory. You might be able to hack that up to put your main jar in one folder and then dump the dependencies into another.
I am creating an assembly with packaging=war.
I need to include few of the jars, which have been declared as project dependencies in pom.xml in my war (web-inf/lib)
How can I do this?
Edited on 15/10-
My project creates few assemblies, one of which is supposed to give packaging of type-war.
Some jar files, which are dependencies for the project(and have been declared in pom.xml)need be included in war under WEB-INF.
How can I include them or how can i point out their paths to my local nexus repository path?
Can you be more precise? By default, when you run the mvn clean install command on a war project, Maven 2 will include all dependencies in WEB-INF/lib directories, excluding the ones with the scope test and provided.
If you create your war file using an assembly, then you have an assembly.xml file, which defines the content of your final war file. In this file, you can specify the list of dependencies you want to include:
<assembly>
...
<dependencySets>
<dependencySet>
<includes>
<include>log4j:log4j</include>
<include>commons-lang:commons-lang</include>
...
</includes>
<unpack>false</unpack>
<outputDirectory>WEB-INF/lib</outputDirectory>
</dependencySet>
</dependencySets>
</assembly>
(in this example, I asked to add log4j and commons-lang dependencies).
For each dependency, you need to specify the groupId and the artifactId. The version is automatically detected regarding the list of dependencies you have set in your pom.xml file.