getResource() not locating the resource on classpath - java

I have set up basic maven project in java SE, with a resource:
main
-java
-resources
-config -> database.properties
now since I don't want this resource in the final jar, I define:
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>2.4</version>
<configuration>
<excludes>
<exclude>config/database.properties</exclude>
</excludes>
</configuration>
<executions>
<execution>
<id>make-jar-ultimateParser</id>
<phase>package</phase>
<goals>
<goal>jar</goal>
</goals>
<configuration>
<outputDirectory>${project.build.directory}/dist</outputDirectory>
<finalName>testApp</finalName>
<archive>
<compress>false</compress>
<!-- Manifest - MainClass & ClassPath -->
<manifest>
<mainClass>aa.bb.Class</mainClass>
<addClasspath>true</addClasspath>
<classpathPrefix>lib/</classpathPrefix>
</manifest>
<manifestEntries>
<Class-Path>config/database.properties</Class-Path>
</manifestEntries>
</archive>
</configuration>
</execution>
</executions>
</plugin>
<!-- Copy configuration files -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId>
<version>2.6</version>
<executions>
<execution>
<id>copy-resources</id>
<phase>validate</phase>
<goals>
<goal>copy-resources</goal>
</goals>
<configuration>
<outputDirectory>${project.build.directory}/dist/config</outputDirectory>
<resources>
<resource>
<directory>src/main/resources/config</directory>
</resource>
</resources>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.0</version>
<configuration>
<source>1.6</source>
<target>1.6</target>
</configuration>
</plugin>
</plugins>
</build>
So the resource is on classpath and the directory with the resource is copied to the final jar.
My manifest looks like this: "Class-Path: config/database.properties"
But I'm not able to read it:
String db = "/config/database.properties";
properties = new Properties();
properties.load(getClass().getResourceAsStream(db));
I tried absolute/relative paths, getClass()/ClassLoader. Nothing. It works flawlessly in NetBeans, but that's about it.

