Why Maven generates a maven directory in a jar when two jars are merged? - maven

I've merged sources from two artifacts/jars into separate single jar using assembly plugin. However, looking at the content of the new jar file at META-INF/maven there is a maven directory which contains packages from both of those jars.
Few questions:
1 - What is the purpose of that META-INF/maven dir?
2 - How/who generate that file and why?
3 - Is there an option to remove it from the archive and how?
4 - What is the impact if we removed it from the archive?
Here is my plugin:
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<executions>
<execution>
<id>merge-two-jars</id>
<phase>prepare-package</phase>
<goals>
<goal>single</goal>
</goals>
<configuration>
<finalName>com.ibm.scope.ext.system.agent-${scope.release}-${ibm.build.number}</finalName>
<appendAssemblyId>false</appendAssemblyId>
<descriptors>
<descriptor>src/main/assembly/ppk-agent-merge-agent-common.xml</descriptor>
</descriptors>
<archive>
<manifestFile>src/main/resources/META-INF/MANIFEST.MF</manifestFile>
<addMavenDescriptor>false</addMavenDescriptor>
</archive>
</configuration>
</execution>
</executions>
.....

Informational purpose - maven feature
Maven for informational purpose
For JAR, EAR, and WAR Plugins. Use <archive><addMavenDescriptor>false</addMavenDescriptor></archive> to exclude META-INF/maven, MWAR-27
No impact
Overriding Manifest
<project>
[...]
<build>
[...]
<plugins>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.4</version>
<configuration>
[...]
<archive>
<addMavenDescriptor>false</addMavenDescriptor>
</archive>
</configuration>
[...]
</plugin>
[...]
</project>
More about Maven Manifest: Maven Archiver

Related

Executing Maven Project [duplicate]

I have a code base which I want to distribute as jar. It also have dependency on external jars, which I want to bundle in the final jar.
I heard that this can be done using maven-assembly-plug-in, but I don't understand how. Could someone point me to some examples.
Right now, I'm using fat jar to bundle the final jar. I want to achieve the same thing using maven.
Note: If you are a spring-boot application, read the end of answer
Add following plugin to your pom.xml
The latest version can be found at
...
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<version>CHOOSE LATEST VERSION HERE</version>
<configuration>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
<executions>
<execution>
<id>assemble-all</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
...
After configuring this plug-in, running mvn package will produce two jars: one containing just the project classes, and a second fat jar with all dependencies with the suffix "-jar-with-dependencies".
if you want correct classpath setup at runtime then also add following plugin
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<configuration>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<mainClass>fully.qualified.MainClass</mainClass>
</manifest>
</archive>
</configuration>
</plugin>
For spring boot application use just following plugin (choose appropriate version of it)
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<fork>true</fork>
<mainClass>${start-class}</mainClass>
</configuration>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
You can use the maven-shade-plugin.
After configuring the shade plugin in your build the command mvn package will create one single jar with all dependencies merged into it.
Maybe you want maven-shade-plugin, bundle dependencies, minimize unused code and hide external dependencies to avoid conflicts.
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.1.1</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<minimizeJar>true</minimizeJar>
<createDependencyReducedPom>true</createDependencyReducedPom>
<dependencyReducedPomLocation>
${java.io.tmpdir}/dependency-reduced-pom.xml
</dependencyReducedPomLocation>
<relocations>
<relocation>
<pattern>com.acme.coyote</pattern>
<shadedPattern>hidden.coyote</shadedPattern>
</relocation>
</relocations>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
References:
http://maven.apache.org/plugins/maven-shade-plugin/plugin-info.html
http://maven.apache.org/plugins/maven-shade-plugin/shade-mojo.html
actually, adding the
<archive>
<manifest>
<addClasspath>true</addClasspath>
<packageName>com.some.pkg</packageName>
<mainClass>com.MainClass</mainClass>
</manifest>
</archive>
declaration to maven-jar-plugin does not add the main class entry to the manifest file for me.
I had to add it to the maven-assembly-plugin in order to get that in the manifest
You can use the onejar-maven-plugin for packaging. Basically, it assembles your project and its dependencies in as one jar, including not just your project jar file, but also all external dependencies as a "jar of jars", e.g.
<build>
<plugins>
<plugin>
<groupId>com.jolira</groupId>
<artifactId>onejar-maven-plugin</artifactId>
<version>1.4.4</version>
<executions>
<execution>
<goals>
<goal>one-jar</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
Note 1: Configuration options is available at the project home page.
Note 2: For one reason or the other, the onejar-maven-plugin project is not published at Maven Central. However jolira.com tracks the original project and publishes it to with the groupId com.jolira.
An alternative is to use the maven shade plugin to build an uber-jar.
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version> Your Version Here </version>
<configuration>
<!-- put your configurations here -->
</configuration>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
</execution>
</executions>
</plugin>
Read if you want to use the maven-assembly-plugin.
As other answers have already outlined, it seems that the maven-shade-plugin offers more features and is the recommended plugin to build a fat jar, but in case you would like to use the maven-assembly-plugin the following plugin configuration will work.
The answer of #jmj explains that the correct classpath can be setup with an additional maven-jar-plugin, but this will only add the classpath to the original jar and not the fat jar. The information must instead be directly included into the configuration section of the maven-assembly-plugin.
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<version>3.4.2</version>
<configuration>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<mainClass>com.package.YourMainClass</mainClass>
</manifest>
</archive>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
<executions>
<execution>
<id>assemble-all</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
When you now run maven package, your normal and fat jar will be created and you can run your fat jar with java -jar yourJar.jar.

