I'm starting to work with Maven but am not yet successfully thinking in Maven's terms. I have a specific requirement and the docs aren't giving me enough clues, so I could use a bit of help:
I'd like to create an assembly that
builds a jar-with-dependencies like the "standard" target of this name, but excluding a couple of the resources. I want log4j.properties and a couple of other configuration files to not be in the jar.
builds a .ZIP file containing in its root directory the .jar from step 1 as well as the above mentioned config files.
I want to fire this assembly up from the command line (only), hence no need to tie to a phase (or goal? mojo?). Preferrably using either assembly:assembly or assembly:single.
Do I need a custom assembly descriptor for this?
And is it true I can't nest it in the pom.xml? So it goes in src/assembly/something.xml and gets referenced with a descriptorRef?
Can I code this as two relatively simple assemblies, of which one builds on the other (i.e. the .Zip assembly uses the .Jar assembly) or do I have to do everything in one assembly?
I'm starting to work with Maven but am not yet successfully thinking in Maven's terms.
Welcome on board, Carl! :D
I want to fire this assembly up from the command line (only), hence no need to tie to a phase (or goal? mojo?). Preferrably using either assembly:assembly or assembly:single.
Just to clarify: the build lifecycle itself is made of phases (compile, test, package, etc) and plugin goals (technically Mojos) are bound on phases. You then either invoke a phase... or just a specific plugin goal.
Do I need a custom assembly descriptor for this?
Well, since you want behavior that the pre-defined descriptors don't cover, yes. You'll even need two of them (of for the uberjar, one for the zip).
And is it true I can't nest it in the pom.xml? So it goes in src/assembly/something.xml and gets referenced with a descriptorRef?
Yes, that's true (descriptors use a custom format) and they usually go into src/main/assembly. And no, descriptorRef is for the built-in descriptors, you'll have to use descriptor here.
Can I code this as two relatively simple assemblies, of which one builds on the other (i.e. the .Zip assembly uses the .Jar assembly) or do I have to do everything in one assembly?
As hinted, you'll need two assembly descriptors. Let me help a bit...
Let's assume you have the following project structure:
$ tree .
.
├── pom.xml
└── src
├── main
│ ├── assembly
│ │ ├── jar.xml
│ │ └── zip.xml
│ ├── java
│ │ └── com
│ │ └── stackoverflow
│ │ └── App.java
│ └── resources
│ └── log4j.properties
└── test
└── java
└── com
└── stackoverflow
└── AppTest.java
Where the pom.xml contains the following configuration for the assembly plugin:
<project>
...
<dependencies>
...
</dependencies>
...
<build>
<plugins>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.2-beta-5</version>
<configuration>
<descriptors>
<descriptor>src/main/assembly/jar.xml</descriptor>
<descriptor>src/main/assembly/zip.xml</descriptor>
</descriptors>
</configuration>
</plugin>
</plugins>
</build>
</project>
The descriptor for the "filtered" uberjar (jar.xml) looks like this:
<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>uberjar</id>
<formats>
<format>jar</format>
</formats>
<includeBaseDirectory>false</includeBaseDirectory>
<dependencySets>
<dependencySet>
<unpack>true</unpack>
<scope>runtime</scope>
<useProjectArtifact>false</useProjectArtifact>
</dependencySet>
</dependencySets>
<fileSets>
<fileSet>
<directory>${project.build.outputDirectory}</directory>
<outputDirectory>/</outputDirectory>
<excludes>
<exclude>log4j.properties</exclude>
</excludes>
</fileSet>
</fileSets>
</assembly>
What this descriptor does is (in short):
include the dependencies, unpack them, but exclude the project itself (yes, this is counter intuitive but this weird default behavior has been kept for backward compatibility)
include the project files but exclude some of them.
And the descriptor for the zip (zip.xml) looks like this:
<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>
<formats>
<format>zip</format>
</formats>
<includeBaseDirectory>false</includeBaseDirectory>
<fileSets>
<fileSet>
<directory>${project.basedir}/src/main/resources</directory>
<outputDirectory/>
<includes>
<include>log4j.properties</include>
</includes>
</fileSet>
<fileSet>
<directory>${project.build.directory}</directory>
<outputDirectory/>
<includes>
<include>*-uberjar.jar</include>
</includes>
</fileSet>
</fileSets>
</assembly>
Which is (somehow) self explaining :)
it includes the configuration files (relatively to <directory>) at the root of the assembly
it includes the uberjar (relatively to <directory>) at the root of the assembly
Finally, just run mvn assembly:assembly (that's the goal intended to be used on the CLI).
I didn't (knowingly) include META-INF/maven/** in the assembly for the uberjar. Is there a simple way to prevent inclusion of these?
These are coming from the libraries that are unpacked. You can exclude them using unpackOptions. Here is a modified version of the jar.xml:
<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>uberjar</id>
<formats>
<format>jar</format>
</formats>
<includeBaseDirectory>false</includeBaseDirectory>
<dependencySets>
<dependencySet>
<unpack>true</unpack>
<scope>runtime</scope>
<unpackOptions>
<excludes>
<exclude>META-INF/maven/**</exclude>
</excludes>
</unpackOptions>
<useProjectArtifact>false</useProjectArtifact>
</dependencySet>
</dependencySets>
<fileSets>
<fileSet>
<directory>${project.build.outputDirectory}</directory>
<outputDirectory>/</outputDirectory>
<excludes>
<exclude>log4j.properties</exclude>
</excludes>
</fileSet>
</fileSets>
</assembly>
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'm trying to set up a project using Maven and am a bit stuck with how to include some third party dependencies that need to be included unpacked in the resultant war file.
My project contains some custom ColdFusion code and includes Java dependencies, including ColdFusion packaged as a war file. I then am attempting to include some 3rd party ColdFusion code, which I've installed in my maven repository packaged as a jar, but I actually want to deploy it unpacked in the resultant war file. It's this unpacking of the 3rd party libraries that I'm stuck with. I'd really like this to be done BEFORE the war is build, so that I can use war:exploded during the development.
Currently my pom.xml looks something like this:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.mycompany.app</groupId>
<artifactId>my-webapp</artifactId>
<packaging>war</packaging>
<version>1.0-SNAPSHOT</version>
<name>my-webapp Maven Webapp</name>
<url>http://maven.apache.org</url>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
<!-- This is the war overlay -->
<dependency>
<groupId>com.adobe.coldfusion</groupId>
<artifactId>coldfusion</artifactId>
<version>9.0.1</version>
<type>war</type>
<scope>runtime</scope>
<optional>false</optional>
</dependency>
<!-- This is the 3rd party ColdFusion dependency -->
<dependency>
<groupId>org.corfield</groupId>
<artifactId>fw1</artifactId>
<version>1.2RC2A</version>
<scope>provided</scope>
</dependency>
</dependencies>
<build>
<finalName>my-webapp</finalName>
</build>
</project>
I've kind of got it doing what I want by modifying the build section as follows:
<build>
<finalName>${project.artifactId}</finalName>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<id>unpack</id>
<phase>package</phase>
<goals>
<goal>unpack</goal>
</goals>
<configuration>
<artifactItems>
<artifactItem>
<groupId>org.corfield</groupId>
<artifactId>fw1</artifactId>
<version>1.2RC2A</version>
<type>jar</type>
<overWrite>true</overWrite>
<outputDirectory>${project.build.directory}/${project.artifactId}</outputDirectory>
<includes>**/*.cfc</includes>
</artifactItem>
</artifactItems>
<includes>**/*.cfc</includes>
<outputDirectory>${project.build.directory}/${project.artifactId}</outputDirectory>
<overWriteReleases>false</overWriteReleases>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
The problem with this is that the package:unpack happens after the war is built, so the unpacked dependecies are not in the resulting war file.
I have also tried a few things with the assembly plugin and I came fairly close also by using something like this:
<assembly>
<id>${project.artifactId}</id>
<formats>
<format>war</format>
</formats>
<includeBaseDirectory>false</includeBaseDirectory>
<dependencySets>
<dependencySet>
<includes>
<include>org.corfield:fw1</include>
</includes>
<unpack>true</unpack>
<outputDirectory>/</outputDirectory>
</dependencySet>
<dependencySet>
<excludes>
<exclude>org.corfield:fw1</exclude>
</excludes>
<unpack>false</unpack>
<outputDirectory>/WEB-INF/lib</outputDirectory>
</dependencySet>
</dependencySets>
<fileSets>
<fileSet>
<directory>src/main/webapp</directory>
<outputDirectory>/</outputDirectory>
</fileSet>
</fileSets>
</assembly>
However that created a second war file named something like my-webapp-1.0-SNAPSHOT-my-webapp.war as well as the my-webapp-1.0-SNAPSHOT.war. The my-webapp-1.0-SNAPSHOT-my-webapp.war also included my-webapp-1.0-SNAPSHOT.war
At the end of the day I want my resultant war to look like:
org
|-- corfield
|-- framework.cfc
WEB-INF
|-- lib
|-- web.xml
index.cfm
(in reality there's a lot more to it than that, but that's enough to illustrate the point hopefully)
I think I'm pretty close but I'm just missing something I need. I'd be extremely grateful for any assistance.
For the maven-dependency-plugin approach, bind the unpack goal on the prepare-package phase (Maven 2.1+) instead of package.
References
Lifecycle Reference
Have you looked at the overlay option with maven-war-plugin? It esstentially allows you to unpack the ColdFusion war on top your site layout. I've done this with a combination of ColdFusion 9.x and Struts2. Doing a ColdFusion only overlay should make it real easy. You may want to create the ColdFusion war first. You can also then control the neo-*.xml files from your Maven project as well.
I'm trying to write a maven assembly and I'm not sure how to continue. It's fairly complicated, so the examples I google don't really help. This is what I'm trying to do:
Create an installation file using launch4j. This part works, assuming the jar file is correctly assembled (hence the need for a maven assembly.)
The installation program contains some dependencies. These are assembled (currently) using the jar-with-dependencies descriptorRef. This works as well.
I need to include a war file (from another project) into the big jar. This is my confusion.
How do I create an assembly.xml that will do both the jar with dependencies (unpacking all of those jar files) and include a war file from another project (which is not unpacked).
Any help would be appreciated.
How do I create an assembly.xml that will do both the jar with dependencies (unpacking all of those jar files) and include a war file from another project (which is not unpacked).
Assuming you have a project structure similar to the one below (I'm assuming a simple structure since you didn't mention anything particular about it):
.
├── pom.xml
└── src
├── main
│ ├── assembly
│ │ └── uberjar.xml
│ └── java
│ └── com
│ └── stackoverflow
│ └── App.java
└── test
└── java
└── com
└── stackoverflow
└── AppTest.java
With the following pom.xml:
<project>
<modelVersion>4.0.0</modelVersion>
<groupId>com.stackoverflow</groupId>
<artifactId>Q3762049</artifactId>
<version>1.0-SNAPSHOT</version>
<dependencies>
<!-- this is the war we want to include in the assembly -->
<dependency>
<groupId>com.mycompany</groupId>
<artifactId>my-webapp</artifactId>
<version>1.0-SNAPSHOT</version>
<type>war</type>
<scope>runtime</scope>
</dependency>
<!-- and below, the other dependencies -->
<dependency>
<groupId>commons-lang</groupId>
<artifactId>commons-lang</artifactId>
<version>2.4</version>
</dependency>
...
</dependencies>
<build>
<plugins>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.2-beta-5</version>
<configuration>
<descriptors>
<descriptor>src/main/assembly/uberjar.xml</descriptor>
</descriptors>
</configuration>
<executions>
<execution>
<id>make-assembly</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
As you can see,
We are not going to use the predefined jar-with-dependencies descriptor here, we are going to reuse it in our own custom assembly descriptor.
We have a dependency declared on the war with a runtime scope so that we'll be able to include it in the assembly.
And now, the custom uberjar.xml:
<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>uberjar</id>
<formats>
<format>jar</format>
</formats>
<includeBaseDirectory>false</includeBaseDirectory>
<dependencySets>
<dependencySet>
<unpack>true</unpack>
<scope>runtime</scope>
<useProjectArtifact>false</useProjectArtifact>
<excludes>
<exclude>*:war</exclude>
</excludes>
</dependencySet>
<dependencySet>
<unpack>false</unpack>
<scope>runtime</scope>
<useProjectArtifact>false</useProjectArtifact>
<includes>
<include>*:war</include>
</includes>
</dependencySet>
</dependencySets>
<fileSets>
<fileSet>
<directory>${project.build.outputDirectory}</directory>
<outputDirectory>/</outputDirectory>
</fileSet>
</fileSets>
</assembly>
This is a little variation of the jar-with-dependencies descriptor that will create a jar:
the dependencies except the war, unpacked
the war of the webapp, not unpacked
the classes from the project itself
As shown below:
$ mvn clean package
[INFO] Scanning for projects...
...
$ cd target; jar xvf Q3762049-1.0-SNAPSHOT-uberjar.jar
created: META-INF/
inflated: META-INF/MANIFEST.MF
created: org/
created: org/apache/
created: org/apache/commons/
created: org/apache/commons/lang/
created: org/apache/commons/lang/builder/
created: org/apache/commons/lang/enum/
created: org/apache/commons/lang/enums/
created: org/apache/commons/lang/exception/
created: org/apache/commons/lang/math/
created: org/apache/commons/lang/mutable/
created: org/apache/commons/lang/text/
created: org/apache/commons/lang/time/
inflated: META-INF/LICENSE.txt
inflated: META-INF/NOTICE.txt
inflated: org/apache/commons/lang/ArrayUtils.class
...
created: META-INF/maven/
created: META-INF/maven/commons-lang/
created: META-INF/maven/commons-lang/commons-lang/
inflated: META-INF/maven/commons-lang/commons-lang/pom.xml
inflated: META-INF/maven/commons-lang/commons-lang/pom.properties
inflated: my-webapp-1.0-SNAPSHOT.war
created: com/
created: com/stackoverflow/
inflated: com/stackoverflow/App.class
I have a Maven project, where under src/main directory there is a sub dir called output. this folder needs to be packaged into tar.gz. when using the assembly plugin as follows:
From the pom.xml:
<build>
<finalName>front</finalName>
<plugins>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.2-beta-5</version>
<configuration>
<descriptors>
<descriptor>src/main/assembly/assembly.xml</descriptor>
</descriptors>
</configuration>
</plugin>
</plugins>
</build>
the assembly.xml:
<assembly>
<id>bundle</id>
<formats>
<format>tar.gz</format>
</formats>
<fileSets>
<fileSet>
<directory>src/main/output</directory>
</fileSet>
</fileSets>
</assembly>
My problem is that I am trying the outcome will be as running the tar utility itself, meaning when extracting to get output directory and all its content. what I get is the output folder wrapped with all the project path - name/src/main/output.
You need to configure the assembly descriptor to not include the base directory and to configure an output directory for the fileSet:
<assembly>
<id>bundle</id>
<formats>
<format>tar.gz</format>
</formats>
<includeBaseDirectory>false</includeBaseDirectory>
<fileSets>
<fileSet>
<directory>src/main/output</directory>
<outputDirectory>output</outputDirectory>
</fileSet>
</fileSets>
</assembly>
With the above assembly descriptor, I get the following result (when running on a project reproducing the structure):
$ mvn clean assembly:assembly
...
$ cd target
$ tar zxvf Q3330855-1.0-SNAPSHOT-bundle.tar.gz
output/
output/hello.txt
See also
The Assembly Descriptor Format reference
Try setting outputDirectory in the fileSet. That should remove the src/main/output directories.
<fileSet>
<directory>src/main/output</directory>
<outputDirectory>.</outputDirectory>
</fileSet>
You may also need to set includeBaseDirectory to false. That would remove the name directory.
<assembly>
<id>bundle</id>
<includeBaseDirectory>false</includeBaseDirectory>
<!-- ... -->
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.