Including dependencies in a jar with Maven
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>
How can I create an executable JAR with dependencies using Maven?
<build>
<plugins>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<configuration>
<archive>
<manifest>
<mainClass>fully.qualified.MainClass</mainClass>
</manifest>
</archive>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
</plugin>
</plugins>
</build>
and you run it with
mvn clean compile assembly:single
Compile goal should be added before assembly:single or otherwise the code on your own project is not included.
See more details in comments.
Commonly this goal is tied to a build phase to execute automatically. This ensures the JAR is built when executing mvn install
or performing a deployment/release.
<build>
<plugins>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<configuration>
<archive>
<manifest>
<mainClass>fully.qualified.MainClass</mainClass>
</manifest>
</archive>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
<executions>
<execution>
<id>make-assembly</id> <!-- this is used for inheritance merges -->
<phase>package</phase> <!-- bind to the packaging phase -->
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
How to add local jar files to a Maven project?
Install the JAR into your local Maven repository (typically .m2
in your home folder) as follows:
mvn install:install-file \
-Dfile=<path-to-file> \
-DgroupId=<group-id> \
-DartifactId=<artifact-id> \
-Dversion=<version> \
-Dpackaging=<packaging> \
-DgeneratePom=true
Where each refers to:
<path-to-file>
: the path to the file to load e.g → c:\kaptcha-2.3.jar
<group-id>
: the group that the file should be registered under e.g → com.google.code
<artifact-id>
: the artifact name for the file e.g → kaptcha
<version>
: the version of the file e.g → 2.3
<packaging>
: the packaging of the file e.g. → jar
Reference
- Maven FAQ: I have a jar that I want to put into my local repository. How can I copy it in?
- Maven Install Plugin Usage: The
install:install-file
goal
How to include maven dependencies in a jar file?
Take a look at this question: How can I create an executable JAR with dependencies using Maven?
I think that @Rocky Inde's answer is what you are looking for (using eclipse):
1) Just right-click on your project folder (in Eclipse) and select
Export2) Then select Java -> Runnable Jar
3) You will be asked to choose the location of the jar file
4) Finally, select the class that has the Main method that you want to
run and choose Package dependencies with the Jar file and click Finish
Maven not including dependencies in Jar file
You can verify yourself if the driver is included in the resulting artifact (supposing its name is assembly.jar):
jar tf target/assembly.jar | fgrep jdbc
It probably is, though.
I think the problem comes from the fact that the driver is automatically registered using the Service Provider Interface (SPI), by listing the classes in META-INF/services/java.sql.Driver
. However, because the assembly plugin packages the dependency jars inside the assembly jar instead of exploding them and creating an uber-jar (like the shade plugin can), the SPI files are not scanned. See this blog post for example.
I suggest you try the shade plugin instead, configured with a ServicesResourceTransformer
.
Update
If the SPI mechanism doesn't work in your context (jar loaded as a plugin by a container application), you can register the driver yourself if there's a place in the code you know will be called before the driver is used (some initialization service for the plugin, for example, maybe by implementing Plugin.onLoad()
?): just create a instance of the driver, it will register itself.
try {
new org.neo4j.jdbc.http.HttpDriver();
} catch (SQLException e) {
logger.error("Could not load HttpDriver for Neo4j", e);
}
How to bundle a JAR file with its dependencies using maven
Sounds like you need to use the "maven-assembly-plugin" with the "jar-with-dependencies" descriptor.
E.g. here is a full example pom file with a dependency on ByteBuddy:
<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/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>test.example</groupId>
<artifactId>packaging-example</artifactId>
<version>1.0-SNAPSHOT</version>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.4.1</version>
<configuration>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
<archive>
<manifest>
<mainClass>test.example.TestByteBuddy</mainClass>
</manifest>
</archive>
</configuration>
<executions>
<execution>
<id>make-assembly</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>net.bytebuddy</groupId>
<artifactId>byte-buddy</artifactId>
<version>1.12.6</version>
</dependency>
</dependencies>
</project>
And for the sake of completeness - here is the main class also :
package test.example;
import net.bytebuddy.ByteBuddy;
public class TestByteBuddy
{
public static void main(String... args) throws Exception
{
System.out.println("Hello Byte Buddy Class - " + ByteBuddy.class);
}
}
Building this will produce an additional file in the target directory - packaging-example-1.0-SNAPSHOT-jar-with-dependencies.jar
Then you should be able to run it simply with :
java -jar packaging-example-1.0-SNAPSHOT-jar-with-dependencies.jar
to give you the output:
Hello Byte Buddy Class - class net.bytebuddy.ByteBuddy
Generate jar file in Maven with dependencies and tests
My solution is to build an archive (zip or other formats) that contains your classes in a jar, the dependencies jars, a folder with runtime configuration files and scripts to launch the application. The scope is to have a run ready application just by unzipping the archive.
The built archive content is:
artifactId-version.zip:
<artifactId folder>
├─ config
| ├─ log4j2.xml
├─ lib
| ├─ <all dependencies jars>
├─ leanft.cmd
├─ leanft.sh
└─ artifactId-version.jar
You should tailor the solution based on what/if you need configuration files. You don't need the META-INF folders with MANIFEST.MF files because will be generated automatically by maven plugin.
Project structure
<maven_module_root>
├─ src
| ├─ main
| | ├─ assembly
| | | ├─ leanft-assembly.xml
| | ├─ java
| | | ├─ <your classes content>
| | ├─ resources
| | | ├─ log4j2.xml
| | | ├─ <your runtime configuration files>
| | ├─ scripts
| | | ├─ leanft.cmd
| | | ├─ leanft.sh
│ └───test
├─ pom.xml
The project structure is similar with your current structure with two additional folders:
- assembly: in this folder is the leanft-assembly.xml to customize the maven-assembly-plugin.
- scripts: in this folder are the launcher scripts for your application. This is necessary it if you need to have runtime configuration files available for edit. In my example, the resources/log4j2.xml will be in a config file so the user can edit this file without touching any jar/archive.
Assembly descriptor
The solution is based on maven assembly plugin with custom configuration. I recommend to get familiar with it, starting with descriptor assembly descriptor
Your leanft-assembly.xml could look like:
<assembly
xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.3"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.3 http://maven.apache.org/xsd/assembly-1.1.3.xsd">
<id>dist</id>
<formats>
<!-- <format>tar.gz</format> -->
<format>zip</format>
</formats>
<includeBaseDirectory>true</includeBaseDirectory>
<baseDirectory>${project.artifactId}</baseDirectory>
<fileSets>
<fileSet>
<directory>${project.build.directory}</directory>
<outputDirectory>/</outputDirectory>
<includes>
<include>${project.artifactId}-${project.version}.jar</include>
</includes>
</fileSet>
<fileSet>
<directory>${project.build.directory}/lib</directory>
<outputDirectory>/lib</outputDirectory>
<includes>
<include>*.*</include>
</includes>
</fileSet>
<fileSet>
<directory>${project.build.outputDirectory}</directory>
<outputDirectory>/config</outputDirectory>
<includes>
<include>log4j2.xml</include>
</includes>
</fileSet>
<fileSet>
<directory>${project.basedir}/src/main/scripts</directory>
<outputDirectory>/</outputDirectory>
<includes>
<include>leanft.*</include>
</includes>
</fileSet>
</fileSets>
</assembly>
Maven pom
Finally, the pom.xml make use of 3 plugins:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<version>3.0.1</version>
<executions>
<execution>
<id>copy-dependencies</id>
<phase>package</phase>
<goals>
<goal>copy-dependencies</goal>
</goals>
<configuration>
<outputDirectory>${project.build.directory}/lib</outputDirectory>
<overWriteIfNewer>true</overWriteIfNewer>
<overWriteReleases>false</overWriteReleases>
<overWriteSnapshots>true</overWriteSnapshots>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<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>test.LeanFTest</mainClass>
</manifest>
</archive>
<excludes>
<exclude>log4j2.xml</exclude>
</excludes>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<version>3.0.0</version>
<executions>
<execution>
<id>make-assembly</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
<configuration>
<finalName>${project.artifactId}-${project.version}</finalName>
<appendAssemblyId>false</appendAssemblyId>
<descriptors>
<descriptor>src/main/assembly/leanft-assembly.xml</descriptor>
</descriptors>
</configuration>
</plugin>
I will explain the usage of maven plugins:
- maven-dependency-plugin: copy all dependencies at package phase in a lib folder under the target folder.
- maven-jar-plugin:
- archive: generate manifest file, define in manifest all dependencies from the lib folder and what is the main class so you can run the application also with "java -jar"
- excludes: don't include the log4j2.xml file in the module jar because will be in config folder available at runtime from outside jar.
- maven-assembly-plugin: create at package phase a zip file that contains your distribution. The archive is placed in target folder. The descriptor tag reference your assembly configuration file leanft-assembly.xml.
Script
The script to launch the application call java with predefined parameters, the main line from script being:
%JAVA_HOME%\bin\java %JVM_ARGS% -cp %SCRIPT_DIR%\*;%SCRIPT_DIR%\config\ test.LeanFTest
How to generate a JAR with Maven and 3rd party dependencies
It depends on how GestorProblema1maquina.jar was built. Does GestorProblema1maquina.jar contain the 3rd party jar with dominio/Instancia class, as in, is it a fat jar / uber jar?
If it is built using maven assembly plugin in a way that it includes all of its dependencies, you should not run into this at runtime.
There are 2 choices
- Use mvn install and make GestorProblema1maquina.jar available in the repository.
- [link] https://maven.apache.org/plugins/maven-dependency-plugin/copy-dependencies-mojo.html says that the dependecnies are copied from a repository.
Also it states "The scopes being interpreted are the scopes as Maven sees them, not as specified in the pom" , so your configuration for the plugin may need explicit includes for the 3rd party system scope jar dependency to be included in the eventual jar.
Related Topics
What Is a Nosuchbeandefinitionexception and How to Fix It
Polymorphism VS Overriding VS Overloading
Fastest Way to Determine If an Integer'S Square Root Is an Integer
Difference Between Declaring Variables Before or in Loop
Regexp Java For Password Validation
How to Convert Json to a Hashmap Using Gson
Causes of Getting a Java.Lang.Verifyerror
Compare Two Objects With .Equals() and == Operator
Ways to Iterate Over a List in Java
Error: the Processing Instruction Target Matching "[Xx][Mm][Ll]" Is Not Allowed
Best Implementation For Hashcode Method For a Collection
Difference Between Javac and the Eclipse Compiler