Include only certain packages in a Maven generated non-runnable jar

I'm trying to build a non-executable jar file that only includes certain packages from my project to use as a library for common code. I'm planning on deploying that to Nexus and including it in other projects.
I can make it manually in eclipse by right clicking on the project, selecting Export, selecting JAR file (NOT Runnable Jar File) then checking the packages that I want to include. I'm trying to mimic this behavior in Maven. I have been able to replicate the non-runnable part in maven by not including a main in the manifest, but still have to find out how to include only certain packages.
This project actually builds 2 jar files already (from 2 different main's in the program - a test GUI and the regular application). I'm having trouble finding information on how to do the non-runnable jar and selecting certain packages only.
Here is the existing build portion of my pom file is below. Build-third is the non-runnable jar:
<plugins>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.4</version>
<executions>
<execution>
<id>build-first</id>
<configuration>
<appendAssemblyId>false</appendAssemblyId>
<archive>
<manifest>
<mainClass>com.joy.fb20.da.exec.jDaExecutive</mainClass>
</manifest>
</archive>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
<finalName>DaExecutive</finalName>
</configuration>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
<execution>
<id>build-second</id>
<configuration>
<appendAssemblyId>false</appendAssemblyId>
<archive>
<manifest>
<mainClass>com.joy.fb20.gui.jExampleAppGui</mainClass>
</manifest>
</archive>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
<finalName>ExampleAppGui</finalName>
</configuration>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
<execution>
<id>build-third</id>
<configuration>
<appendAssemblyId>false</appendAssemblyId>
<archive>
<manifest>
</manifest>
</archive>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
<finalName>ddslib</finalName>
</configuration>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</plugin>
</plugins>
</build>
Tried this myself and it is possible.
Create a new maven profile
Add pluginManagement section to that new profile for maven-jar-plugin and if needed for maven-resources-plugin also
Use this pluginManagement to configure inclusions/exclusions of sources/resources and override artifacts final name here to have different name for that separate jar
Example
<profiles>
<profile>
<id>subset</id>
<build>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>3.0.2</version>
<configuration>
<finalName>subset</finalName>
<includes>
<include>org/example/stuff/**</include>
</includes>
</configuration>
</plugin>
</plugins>
</pluginManagement>
</build>
</profile>
</profiles>
Using this profile maven creates subset.jar that has everything under org/example/stuff/**
See more about excluding: How to exclude a set of packages from maven build jar?
Of course it might be possible to do all this also without pluginManagement but in my opinion pluginManagement provides clean & flexible way to configure this kind of stuff so i recommend that.
You should be able to do that by using a custom assembly descriptor and specifying your fileset and / or file includes / excludes. See https://maven.apache.org/plugins/maven-assembly-plugin/assembly.html#class_fileSet

How to combine javafx-maven-plugin and maven-assembly-plugin?

I have a JavaFx project which I want to reduce to one jar file.
My pom contains a java-fx plugin:
<plugin>
<groupId>com.zenjava</groupId>
<artifactId>javafx-maven-plugin</artifactId>
<version>8.1.4</version>
<configuration>
<mainClass>application.Main</mainClass>
<jfxAppOutputDir>${project.build.directory}/jfx/app</jfxAppOutputDir>
</configuration>
<executions>
<execution>
<id>create-jfxjar</id>
<phase>package</phase>
<goals>
<goal>build-jar</goal>
</goals>
</execution>
</executions>
</plugin>
and an assembly plugin:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.4.1</version>
<configuration>
<!-- get all project dependencies -->
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
<!-- MainClass in mainfest make a executable jar -->
<archive>
<manifest>
<mainClass>application.Main</mainClass>
</manifest>
</archive>
</configuration>
<executions>
<execution>
<id>make-assembly</id>
<!-- bind to the packaging phase -->
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
When I call "mvn package" a single jar file is being build but it does not contain the jfx-jar file but contains some sort of "jar wihout jfx support"-version.
How can I tell the Maven Assembly Plugin to use the jar version from the jfx plugin (which is located in jfxAppOutputDir (../jfx/app/))?
Found the problem myself.
the jar file with the "no main manifest attribute"-error was created by maven-jar-plugin. But it is possible to configure it to omit that creation. If you are interested please take a look:"what-is-the-best-way-to-avoid-maven-jar"
the assembly plugin worked correctly. It was my fault. I thought that the assembly plugin creates a jar file with all dependencies including all resource files(all files from the resource folder). My mistake. "jar-with-dependencies" includes all jars belonging to the project, nothing more.

include package in maven while preparing jar

I have below project structure. I wanted to prepare a jar with dependencies including different packages which has .java files.
Project Structure:
src/com/rev/automation/utilities
src/com/rev/automation/testdata
src/com/rev/automation/pages
Main Class:
org.openqa.selenium.remote
How to include "src/com/rev/automation" packages into the jar in maven? i'm preparing the jar using below code, But it is not including packages and files present in "src/com/rev/automation". Kindly suggest
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.4.1</version>
<configuration>
<!-- get all project dependencies -->
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
<!-- MainClass in mainfest make a executable jar -->
<archive>
<manifest>
<mainClass>org.openqa.selenium.remote.RemoteWElement</mainClass>
</manifest>
</archive>
</configuration>
<executions>
<execution>
<id>make-assembly</id>
<!-- bind to the packaging phase -->
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
While using Maven, you need to follow the Maven Standard Directory Structure.
In your case, create a folder structure like src/main/java and put all your code in java directory. So it should now look like src/main/java/com/rev/automation etc.
If you follow this structure, then your package will get included in the jar.
Update:
If you absolutely don't want to / cannot do what is mentioned above, alternatively, you can use the Maven Build Helper plugin. This will tell maven to include the specified directory as an additional source directory.
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>build-helper-maven-plugin</artifactId>
<version>1.7</version>
<executions>
<execution>
<id>add-source</id>
<phase>generate-sources</phase>
<goals>
<goal>add-source</goal>
</goals>
<configuration>
<sources>
<source>src</source> // specify your directory here
...
</sources>
</configuration>
</execution>
</executions>
</plugin>

Building a fat jar using maven

I have a code base which I want to distribute as jar. It also have dependency on external jars, which I want to bundle in the final jar.
I heard that this can be done using maven-assembly-plug-in, but I don't understand how. Could someone point me to some examples.
Right now, I'm using fat jar to bundle the final jar. I want to achieve the same thing using maven.
Note: If you are a spring-boot application, read the end of answer
Add following plugin to your pom.xml
The latest version can be found at
...
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<version>CHOOSE LATEST VERSION HERE</version>
<configuration>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
<executions>
<execution>
<id>assemble-all</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
...
After configuring this plug-in, running mvn package will produce two jars: one containing just the project classes, and a second fat jar with all dependencies with the suffix "-jar-with-dependencies".
if you want correct classpath setup at runtime then also add following plugin
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<configuration>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<mainClass>fully.qualified.MainClass</mainClass>
</manifest>
</archive>
</configuration>
</plugin>
For spring boot application use just following plugin (choose appropriate version of it)
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<fork>true</fork>
<mainClass>${start-class}</mainClass>
</configuration>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
You can use the maven-shade-plugin.
After configuring the shade plugin in your build the command mvn package will create one single jar with all dependencies merged into it.
Maybe you want maven-shade-plugin, bundle dependencies, minimize unused code and hide external dependencies to avoid conflicts.
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.1.1</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<minimizeJar>true</minimizeJar>
<createDependencyReducedPom>true</createDependencyReducedPom>
<dependencyReducedPomLocation>
${java.io.tmpdir}/dependency-reduced-pom.xml
</dependencyReducedPomLocation>
<relocations>
<relocation>
<pattern>com.acme.coyote</pattern>
<shadedPattern>hidden.coyote</shadedPattern>
</relocation>
</relocations>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
References:
http://maven.apache.org/plugins/maven-shade-plugin/plugin-info.html
http://maven.apache.org/plugins/maven-shade-plugin/shade-mojo.html
actually, adding the
<archive>
<manifest>
<addClasspath>true</addClasspath>
<packageName>com.some.pkg</packageName>
<mainClass>com.MainClass</mainClass>
</manifest>
</archive>
declaration to maven-jar-plugin does not add the main class entry to the manifest file for me.
I had to add it to the maven-assembly-plugin in order to get that in the manifest
You can use the onejar-maven-plugin for packaging. Basically, it assembles your project and its dependencies in as one jar, including not just your project jar file, but also all external dependencies as a "jar of jars", e.g.
<build>
<plugins>
<plugin>
<groupId>com.jolira</groupId>
<artifactId>onejar-maven-plugin</artifactId>
<version>1.4.4</version>
<executions>
<execution>
<goals>
<goal>one-jar</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
Note 1: Configuration options is available at the project home page.
Note 2: For one reason or the other, the onejar-maven-plugin project is not published at Maven Central. However jolira.com tracks the original project and publishes it to with the groupId com.jolira.
An alternative is to use the maven shade plugin to build an uber-jar.
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version> Your Version Here </version>
<configuration>
<!-- put your configurations here -->
</configuration>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
</execution>
</executions>
</plugin>
Read if you want to use the maven-assembly-plugin.
As other answers have already outlined, it seems that the maven-shade-plugin offers more features and is the recommended plugin to build a fat jar, but in case you would like to use the maven-assembly-plugin the following plugin configuration will work.
The answer of #jmj explains that the correct classpath can be setup with an additional maven-jar-plugin, but this will only add the classpath to the original jar and not the fat jar. The information must instead be directly included into the configuration section of the maven-assembly-plugin.
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<version>3.4.2</version>
<configuration>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<mainClass>com.package.YourMainClass</mainClass>
</manifest>
</archive>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
<executions>
<execution>
<id>assemble-all</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
When you now run maven package, your normal and fat jar will be created and you can run your fat jar with java -jar yourJar.jar.

Resources