Eclipse built-in jar export option vs Maven assembly plugin - java

I use IntelliJ IDEA to generate a jar file with maven-assembly-plugin.
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<version>3.1.0</version>
<executions>
<execution>
<id>make-assembly</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
<configuration>
<archive>
<manifest>
<mainClass>test.LeanFTest</mainClass>
</manifest>
</archive>
<finalName>${project.artifactId}-fatjar-${project.version}</finalName>
<appendAssemblyId>false</appendAssemblyId>
</configuration>
</plugin>
It didn't work, it asks continuously for dependencies during execution. I was unable to use jar file, so I imported the project to Eclipse and used the built-in jar export option. This jar is working fine. I couldn't find what the difference is between these jar files.

The reason is probably that Eclipse is generating a "Class-Path:" entry in the manifest file.
Try to update the assembly conf in your .pom file by adding something like (by heart, not checked):
<addClasspath>true</addClasspath>

By default the maven-assembly-plugin will not bundle all the dependencies required for your own jar to run standalone.
So you will need to add this below under the plugin configuration:
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
As a result, the plugin tag becomes:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<version>3.1.0</version>
<executions>
<execution>
<id>make-assembly</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
<configuration>
<archive>
<manifest>
<mainClass>test.LeanFTest</mainClass>
</manifest>
</archive>
<finalName>${project.artifactId}-fatjar-${project.version}</finalName>
<appendAssemblyId>false</appendAssemblyId>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef> <!-- the secret -->
</descriptorRefs>
</configuration>
</plugin>
You can run:
java -jar path/to/LeanFTest.jar
To directly run the program.

Related

Maven - error cannot find or load main class

I tried to build this example : https://github.com/oltzen/JavaCppExample with Maven (mvn clean install) on Linux.
After the successful build, when I run : java de.oltzen.javacppexample.Abc : it says 'could not load or find the main class'
The video tutorial (https://www.youtube.com/watch?v=LZrrqZLhtmw) uses Eclipse and it runs the program with Run as .. Java Application
Is the POM file missing something ?
I tried to add this plugin in POM but it did not work:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<configuration>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<classpathPrefix>lib/</classpathPrefix>
<mainClass>de.oltzen.javacppexample.Abc</mainClass>
</manifest>
</archive>
</configuration>
</plugin>
I am executing from JavaCppExample/target/classes/ :-
The /classes folder contains package folders : de/oltzen/javacppexample/
The last folder contains the class file Abc.class
So I run the command :
java de.oltzen.javacppexample.Abc
The /target folder contains :
1) classes [folder containing the package]
2) JavaCppExample.jar
3) maven-archiver
4) maven-status
Please help
I added the following plugins for maven copy dependencies and executed java -jar javaCppExample.jar [from /target folder]and it worked. Thanks everyone !
[Simply build using mvn clean install]
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<encoding>UTF-8</encoding>
<target>1.8</target>
<source>1.8</source>
</configuration>
</plugin>
<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}/lib/</outputDirectory>
<overWriteReleases>false</overWriteReleases>
<overWriteSnapshots>false</overWriteSnapshots>
<overWriteIfNewer>true</overWriteIfNewer>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<!-- Build an executable JAR -->
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>3.0.2</version>
<configuration>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<classpathPrefix>lib/</classpathPrefix>
<mainClass>de.oltzen.javacppexample.Abc</mainClass>
</manifest>
</archive>
</configuration>
</plugin>
If you are only looking to run your prgramm via maven then use exec-maven-plugin.
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>1.6.0</version>
<executions>
<execution>
<goals>
<goal>java</goal>
</goals>
</execution>
</executions>
<configuration>
<mainClass>de.oltzen.javacppexample.Abc</mainClass>
</configuration>
</plugin>
Explore more here => https://www.mojohaus.org/exec-maven-plugin/index.html
If you want to build & run as jar then use assembly plugin
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<version>3.1.0</version>
<configuration>
<appendAssemblyId>true</appendAssemblyId>
<descriptors>
<descriptor>${project.basedir}/assembly/assembly.xml</descriptor>
</descriptors>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
<archive>
<manifest>
<mainClass>de.oltzen.javacppexample.Abc</mainClass>
</manifest>
</archive>
</configuration>
<executions>
<execution>
<id>make-assembly</id>
<phase>install</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
Explore more about Maven assembly plugin to customize to your needs.

