Below is the pom.xml. When I Try running it with mvn package, the fat jar is not getting built. But mvn assembly:single builds the fat jar.
What am I doing wrong here?
<build>
<sourceDirectory>src</sourceDirectory>
<pluginManagement>
<plugins>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<configuration>
<archive>
<manifest>
<mainClass>com.xyz.main.MainHandler</mainClass>
</manifest>
</archive>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
<executions>
<execution>
<id>make-assembly</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</pluginManagement>
</build>
So, after removing the maven-assembly-plugin from the pluginManagement tags, it worked.
Need clarity checkout this.
Related
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.
Please, could you explain me why my jar file doesn't execute outside the target folder? And how can I do it independent? To copy/paste it to another directory.
When I execute my jar outside target folder, NoClassDefFound error is produced. It can't load jars from dependencies.
This is my pom.xml:
<properties>
<docx4j.version>3.3.0</docx4j.version>
</properties>
<build>
<plugins>
<plugin>
<!-- Build an executable JAR -->
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>2.6</version>
<configuration>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<classpathPrefix>lib/</classpathPrefix>
<mainClass>com.epam.executor.Main</mainClass>
</manifest>
</archive>
</configuration>
</plugin>
<plugin>
<!-- Build an executable JAR with runtime dependencies so that this program can be executed from command line using java -jar command -->
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<version>2.10</version>
<executions>
<execution>
<id>copy-dependencies</id>
<phase>package</phase>
<goals>
<goal>copy-dependencies</goal>
</goals>
<configuration>
<outputDirectory>${project.build.directory}/lib</outputDirectory>
<overWriteReleases>false</overWriteReleases>
<overWriteSnapshots>false</overWriteSnapshots>
<overWriteIfNewer>true</overWriteIfNewer>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>org.docx4j</groupId>
<artifactId>docx4j</artifactId>
<version>${docx4j.version}</version>
</dependency>
</dependencies>
I execute my jar via this command with 3 parameters:
java -jar DocumentTemplate-1.0.jar D:\Trash\xml1.xml D:\Trash\template.docx D:\Trash\results.docx
I think you need to create one jar which includes all its executable dependencies also. I have been you one-jar plugin for it. try below plugin .
<plugin>
<!-- Build an executable JAR -->
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>2.6</version>
<configuration>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<classpathPrefix>lib/</classpathPrefix>
<mainClass>com.kulhade.elasticsearch.Indexer</mainClass>
</manifest>
</archive>
</configuration>
</plugin>
<plugin>
<groupId>org.dstovall</groupId>
<artifactId>onejar-maven-plugin</artifactId>
<version>1.4.4</version>
<executions>
<execution>
<goals>
<goal>one-jar</goal>
</goals>
</execution>
</executions>
</plugin>
Copy Dependencies to a specific directory
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<id>copy-dependencies</id>
<phase>prepare-package</phase>
<goals>
<goal>copy-dependencies</goal>
</goals>
<configuration>
<outputDirectory>${project.build.directory}/${project.build.finalName}.lib</outputDirectory>
</configuration>
</execution>
</executions>
</plugin>
Make the Jar Executable and Classpath Aware
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<configuration>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<classpathPrefix>${project.build.finalName}.lib/</classpathPrefix>
<mainClass>${fully.qualified.main.class}</mainClass>
</manifest>
</archive>
</configuration>
</plugin>
At this point the jar is actually executable with external classpath elements.
$ java -jar target/${project.build.finalName}.jar
I'd like to build an assembly and then sign it. My problem is that the jarsigner signs not the assembly, only the standalone jar file. Could you tell me what is the problem? Maven seems like 'magic' to me after having used Ant for years.. I can't see the way the plugins cooperate and pass information to each other.
After executing mvn install, I get two jar files, one called example-1.0.0-SNAPSHOT.jar and this is signed, and one called example-1.0.0-jar-with-dependencies.jar and this is not signed. I do not need the solo one, only the assembly, but that signed.
Here is my pom.xml:
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jarsigner-plugin</artifactId>
<version>1.2</version>
<executions>
<execution>
<id>sign</id>
<goals>
<goal>sign</goal>
</goals>
</execution>
</executions>
<configuration>
<keystore>${project.basedir}\keystore\mykeystore</keystore>
<alias>myalias</alias>
<storepass>...</storepass>
<keypass>...</keypass>
</configuration>
</plugin>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<executions>
<execution>
<id>make-my-assembly</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
<configuration>
<archive>
<manifest>
<mainClass>com.example.FooBar</mainClass>
</manifest>
</archive>
<appendAssemblyId>true</appendAssemblyId>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
</plugin>
</plugins>
</build>
<configuration>
<archiveDirectory>${project.build.directory}</archiveDirectory>
<includes>
<include>*.jar</include>
</includes>
<keystore>${project.basedir}/keystore/mykeystore</keystore>
<alias>keyalias</alias>
<storepass>storepass</storepass>
<keypass>keypass</keypass>
</configuration>
Refer this http://maven.apache.org/plugins/maven-jarsigner-plugin/sign-mojo.html
You should try to put the maven-assembly-plugin into the prepare-package phase instead of the package phase:
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<executions>
<execution>
<id>make-my-assembly</id>
<phase>prepare-package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
...
</plugin>
Change order of plugins in your POM. Order is relevant in Maven. Run mvn install again and review output log. You should be able to see the order of actions from the log.
I use maven assembly plugin to collect all dependencies into one jar file. How can I tell maven not to repack dependencies and include them as jar files into resulting jar?
Currently I use following plugin configuration.
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
<configuration>
<archive>
<manifest>
<mainClass>package.Program</mainClass>
</manifest>
</archive>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
</plugin>
wanted structure of jar file:
my-jar-with-dependencies.jar
|-dependency1.jar
|-|-class1.class
|-dependency2.jar
|-|-class2.class
|-...........
and not
my-jar-with-dependencies.jar
|-class1.class
|-class2.class
|-.............
If I understand the question correctly you want to specify when the assembly plugn should be run or not. I this is the case you should consider creating a build profile and add the assembly plugin configuration to the new profile.
In pom.xml add:
<project>
...
<profiles>
<profile>
<id>myprofile</id>
<build>
<plugins>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
<configuration>
<archive>
<manifest>
<mainClass>package.Program</mainClass>
</manifest>
</archive>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
</plugin>
</plugins>
</build>
</profile>
</profiles>
...
</project>
When you want maven to run the assembly plugin you can then use the -P switch to the 'mvn' script like this:
mvn -Pmyprofile clean package
I'm trying to create different MANIFEST.MF files for the jar-packaged artifacts and the test-jar-packaged. The maven-jar-plugin being used to add additional stuff into the MANIFEST.MF - that works perfectly so far. But if I'd like to chose different template file for the MANIFEST.MF for the testproject, Maven only uses the second referenced template for both artifacts...
How can I get Maven to use the PROD-MANIFEST.MF-template for the normal jar-packaging and the TEST-MANIFEST.MF-template for test-jar-packaging?
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<executions>
<execution>
<id>test-manifest-mf</id>
<phase>package</phase>
<goals>
<goal>test-jar</goal>
</goals>
</execution>
</executions>
<configuration>
<archive>
<manifest>
<addClasspath>true</addClasspath>
</manifest>
<manifestFile>foo/TEST-MANIFEST.MF</manifestFile>
</archive>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<executions>
<execution>
<id>default-manifest-mf</id>
<phase>package</phase>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
<configuration>
<archive>
<manifest>
<addClasspath>true</addClasspath>
</manifest>
<manifestFile>foo/PROD-MANIFEST.MF</manifestFile>
</archive>
</configuration>
</plugin>
Wrap each plugin configuration you have provided in a profile.
<profiles>
<profile>
<id>PROD</id>
<build>
<plugins>
// your PROD plugin configuration
</plugins>
</build>
</profile>
<profile>
<id>TEST</id>
<build>
<plugins>
// your TEST plugin configuration
</plugins>
</build>
</profile>
</profiles>
Then you invoke Maven with a profile
mvn package -P PROD
Hope that helps.
Try this:
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<executions>
<execution>
<id>test-manifest-mf</id>
<phase>package</phase>
<goals>
<goal>test-jar</goal>
</goals>
<configuration>
<archive>
<manifest>
<addClasspath>true</addClasspath>
</manifest>
<manifestFile>foo/TEST-MANIFEST.MF</manifestFile>
</archive>
</configuration>
</execution>
<execution>
<id>default-manifest-mf</id>
<phase>package</phase>
<goals>
<goal>jar</goal>
</goals>
<configuration>
<archive>
<manifest>
<addClasspath>true</addClasspath>
</manifest>
<manifestFile>foo/PROD-MANIFEST.MF</manifestFile>
</archive>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
This configuration is performing 2 different executions of the same plugin, each of which has its own archive configuration.
If there is a parent pom somewhere in your hierarchy that has the archive configured outside of an execution, like this:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<configuration>
<archive>
... other archive config ...
</archive>
</configuration>
</plugin>
then that configuration will be merged with what you have by default. If you don't want that to happen, add the combine.self attribute to the <archive> element like so:
<archive combine.self="override">
as described in the plugins section of the POM reference.