Maven assembly plug-in - how to produce artifact with custom file extension? - maven

I am producing an artifact named foo.bar.zip from the following...
My pom.xml plug-in entry looks like this:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<configuration>
<descriptor>src/assembly/bin.xml</descriptor>
<finalName>foo.bar</finalName>
</configuration>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
My descriptor file looks like this:
<?xml version="1.0" encoding="UTF-8"?>
<assembly>
<formats>
<format>zip</format>
</formats>
<fileSets>
etc. etc.
My question, is how do I produce a file with a custom extension? E.g. with the name foo.bar instead of foo.bar.zip.

I solved this by combining:
maven-assembly-plugin
copy-rename-maven-plugin
build-helper-maven-plugin
The assembly plugin has a configuration option to not attach the file, so I do that:
<configuration>
...
<attach>false</attach>
</configuration>
Then I use the copy-rename-maven-plugin to rename the file, produced by assembly-plugin, from zip to my custom file type (in my case it is CLI).
After that I use build-helper-maven-plugin to attach the artifact with the custom file type.

Assembly supports just these formats:
"zip" - Creates a ZIP file format
"tar" - Creates a TAR format
"tar.gz" or "tgz" - Creates a gzip'd TAR format
"tar.bz2" or "tbz2" - Creates a bzip'd TAR format
"jar" - Creates a JAR format
"dir" - Creates an exploded directory format
"war" - Creates a WAR format
You should consider to use antrun plugin in a later goal/phase to rename file extension

Related

Zip file empty using maven assembly plugin in pom