Maven-assembly: how package only imported/used dependencies for each execution

I have a Maven project where I need to package different Java programs as jars, each one with its own dependecies.
To achieve this I am currently using maven-assembly-plugin with different executions, one for each java program I need to package (e.g. Program1.java, Program2.java, Program3.java):
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<executions>
<execution>
<id>assembly1</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
<configuration>
<archive>
<manifest>
<mainClass>my.package1.Program1</mainClass>
</manifest>
</archive>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
<finalName>Program1</finalName>
<appendAssemblyId>false</appendAssemblyId>
</configuration>
</execution>
<execution>
<id>assembly2</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
<configuration>
<archive>
<manifest>
<mainClass>my.package2.Program2</mainClass>
</manifest>
</archive>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
<finalName>Program2</finalName>
<appendAssemblyId>false</appendAssemblyId>
</configuration>
</execution>
<execution>
<id>assembly3</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
<configuration>
<archive>
<manifest>
<mainClass>my.package3.Program3</mainClass>
</manifest>
</archive>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
<finalName>Program3</finalName>
<appendAssemblyId>false</appendAssemblyId>
</configuration>
</execution>
</executions>
</plugin>
Each one of these classes (Program1, Program2, Program3) requires different libraries as depedencies, thus I expected in output to get 3 jars with different size, but I got 3 files of the same size (Program1.jar, Program2.jar, Program3.jar).
It's like Maven is packaging all the dependencies defined inside the tag dependencies, regardless if they are used or not.
How can I tell maven to package, for each execution inside the assembly-plugin, only the dependencies effectively imported and used by the specified Class?
The default behaviour of assembly plugin is to include all dependencies of your current maven module. You could change that by explictly excluding the unwanted dependencies.
However, if you have three different programs that even do not have the same dependencies, it might be better to split up your project into three different (sub-)modules, maybe with a common parent pom. More details can be found here. After splitting up the project, each submodule can run its own assembly plugin that only packs the dependencies that are declared for each submodule.
If you decide to split up your project, you can clean up the required dependencies for each sub-module with the help of the dependency plugin, goal dependency:analyze.

How to build a jar from multimudule project?

I have two Maven modules in on root module.
root
- module-core
- module-run
module-run has module-core as a dependency.
How can I build a jar file based on module-run with dependencies and manifest?
UPD
I use
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
<configuration>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
<archive>
<manifest>
<mainClass>com.test.app.main.App</mainClass>
</manifest>
</archive>
</configuration>
</plugin>
Use the maven-assembly-plugin. It will by default bundle all of the modules dependencies into the JAR. If you need to restrict it to just module 2, that's trickier but doable... To bundle all dependencies, just add this plugin configuration:
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<configuration>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
</plugin>

How to format the name of a JAR File, which will be created with Maven3?

I have a question concerning Maven3. I want to create a JAR File with the name myJarFile_1.0.0-SNAPSHOT_200140723.jar.
But Maven only create the follwoing name (I used the command "mvn clean install"):
myJarFile_1.0.0-SNAPSHOT_200140723-jar-with-dependencies.jar
Here is my finalName declaration:
<finalName>${project.artifactId}_${project.version}_${timestamp}</finalName>
Here is the configuration of my Maven-asembly-plugin:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<configuration>
<descriptorRefs>
<descriptorRef>
jar-with-dependencies
</descriptorRef>
</descriptorRefs>
<archive>
<addMavenDescriptor>false</addMavenDescriptor>
<manifestEntries>
<source-jdk>1.6</source-jdk>
<target-jdk>1.6</target-jdk>
</manifestEntries>
<manifest>
<addClasspath>true</addClasspath>
<classpathPrefix>lib/</classpathPrefix>
<mainClass>myMainClass</mainClass>
</manifest>
</archive>
</configuration>
<executions>
<execution>
<id>assembly-jar-Id</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
How can i solve this problem?
I can only work with the JAR File, which includes the text "jar-with dependencies". But i must rename this file, because of my bash sell script, which execute this File. The second JAR file, which was created by maven, can not be used, since i get this error message: no main manifest attribute, in myJarFile.jar
Many thanks !