You're misunderstanding what the Maven Resources plugin does. It simply copies resources (perhaps with transformation) into the build output directory. Where they're then included into the build artifact (JAR, WAR, whatever).
To make this work (referencing the JAR's directory using the Class-Path manifest entry), you need to distribute the config file separately. Or reference it using a File, and not bothering with the classpath.
A better approach is to distribute your application as an assembly, which contains the core app, any dependencies, and the configuration file. This would typically be packaged as a ZIPfile, and the user would unzip it to install.

I dont understand why you are excluding it. Maven uses its own resources dir.
Project
|-- pom.xml
-- src
-- main
`-- resources
wich it makes easier the life the programmer. Theres no need to get classpatch or other when you using this way.

Related

Getting "java.lang.NoClassDefFoundError: org/apache/kafka/clients/consumer/KafkaConsumer" when I try to run the Java -jar command after maven build [duplicate]

Is there a way to force maven(2.0.9) to include all the dependencies in a single jar file?
I have a project the builds into a single jar file. I want the classes from dependencies to be copied into the jar as well.
Update: I know that I cant just include a jar file in a jar file. I'm searching for a way to unpack the jars that are specified as dependencies, and package the class files into my jar.
You can do this using the maven-assembly plugin with the "jar-with-dependencies" descriptor. Here's the relevant chunk from one of our pom.xml's that does this:
<build>
<plugins>
<!-- any other plugins -->
<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>
</configuration>
</plugin>
</plugins>
</build>
With Maven 2, the right way to do this is to use the Maven2 Assembly Plugin which has a pre-defined descriptor file for this purpose and that you could just use on the command line:
mvn assembly:assembly -DdescriptorId=jar-with-dependencies
If you want to make this jar executable, just add the main class to be run to the plugin configuration:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<configuration>
<archive>
<manifest>
<mainClass>my.package.to.my.MainClass</mainClass>
</manifest>
</archive>
</configuration>
</plugin>
If you want to create that assembly as part of the normal build process, you should bind the single or directory-single goal (the assembly goal should ONLY be run from the command line) to a lifecycle phase (package makes sense), something like this:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<executions>
<execution>
<id>create-my-bundle</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
<configuration>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
...
</configuration>
</execution>
</executions>
</plugin>
Adapt the configuration element to suit your needs (for example with the manifest stuff as spoken).
If you want to do an executable jar file, them need set the main class too. So the full configuration should be.
<plugins>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
<configuration>
<!-- ... -->
<archive>
<manifest>
<mainClass>fully.qualified.MainClass</mainClass>
</manifest>
</archive>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
</plugin>
</plugins>
Method 1: Copy the dependencies' JAR files into target/lib and then add them to the JAR's classpath in MANIFEST:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<configuration>
<outputDirectory>${project.build.directory}/lib</outputDirectory>
<excludeTransitive>false</excludeTransitive>
<stripVersion>false</stripVersion>
</configuration>
<executions>
<execution>
<id>copy-dependencies</id>
<phase>package</phase>
<goals>
<goal>copy-dependencies</goal>
</goals>
</execution>
</executions>
</plugin>
<!-- Add LIB folder to classPath -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>2.4</version>
<configuration>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<classpathPrefix>lib/</classpathPrefix>
</manifest>
</archive>
</configuration>
</plugin>
Method 2: Unpack all dependencies and repack their classes and resources into one flat JAR. Note: The overlapping resources will be randomly lost!
<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>
</configuration>
</plugin>
There's the shade maven plugin. It can be used to package and rename dependencies (to omit dependency problems on the classpath).
You can use the newly created jar using a <classifier> tag.
<dependencies>
<dependency>
<groupId>your.group.id</groupId>
<artifactId>your.artifact.id</artifactId>
<version>1.0</version>
<type>jar</type>
<classifier>jar-with-dependencies</classifier>
</dependency>
</dependencies>
If you (like me) dont particularly like the jar-with-dependencies approach described above,
the maven-solution I prefer is to simply build a WAR-project,
even if it is only a stand-alone java application you are building:
Make a normal maven jar-project, that will build your jar-file (without the dependencies).
Also, setup a maven war-project (with only an empty src/main/webapp/WEB-INF/web.xml file, which will avoid a warning/error in the maven-build), that only has your jar-project as a dependency, and make your jar-project a <module> under your war-project. (This war-project is only a simple trick to wrap all your jar-file dependencies into a zip-file.)
Build the war-project to produce the war-file.
In the deployment-step, simply rename your .war-file to *.zip and unzip it.
You should now have a lib-directory (which you can move where you want it) with your jar and all the dependencies you need to run your application:
java -cp 'path/lib/*' MainClass
(The wildcard in classpath works in Java-6 or higher)
I think this is both simpler to setup in maven (no need to mess around with the assembly plugin) and also gives you a clearer view of the application-structure (you will see the version-numbers of all dependent jars in plain view, and avoid clogging everything into a single jar-file).
http://fiji.sc/Uber-JAR provides an excellent explanation of the alternatives:
There are three common methods for constructing an uber-JAR:
Unshaded. Unpack all JAR files, then repack them into a single JAR.
Pro: Works with Java's default class loader.
Con: Files present in multiple JAR files with the same path (e.g.,
META-INF/services/javax.script.ScriptEngineFactory) will overwrite one
another, resulting in faulty behavior.
Tools: Maven Assembly
Plugin, Classworlds Uberjar
Shaded. Same as unshaded, but rename (i.e., "shade") all packages of all dependencies.
Pro: Works with Java's default class loader.
Avoids some (not all) dependency version clashes.
Con: Files
present in multiple JAR files with the same path (e.g.,
META-INF/services/javax.script.ScriptEngineFactory) will overwrite one
another, resulting in faulty behavior.
Tools: Maven Shade Plugin
JAR of JARs. The final JAR file contains the other JAR files embedded within.
Pro: Avoids dependency version clashes. All
resource files are preserved.
Con: Needs to bundle a special
"bootstrap" classloader to enable Java to load classes from the
wrapped JAR files. Debugging class loader issues becomes more complex.
Tools: Eclipse JAR File Exporter, One-JAR.
My definitive solution on Eclipse Luna and m2eclipse:
Custom Classloader (download and add to your project, 5 classes only)
:http://git.eclipse.org/c/jdt/eclipse.jdt.ui.git/plain/org.eclipse.jdt.ui/jar%20in%20jar%20loader/org/eclipse/jdt/internal/jarinjarloader/;
this classloader is very best of one-jar classloader and very fast;
<project.mainClass>org.eclipse.jdt.internal.jarinjarloader.JarRsrcLoader</project.mainClass>
<project.realMainClass>my.Class</project.realMainClass>
Edit in JIJConstants "Rsrc-Class-Path" to "Class-Path"
mvn clean dependency:copy-dependencies package
is created a jar with dependencies in lib folder with a thin classloader
<build>
<resources>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.java</include>
<include>**/*.properties</include>
</includes>
</resource>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
<includes>
<include>**/*</include>
</includes>
<targetPath>META-INF/</targetPath>
</resource>
<resource>
<directory>${project.build.directory}/dependency/</directory>
<includes>
<include>*.jar</include>
</includes>
<targetPath>lib/</targetPath>
</resource>
</resources>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<configuration>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<mainClass>${project.mainClass}</mainClass>
<classpathPrefix>lib/</classpathPrefix>
</manifest>
<manifestEntries>
<Rsrc-Main-Class>${project.realMainClass} </Rsrc-Main-Class>
<Class-Path>./</Class-Path>
</manifestEntries>
</archive>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<id>copy-dependencies</id>
<phase>package</phase>
<goals>
<goal>copy-dependencies</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</pluginManagement>
</build>
Putting Maven aside, you can put JAR libraries inside the Main Jar but you will need to use your own classloader.
Check this project: One-JAR link text
I was trying to do sth similar, but I didn't want all jars to be included. I wanted to include some specific directories from the given dependency. In addition classifier tag was already occupied, so I couldn't do:
<dependencies>
<dependency>
<groupId>your.group.id</groupId>
<artifactId>your.artifact.id</artifactId>
<version>1.0</version>
<type>jar</type>
<classifier>jar-with-dependencies</classifier>
</dependency>
</dependencies>
I used maven-dependency-plugin and unpack goal
And unpacked what I wanted to the ${project.build.directory}/classes, otherwise it will be omitted
Because it was in the classes directory, maven finally placed it in the jar
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<id>unpack</id>
<phase>prepare-package</phase>
<goals>
<goal>unpack</goal>
</goals>
<configuration>
<artifactItems>
<artifactItem>
<groupId>my.group</groupId>
<artifactId>my.artifact</artifactId>
<classifier>occupied</classifier>
<version>1.0</version>
<type>jar</type>
</artifactItem>
</artifactItems>
<outputDirectory>${project.build.directory}/classes</outputDirectory>
<includes>aaa/**, bbb/**, ccc/**</includes>
</configuration>
</execution>
</executions>
</plugin>
This post may be a bit old, but I also had the same problem recently. The first solution proposed by John Stauffer is a good one, but I had some problems as I am working this spring. The spring's dependency-jars I use have some property files and xml-schemas declaration which share the same paths and names. Although these jars come from the same versions, the jar-with-dependencies maven-goal was overwriting theses file with the last file found.
In the end, the application was not able to start as the spring jars could not find the correct properties files. In this case the solution propose by Rop have solved my problem.
Also since then, the spring-boot project now exist. It has a very cool way to manage this problem by providing a maven goal which overload the package goal and provide its own class loader. See spring-boots Reference Guide
Have a look at this answer:
I am creating an installer that runs as a Java JAR file and it needs to unpack WAR and JAR files into appropriate places in the installation directory. The dependency plugin can be used in the package phase with the copy goal and it will download any file in the Maven repository (including WAR files) and write them where ever you need them. I changed the output directory to ${project.build.directory}/classes and then end result is that the normal JAR task includes my files just fine. I can then extract them and write them into the installation directory.
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<id>getWar</id>
<phase>package</phase>
<goals>
<goal>copy</goal>
</goals>
<configuration>
<artifactItems>
<artifactItem>
<groupId>the.group.I.use</groupId>
<artifactId>MyServerServer</artifactId>
<version>${env.JAVA_SERVER_REL_VER}</version>
<type>war</type>
<destFileName>myWar.war</destFileName>
</artifactItem>
</artifactItems>
<outputDirectory>${project.build.directory}/classes</outputDirectory>
</configuration>
</execution>
</executions>
Thanks
I have added below snippet in POM.xml file and Mp problem resolved and
create fat jar file that include all dependent jars.
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
<configuration>
<descriptorRefs>
<descriptorRef>dependencies</descriptorRef>
</descriptorRefs>
</configuration>
</plugin>
</plugins>
I found this to be the clearest answer; other answers here were missing things that weren't obvious to me such as mvn clean package command for example, and adding the plugin separately as a dependancy also. All of which are probably obvious to more habitual maven users.
https://howtodoinjava.com/maven/executable-jar-with-dependencies/
To make it more simple, You can use the below plugin.
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
<configuration>
<classifier>spring-boot</classifier>
<mainClass>
com.nirav.certificate.CertificateUtility
</mainClass>
</configuration>
</execution>
</executions>
</plugin>

Maven deploy:deploy-file publishes all files instead of one

I am building my Java application using Maven and the Maven Assembly Plugin to create an executable jar.
As a result, the target folder contains multiple jars and other files. However, I only want to deploy the executable jar file built via the Assembly Plugin.
To do this, I have tried to use mvn deploy:deploy-file and provided it with the following properties:
file
repositoryId
url
artifactId
groupId
version
However, when I execute the command, Maven deploys all files instead of only the executable jar.
I also tried disabling the default build step:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-deploy-plugin</artifactId>
<executions>
<!-- disable standard deploy -->
<execution>
<id>default-deploy</id>
<phase>none</phase>
</execution>
</executions>
</plugin>
The build part of my pom.xml looks like this:
<build>
<!--suppress UnresolvedMavenProperty -->
<finalName>${project.artifactId}-${BUILD_DATE}</finalName>
<sourceDirectory>src</sourceDirectory>
<resources>
<resource>
<directory>src</directory>
<filtering>true</filtering>
<excludes>
<exclude>**/*.java</exclude>
</excludes>
</resource>
</resources>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<configuration>
<archive>
<manifest>
<mainClass>main.PAtrackMain</mainClass>
<addDefaultImplementationEntries>true</addDefaultImplementationEntries>
<addDefaultSpecificationEntries>true</addDefaultSpecificationEntries>
</manifest>
<manifestEntries>
<!--suppress UnresolvedMavenProperty -->
<Implementation-Build>${BUILD_DATE}</Implementation-Build>
</manifestEntries>
</archive>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
<appendAssemblyId>true</appendAssemblyId>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-deploy-plugin</artifactId>
<executions>
<!-- disable standard deploy -->
<execution>
<id>default-deploy</id>
<phase>none</phase>
</execution>
</executions>
</plugin>
</plugins>
</build>
How can I deploy only the executable jar without the other files?
That is much simpler than you might think.
There are two kinds of artifacts, produced by maven project:
main: ${artifactId}-${version}.${packaging} - this one you would like to not publish
supplemental: everything else produced by plugins (javadoc, sources, assembly, etc)
If project/module packaging is pom, that means following:
project/module may not have main artifact, only supplemental ones
some plugins are not enabled by default (https://maven.apache.org/ref/3.8.6/maven-core/default-bindings.html - compare default bindings for pom and jar packaging)
Thus, all what you need is:
switch module packaging from jar to pom
enable missing plugins: maven-compiler-plugin, maven-resources-plugin, maven-jar-plugin, etc
extra configuration of maven-deploy-plugin is not required

Building an executable jar with maven depencies and external jars

I have an application where Im using maven dependecies and Im also using an external jar of a project which is located in my computer, the project is added to the application manually. The problem is whenever I export the project with maven, It only exports all maven dependencies, not the externatl jar that I have included manually. Is there anyway that I can export it?
Here is my pom.xml:
<build>
<plugins>
<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}/libs
</outputDirectory>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<configuration>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<classpathPrefix>libs/</classpathPrefix>
<mainClass>
com.cristianruizblog.loginSecurity.LoginSecurityTutorialApplication
</mainClass>
</manifest>
</archive>
</configuration>
</plugin>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
Thanks for reading. If anyone can help I would be so happy!
As stated by #M. Deunum, try to get your external jar into a Maven repository to avoid enable any machine to build your jar. If this is no option, you can use the Maven system dependency scope to include the jar. Note that this is only a temporary solution as this scope has been marked as depricated.

Exclude file from jar as built by jar-with-dependencies

My pom.xml contains the following to create a jar of my project with all dependencies.
Now I have a properties file in src/main/resources which is necessary to run the application (and I want to use it from starting from the IDE), but I do not want to ship it in the created jar file, as the settings are maintained separately.
Question: How I can I get a file with all dependencies, but exclude those properties files?
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<executions>
<execution>
<id>make-jar</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
<configuration>
<archive>
<manifest>
<mainClass>x.Main</mainClass>
</manifest>
</archive>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
</execution>
</executions>
</plugin>
As specified by the maven-assembly-plugin documentation:
If your project wants to package your artifact in an uber-jar, the assembly plugin provides only basic support. For more control, use the Maven Shade Plugin.
Using the maven-shade-plugin you can have a fat jar (like using the assembly plugin) and solve similar issues of excluding files via configuration (no need of external assembly descriptor file).
In your case, to exclude resources from assembled jars, you can use shade filters.
A simple configuration would look like:
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>2.4.3</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<filters>
<filter>
<artifact>*:*</artifact>
<excludes>
<exclude>**/*file_pattern*</exclude>
</excludes>
</filter>
</filters>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
In the example above, you can customize file_pattern or narrow down your filter in the artifact element using your my.groupId:my.artifactId.
Note: the approach above is recommended when excluding files from external libraries, however you can still use the maven-assembly-plugin for excluding files from your own project via a custom assembly descriptor file.
If you want to stick with maven-assembly-plugin you can use an assembly descriptor file where you configure your filters, like in this section:
<fileSets>
<fileSet>
<directory>${basedir}</directory>
<includes>
<include>*.txt</include>
</includes>
<excludes>
<exclude>*.properties/exclude>
</excludes>
</fileSet>
And in your maven configuration, pom.xml you specify the assemblu descriptor file, in the descriptors tag (distribution.xml is a file containing the section from above)
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.6</version>
<configuration>
<filters>
<filter>src/assembly/filter.properties</filter>
</filters>
<descriptors>
<descriptor>src/assembly/distribution.xml</descriptor>
</descriptors>
</configuration>
</plugin>
Also check this link maven-assembly
I faced similar problem (I had a checkstyle-config.xml that, should not be included in the final assembly). A solution below worked for me:
Adding the resources section made my project-jar-with-dependancies.jar not containing checkstyle-config.xml file
Simplified pom.xml:
<?xml version="1.0" encoding="UTF-8"?>
<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/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>...</groupId>
<artifactId>...</artifactId>
<version>...</version>
<properties>
...
</properties>
<packaging>jar</packaging>
<build>
<resources>
<resource>
<directory>${project.basedir}/src/main/resources</directory>
<excludes>
<exclude>checkstyle-config.xml</exclude>
</excludes>
</resource>
</resources>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<version>3.3.0</version>
<configuration>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
<archive>
<manifest>
<mainClass>...</mainClass>
</manifest>
</archive>
</configuration>
<executions>
<execution>
<id>make-assembly</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
<dependencies>
...
</dependencies>
</project>

Including dependencies in a jar with Maven

Is there a way to force maven(2.0.9) to include all the dependencies in a single jar file?
I have a project the builds into a single jar file. I want the classes from dependencies to be copied into the jar as well.
Update: I know that I cant just include a jar file in a jar file. I'm searching for a way to unpack the jars that are specified as dependencies, and package the class files into my jar.
You can do this using the maven-assembly plugin with the "jar-with-dependencies" descriptor. Here's the relevant chunk from one of our pom.xml's that does this:
<build>
<plugins>
<!-- any other plugins -->
<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>
</configuration>
</plugin>
</plugins>
</build>
With Maven 2, the right way to do this is to use the Maven2 Assembly Plugin which has a pre-defined descriptor file for this purpose and that you could just use on the command line:
mvn assembly:assembly -DdescriptorId=jar-with-dependencies
If you want to make this jar executable, just add the main class to be run to the plugin configuration:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<configuration>
<archive>
<manifest>
<mainClass>my.package.to.my.MainClass</mainClass>
</manifest>
</archive>
</configuration>
</plugin>
If you want to create that assembly as part of the normal build process, you should bind the single or directory-single goal (the assembly goal should ONLY be run from the command line) to a lifecycle phase (package makes sense), something like this:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<executions>
<execution>
<id>create-my-bundle</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
<configuration>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
...
</configuration>
</execution>
</executions>
</plugin>
Adapt the configuration element to suit your needs (for example with the manifest stuff as spoken).
If you want to do an executable jar file, them need set the main class too. So the full configuration should be.
<plugins>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
<configuration>
<!-- ... -->
<archive>
<manifest>
<mainClass>fully.qualified.MainClass</mainClass>
</manifest>
</archive>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
</plugin>
</plugins>
Method 1: Copy the dependencies' JAR files into target/lib and then add them to the JAR's classpath in MANIFEST:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<configuration>
<outputDirectory>${project.build.directory}/lib</outputDirectory>
<excludeTransitive>false</excludeTransitive>
<stripVersion>false</stripVersion>
</configuration>
<executions>
<execution>
<id>copy-dependencies</id>
<phase>package</phase>
<goals>
<goal>copy-dependencies</goal>
</goals>
</execution>
</executions>
</plugin>
<!-- Add LIB folder to classPath -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>2.4</version>
<configuration>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<classpathPrefix>lib/</classpathPrefix>
</manifest>
</archive>
</configuration>
</plugin>
Method 2: Unpack all dependencies and repack their classes and resources into one flat JAR. Note: The overlapping resources will be randomly lost!
<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>
</configuration>
</plugin>
There's the shade maven plugin. It can be used to package and rename dependencies (to omit dependency problems on the classpath).
You can use the newly created jar using a <classifier> tag.
<dependencies>
<dependency>
<groupId>your.group.id</groupId>
<artifactId>your.artifact.id</artifactId>
<version>1.0</version>
<type>jar</type>
<classifier>jar-with-dependencies</classifier>
</dependency>
</dependencies>
If you (like me) dont particularly like the jar-with-dependencies approach described above,
the maven-solution I prefer is to simply build a WAR-project,
even if it is only a stand-alone java application you are building:
Make a normal maven jar-project, that will build your jar-file (without the dependencies).
Also, setup a maven war-project (with only an empty src/main/webapp/WEB-INF/web.xml file, which will avoid a warning/error in the maven-build), that only has your jar-project as a dependency, and make your jar-project a <module> under your war-project. (This war-project is only a simple trick to wrap all your jar-file dependencies into a zip-file.)
Build the war-project to produce the war-file.
In the deployment-step, simply rename your .war-file to *.zip and unzip it.
You should now have a lib-directory (which you can move where you want it) with your jar and all the dependencies you need to run your application:
java -cp 'path/lib/*' MainClass
(The wildcard in classpath works in Java-6 or higher)
I think this is both simpler to setup in maven (no need to mess around with the assembly plugin) and also gives you a clearer view of the application-structure (you will see the version-numbers of all dependent jars in plain view, and avoid clogging everything into a single jar-file).
http://fiji.sc/Uber-JAR provides an excellent explanation of the alternatives:
There are three common methods for constructing an uber-JAR:
Unshaded. Unpack all JAR files, then repack them into a single JAR.
Pro: Works with Java's default class loader.
Con: Files present in multiple JAR files with the same path (e.g.,
META-INF/services/javax.script.ScriptEngineFactory) will overwrite one
another, resulting in faulty behavior.
Tools: Maven Assembly
Plugin, Classworlds Uberjar
Shaded. Same as unshaded, but rename (i.e., "shade") all packages of all dependencies.
Pro: Works with Java's default class loader.
Avoids some (not all) dependency version clashes.
Con: Files
present in multiple JAR files with the same path (e.g.,
META-INF/services/javax.script.ScriptEngineFactory) will overwrite one
another, resulting in faulty behavior.
Tools: Maven Shade Plugin
JAR of JARs. The final JAR file contains the other JAR files embedded within.
Pro: Avoids dependency version clashes. All
resource files are preserved.
Con: Needs to bundle a special
"bootstrap" classloader to enable Java to load classes from the
wrapped JAR files. Debugging class loader issues becomes more complex.
Tools: Eclipse JAR File Exporter, One-JAR.
My definitive solution on Eclipse Luna and m2eclipse:
Custom Classloader (download and add to your project, 5 classes only)
:http://git.eclipse.org/c/jdt/eclipse.jdt.ui.git/plain/org.eclipse.jdt.ui/jar%20in%20jar%20loader/org/eclipse/jdt/internal/jarinjarloader/;
this classloader is very best of one-jar classloader and very fast;
<project.mainClass>org.eclipse.jdt.internal.jarinjarloader.JarRsrcLoader</project.mainClass>
<project.realMainClass>my.Class</project.realMainClass>
Edit in JIJConstants "Rsrc-Class-Path" to "Class-Path"
mvn clean dependency:copy-dependencies package
is created a jar with dependencies in lib folder with a thin classloader
<build>
<resources>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.java</include>
<include>**/*.properties</include>
</includes>
</resource>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
<includes>
<include>**/*</include>
</includes>
<targetPath>META-INF/</targetPath>
</resource>
<resource>
<directory>${project.build.directory}/dependency/</directory>
<includes>
<include>*.jar</include>
</includes>
<targetPath>lib/</targetPath>
</resource>
</resources>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<configuration>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<mainClass>${project.mainClass}</mainClass>
<classpathPrefix>lib/</classpathPrefix>
</manifest>
<manifestEntries>
<Rsrc-Main-Class>${project.realMainClass} </Rsrc-Main-Class>
<Class-Path>./</Class-Path>
</manifestEntries>
</archive>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<id>copy-dependencies</id>
<phase>package</phase>
<goals>
<goal>copy-dependencies</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</pluginManagement>
</build>
Putting Maven aside, you can put JAR libraries inside the Main Jar but you will need to use your own classloader.
Check this project: One-JAR link text
I was trying to do sth similar, but I didn't want all jars to be included. I wanted to include some specific directories from the given dependency. In addition classifier tag was already occupied, so I couldn't do:
<dependencies>
<dependency>
<groupId>your.group.id</groupId>
<artifactId>your.artifact.id</artifactId>
<version>1.0</version>
<type>jar</type>
<classifier>jar-with-dependencies</classifier>
</dependency>
</dependencies>
I used maven-dependency-plugin and unpack goal
And unpacked what I wanted to the ${project.build.directory}/classes, otherwise it will be omitted
Because it was in the classes directory, maven finally placed it in the jar
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<id>unpack</id>
<phase>prepare-package</phase>
<goals>
<goal>unpack</goal>
</goals>
<configuration>
<artifactItems>
<artifactItem>
<groupId>my.group</groupId>
<artifactId>my.artifact</artifactId>
<classifier>occupied</classifier>
<version>1.0</version>
<type>jar</type>
</artifactItem>
</artifactItems>
<outputDirectory>${project.build.directory}/classes</outputDirectory>
<includes>aaa/**, bbb/**, ccc/**</includes>
</configuration>
</execution>
</executions>
</plugin>
This post may be a bit old, but I also had the same problem recently. The first solution proposed by John Stauffer is a good one, but I had some problems as I am working this spring. The spring's dependency-jars I use have some property files and xml-schemas declaration which share the same paths and names. Although these jars come from the same versions, the jar-with-dependencies maven-goal was overwriting theses file with the last file found.
In the end, the application was not able to start as the spring jars could not find the correct properties files. In this case the solution propose by Rop have solved my problem.
Also since then, the spring-boot project now exist. It has a very cool way to manage this problem by providing a maven goal which overload the package goal and provide its own class loader. See spring-boots Reference Guide
Have a look at this answer:
I am creating an installer that runs as a Java JAR file and it needs to unpack WAR and JAR files into appropriate places in the installation directory. The dependency plugin can be used in the package phase with the copy goal and it will download any file in the Maven repository (including WAR files) and write them where ever you need them. I changed the output directory to ${project.build.directory}/classes and then end result is that the normal JAR task includes my files just fine. I can then extract them and write them into the installation directory.
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<id>getWar</id>
<phase>package</phase>
<goals>
<goal>copy</goal>
</goals>
<configuration>
<artifactItems>
<artifactItem>
<groupId>the.group.I.use</groupId>
<artifactId>MyServerServer</artifactId>
<version>${env.JAVA_SERVER_REL_VER}</version>
<type>war</type>
<destFileName>myWar.war</destFileName>
</artifactItem>
</artifactItems>
<outputDirectory>${project.build.directory}/classes</outputDirectory>
</configuration>
</execution>
</executions>
Thanks
I have added below snippet in POM.xml file and Mp problem resolved and
create fat jar file that include all dependent jars.
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
<configuration>
<descriptorRefs>
<descriptorRef>dependencies</descriptorRef>
</descriptorRefs>
</configuration>
</plugin>
</plugins>
I found this to be the clearest answer; other answers here were missing things that weren't obvious to me such as mvn clean package command for example, and adding the plugin separately as a dependancy also. All of which are probably obvious to more habitual maven users.
https://howtodoinjava.com/maven/executable-jar-with-dependencies/
To make it more simple, You can use the below plugin.
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
<configuration>
<classifier>spring-boot</classifier>
<mainClass>
com.nirav.certificate.CertificateUtility
</mainClass>
</configuration>
</execution>
</executions>
</plugin>

Categories

Resources