my pom.xml but i have written something like
.......
..........
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.5.3</version>
<configuration>
<finalName>${project.artifactId}</finalName>
<descriptor>assembly.xml</descriptor>
</configuration>
<executions>
<execution>
<id>create-archive</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
..........
.......
My assembly.xml is
<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>${project.version}</id>
<includeBaseDirectory>false</includeBaseDirectory>
<formats>
<format>zip</format>
</formats>
<fileSets>
<fileSet>
<directory>${project.basedir}/${create.stage.directory}</directory>
<includes>
<include>*.*</include>
</includes>
<outputDirectory>${project.basedir}/${create.release.directory}</outputDirectory>
</fileSet>
</fileSets>
</assembly>
This creates an EMPTY foldername.zip in target!!NOT IN THE OUTPUT FOLDER LOCATION THAT I HAVE GIVEN.Is it always target? cant i override??
But in the given directory path I have 3 folders (in which some files) and readme.txt.I just tried giving *.txt inside include tag still I got empty zip folder. I initially guessed that my directory path and output directory path can be wrong.I directly hardcode still there is no luck.
Please help (This question is not duplicate but similar, and I have tried almost all stackoverflow questions related to this.they haven't solved anything)
For details see http://maven.apache.org/plugins/maven-assembly-plugin/assembly.html#class_fileSet
Your descriptor is now configured like this:
create a zip called ${project.artifactId}
from the directory ${project.basedir}/${create.stage.directory} put all files with an extension (not directories, since it says *.*, not something like **/*.* in the ${project.basedir}/${create.release.directory} folder inside the zip.
Especially the last part is weird. Where in the zip should these files end? It should be a relative path to make it predictable.
Don't like the zip file to be created in target? Set the outputDirectory in the plugin configuration, not in the assembly descriptor.

Maven: Three Jars in one project. Trying to use an assembly, but not getting pom.xml and pom.properties embedded in the jars

I have a project that produces three different jar files:
Server.jar: This contains all classes and resources. A standard jar
Client.jar: This contains only a few external classes and no resources.
ServerSDK.jar: This contains all the classes, resources, test classes, and other configuration files.
I've decided to do all three jars in a single project, so a change in any of the sources spawns a Jenkins build and deploys all three at once. I build the Server.jar as my standard pom.xml jar. Then, I use assemblies to build the Client.jar and the ServerSDK.jar.
I have the assemblies that build the other two jars, and everything is 99% of the way I like it, but there is bit of munging I'd like to do.
We add a few entries in our MANIFEST.MF file to incorporate the Jenkins build information and project information.
In a standard Maven jar, the pom.xml and pom.properties are embedded in the META-INF directory.
The first one I have managed to do via the <assembly> configuration in my maven-assembly-plugin. The second one I can't seem to get to work even though I have <addMavenDescriptor> set to true in my <assembly> configuration.
Here's my maven-assembly-plugin section in my pom.xml
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.6</version>
<configuration>
<archive>
<addMavenDescriptor>true</addMavenDescriptor>
<manifestSections>
<manifestSection>
<name>Build-Information</name>
<manifestEntries>
<Project-Name>${env.JOB_NAME}</Project-Name>
<Build-Number>${env.BUILD_NUMBER}</Build-Number>
<SVN-Revision>${env.SVN_REVISION}</SVN-Revision>
</manifestEntries>
</manifestSection>
<manifestSection>
<name>Module-Information</name>
<manifestEntries>
<Group-ID>${project.groupId}</Group-ID>
<Artifact-ID>${project.artifactId}</Artifact-ID>
<Version>${project.version}</Version>
</manifestEntries>
</manifestSection>
</manifestSections>
</archive>
</configuration>
<executions>
<execution>
<id>Client</id>
<configuration>
<finalName>Client</finalName>
<appendAssemblyId>true</appendAssemblyId>
<descriptors>
<descriptor>src/assembly/client.xml</descriptor>
</descriptors>
</configuration>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
The <manifestSections> work just fine, but the <addMavenDescriptor> doesn't seem to be working although I've explicitly set it to true.
According to the documentation on the maven-archiver-plugin:
Whether the created archive will contain these two Maven files:
The pom file, located in the archive in META-INF/maven/${groupId}/${artifactId}/pom.xml
A pom.properties file, located in the archive in META-INF/maven/${groupId}/${artifactId}/pom.properties
The default value is true.
According the maven-assembly-plugin page:
<archive>
This is a set of instructions to the archive builder, especially for building .jar files. It enables you to specify a Manifest file for the jar, in addition to other options. See Maven Archiver Reference
Is there something simple I'm missing here?
The Maven Assembly Plugin actually ignores the addMavenDescriptor parameter, and will never include the Maven descriptor in the resulting assembly. This can be seen in the source code: only the META-INF/MANIFEST.MF file is possibly added to the JAR archive.
I couldn't find an existing JIRA issue about this, so I went ahead and created MASSEMBLY-835 to track this.
A work-around for now would be to add the files yourself in the assembly descriptor:
<assembly xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.3"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.3 http://maven.apache.org/xsd/assembly-1.1.3.xsd">
<id>client</id>
<formats>
<format>jar</format>
</formats>
<includeBaseDirectory>false</includeBaseDirectory>
<files>
<file>
<source>pom.xml</source>
<outputDirectory>META-INF/maven/${project.groupId}/${project.artifactId}</outputDirectory>
</file>
<file>
<source>${project.build.directory}/maven-archiver/pom.properties</source>
<outputDirectory>META-INF/maven/${project.groupId}/${project.artifactId}</outputDirectory>
</file>
</files>
<!-- rest of your configuration -->
</assembly>
This adds a <files> configuration that adds the pom.xml and the generated pom.properties into the target directory.
Note that the pom.properties is generated by the Maven Archiver component during the default package goal into the target/maven-archiver directory; therefore, in order for it to be present when making your assembly, the Assembly Plugin has to be bound to the phase package (or later in the lifecycle), and the current Maven project needs to be of packaging JAR / WAR / EAR / EJB / RAR... but not POM which doesn't package an archive. The primary artifact of the Maven project also needs to be built (if you skip the generation of the primary JAR of a JAR project, the pom.properties won't be generated).
This works in a large majority of cases. But if you want a bullet-proof solution, you can just create the file yourself. Create a pom.properties somewhere in your project (example, base directory) with the following content:
#Generated by Apache Maven ${maven.version}
version=${project.version}
groupId=${project.groupId}
artifactId=${project.artifactId}
and in the previous assembly descriptor, have instead:
<file>
<source>pom.properties</source>
<outputDirectory>META-INF/maven/${project.groupId}/${project.artifactId}</outputDirectory>
<filtered>true</filtered>
</file>
This would correctly replace the placeholders inside the pom.properties that was created, and mimic what Maven Archiver would do.

how to generate additional jar which having correct and complete manifest file for Bamboo deployment?

Basically, I want to generate a jar file named <project.name>.jar in addition to default jar file(which in my case is something like <project.name> + <project.version>.jar). NOTICE : This <project.name>.jar is all the same to default jar but the name.
And this additional jar should have a manifest file like below which is the manifest file of default generated jar
anifest-Version: 1.0
Archiver-Version: Plexus Archiver
Built-By: XXX
Start-Class: com.XXXX.XXX.Application
Spring-Boot-Version: 1.3.1.RELEASE
Created-By: Apache Maven
Build-Jdk: 1.8.0_74
Main-Class: org.springframework.boot.loader.JarLauncher
I am adding additional block in my as follows
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<executions>
....
<execution>
<id>copy-jar</id>
<phase>package</phase>
<goals><goal>jar</goal></goals>
<configuration>
<finalName>${project.name}</finalName>
</configuration>
</execution>
<execution>
</plugin>
But in my case, the manifest file generated in my addition jar don't have following impart fields:
Start-Class
Main-Class
...
So it couldn't be deployed.
I know the requirement sounds weird, but the question is clear, how to make maven generate a jar which having a correct and complete manifest file for deployment?
//The complete plugin part
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<executions>
<execution>
<goals><goal>test-jar</goal></goals>
</execution>
<execution>
<id>copy-jar</id>
<phase>package</phase>
<goals><goal>jar</goal></goals>
<configuration>
<finalName>${project.artifactId}</finalName>
</configuration>
</execution>
<execution>
<id>dto-jar</id>
<goals><goal>jar</goal></goals>
<phase>package</phase>
<configuration>
<finalName>${project.artifactId}-dto</finalName>
<includes>
<include>**/dto/*</include>
<include>**/dto</include>
<include>**/exceptions/*</include>
<include>**/exceptions</include>
<include>**/utils/*</include>
<include>**/utils</include>
</includes>
</configuration>
</execution>
</executions>
</plugin>
Concerning your maven-jar-plugin section:
You are having three executions: one for the test-jar goal, two for the jar goal
one of them re-using the default execution id (default-jar) to specify the finalName entry, but not specifying any manifest configuration. According to this configuration, your manifest file should also be empty then, not coherent with the description provided by your question then.
the additional jar goal execution has a further configuration with customizated option, nothing wrong here, except that you except to have a properly filled manifest file as part of it, while (again) there is no configuration for it.
A possible explanation would be that your pom also provides a pluginManagement section, with further configuration for the maven-jar-plugin, or a parent pom at its top which would then specify a further configuration for the same.
To double check this, you could run
mvn help:effective-pom -Doutput=eff-pom.xml
And check the content of the generated eff-pom.xml file. That would be the single source of truth for your case.
Looking at your manifest entry:
Spring-Boot-Version: 1.3.1.RELEASE
Main-Class: org.springframework.boot.loader.JarLauncher
It makes quite clear that you are working on a Spring Boot project, normally having a Spring Boot parent pom which already configures the required manifest file. However, it makes use of a fat-jar (jar with dependencies or uber jar), not built via the maven-jar-plugin but via the maven-assembly-plugin.
As an example:
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.4</version>
<configuration>
<descriptors>
<descriptor>src/main/assembly/jar-with-dependencies.xml</descriptor>
</descriptors>
<archive>
<manifest>
<mainClass>org.springframework.boot.loader.JarLauncher</mainClass>
</manifest>
<manifestEntries>
<Start-Class>org.springframework.boot.load.it.jar.EmbeddedJarStarter</Start-Class>
</manifestEntries>
</archive>
</configuration>
<executions>
<execution>
<id>jar-with-dependencies</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
Hence you should not look at the Jar Plugin solution, but rather add a further Assembly Plugin execution for the same.
Just quick share of some other aspects of this problem. actually pom file should never be in charge of deployment business(even though It could, but very likely bring into more issues in the future). This part should be fully managed by bamboo deploy script. That is what I eventually did.

Why maven assembly create manifest if file format is rar?

I have a Maven project with the following assembly descriptor:
<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>assemby-id</id>
<formats>
<format>rar</format>
</formats>
<includeBaseDirectory>false</includeBaseDirectory>
<files>
<file>
<source>${project.build.directory}/resources/file.txt</source>
<outputDirectory>/</outputDirectory>
</file>
</files>
If the format is rar, I get a folder META-INF with a manifest file in the rar.
Can someone explain why?
The maven-assembly-plugin does not support the rar archive format. Quoting the format documentation, the list of supported formats is:
"zip" - Creates a ZIP file format
"tar" - Creates a TAR format
"tar.gz" or "tgz" - Creates a gzip'd TAR format
"tar.bz2" or "tbz2" - Creates a bzip'd TAR format
"jar" - Creates a JAR format
"dir" - Creates an exploded directory format
"war" - Creates a WAR format
When the archiver encounters an unknown format, it defaults to jar and for this format, a META-INF directory is created by default.
As such, the assembly you have created is not a valid RAR file. It is in fact a JAR file.
The maven-assembly-plugin uses the maven-archiver for packaging. The maven-archiver adds a MANIFEST.MF to your package.
Update:
As mentioned here, you may configure the maven-archiver-plugin to leave out the DefaultImplementationEntries:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<configuration>
<archive>
<manifest>
<addDefaultImplementationEntries>false</addDefaultImplementationEntries>
</manifest>
</archive>
</configuration>
</plugin>

maven assembly plugin excludes .gitignore

Maven assembly plugin exludes .gitignore files in the final zip package. How do I include .gitignore in the final output zip?
I tried include **/*, but didn't work.
My assembly file:
<id>assembly</id>
<includeBaseDirectory>false</includeBaseDirectory>
<formats>
<format>zip</format>
</formats>
<fileSets>
<fileSet>
<directory>${project.build.directory}/work</directory>
<outputDirectory>/</outputDirectory>
<excludes>
<exclude>How*.html</exclude>
</excludes>
</fileSet>
</fileSets>`
Assembly plugin:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.5.5</version>
<configuration>
<descriptors>
<descriptor>assembly/config.xml</descriptor>
</descriptors>
</configuration>
<executions>
<execution>
<id>build-archive</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
After some research, I found that .gitignore and other source repository control files (.svn) are excluded in the final package. Maven does this by default. I had to explicitly set the flag - false to include .gitignore files.
As per maven documentation - useDefaultExcludes -
Whether standard exclusion patterns, such as those matching CVS and
Subversion metadata files, should be used when calculating the files
affected by this set. For backward compatibility, the default value is
true
.
Three suggestions:
1- Try files element beside fileSet in your assembly file. It specifies which single files to include in the assembly. A file is specified by providing one or more of file subelements.
2- Set baseDirectory properly. for example
<baseDirectory>../</baseDirectory>
3- Or, set includeBaseDirectory to true
<includeBaseDirectory>true</includeBaseDirectory>
Think of that, that Linux and MacOS don't show files in the Finder that start with a dot.
Use: Command + Shift + "."
to show hidden files.
Then I would also use :
<files>
<file>
<source> 'absolute or relative path' </source>
</file>
</files>
If you think that still does not work and its still ignoring .gitignore
Try this workaround:
Rename your .gitignore file to _gitignore_
enter image description here
If the gitignore is now in your zip as "my-project.jar" than its working.
If you set destination name to .gitignore and its just not showing up -> its hidden.
Use: Command + Shift + "."

Resources