Creating Two Executable Jars Using maven-assembly-plugin

I have a Maven project and I want to create two executable jar files from it. One will be used interactively by users and a second will be run as a scheduled job that reads the log files produced by the former. In the end, I would expect the two jar files to be identical except for the Main-Class attribute in the MANIFEST.MF file.
I am using maven-antrun-plugin to create an executable jar and this seemed to be working fine until I tried to create a second jar file by introducing Maven profiles. The relevant section of my POM file looks like this:
<profiles>
<profile>
<id>publisher</id>
<build>
<finalName>${project.artifactId}</finalName>
<plugins>
...
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.4</version>
<configuration>
<appendAssemblyId>false</appendAssemblyId>
<finalName>${project.artifactId}</finalName>
<archive>
<manifest>
<mainClass>fully.qualified.path.Publisher</mainClass>
</manifest>
</archive>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
<profile>
<id>logReader</id>
<build>
<finalName>${project.artifactId}</finalName>
<plugins>
...
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.4</version>
<configuration>
<appendAssemblyId>false</appendAssemblyId>
<finalName>${project.artifactId}-logReader</finalName>
<archive>
<manifest>
<mainClass>fully.qualified.path.LogReader</mainClass>
</manifest>
</archive>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
</profiles>
Really, the only difference between the two is the "finalName" and "mainClass" elements as defined within the plugin.
When I try to execute mvn:package on both profiles (I'm using IntelliJ IDEA, by the way), I get two .jar files, but one is correct and the other is incorrect. The "correct" one contains all the dependencies and a valid MANIFEST.MF file. The "incorrect" one contains no dependencies and the MANIFEST.MF file lacks the "Main-Class" property that I need in order for it to be executable.
I have found that if I ever run just one profile or the other, that it works fine but, if I try to execute both profiles at once, it fails. I also get the following notes in my log, but I must admit that I don't completely understand what they are saying:
[INFO] Building jar: .../target/publisher.jar
...
[INFO] Building jar: .../target/publisher-logReader.jar
[WARNING] Configuration options: 'appendAssemblyId' is set to false, and 'classifier' is missing.
Instead of attaching the assembly file: .../target/publisher-logReader.jar, it will become the file for main project artifact.
NOTE: If multiple descriptors or descriptor-formats are provided for this project, the value of this file will be non-deterministic!
[WARNING] Replacing pre-existing project main-artifact file: .../target/publisher.jar with assembly file: .../target/publisher-logReader.jar
Any thoughts about this? Is it possible to produce two jar files with a single mvn:package in this way, or am I barking up the wrong tree?
Thanks!
So as soon as I posted this, I found this thread:
Create multiple runnable Jars (with depencies included) from a single Maven project
This uses a different approach in that it doesn't use two profiles, it uses two executions, as such:
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.4</version>
<executions>
<execution>
<id>build-publisher</id>
<configuration>
<appendAssemblyId>false</appendAssemblyId>
<archive>
<manifest>
<mainClass>fully.qualified.path.Publisher</mainClass>
</manifest>
</archive>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
<finalName>${project.artifactId}</finalName>
</configuration>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
<execution>
<id>build-logReader</id>
<configuration>
<appendAssemblyId>false</appendAssemblyId>
<archive>
<manifest>
<mainClass>fully.qualified.path.LogReader</mainClass>
</manifest>
</archive>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
<finalName>${project.artifactId}-logReader</finalName>
</configuration>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
This seems to be working. The moral of the story seems to be that I don't completely understand profiles or when they should be used.

Categories