How do I get my project's runtime dependencies copied into the target/lib folder?
As it is right now, after mvn clean install the target folder contains only my project's jar, but none of the runtime dependencies.
This works for me:
<project>
...
<profiles>
<profile>
<id>qa</id>
<build>
<plugins>
<plugin>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<phase>install</phase>
<goals>
<goal>copy-dependencies</goal>
</goals>
<configuration>
<outputDirectory>${project.build.directory}/lib</outputDirectory>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
</profiles>
</project>
mvn install dependency:copy-dependencies
Works for me with dependencies directory created in target folder. Like it!
The best approach depends on what you want to do:
If you want to bundle your dependencies into a WAR or EAR file, then simply set the packaging type of your project to EAR or WAR. Maven will bundle the dependencies into the right location.
If you want to create a JAR file that includes your code along with all your dependencies, then use the assembly plugin with the jar-with-dependencies descriptor. Maven will generate a complete JAR file with all your classes plus the classes from any dependencies.
If you want to simply pull your dependencies into the target directory interactively, then use the dependency plugin to copy your files in.
If you want to pull in the dependencies for some other type of processing, then you will probably need to generate your own plugin. There are APIs to get the list of dependencies, and their location on disk. You will have to take it from there...
Take a look at the Maven dependency plugin, specifically, the dependency:copy-dependencies goal. Take a look at the example under the heading The dependency:copy-dependencies mojo. Set the outputDirectory configuration property to ${basedir}/target/lib (I believe, you'll have to test).
Hope this helps.
All you need is the following snippet inside pom.xml's build/plugins:
<plugin>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<phase>prepare-package</phase>
<goals>
<goal>copy-dependencies</goal>
</goals>
<configuration>
<outputDirectory>${project.build.directory}/lib</outputDirectory>
</configuration>
</execution>
</executions>
</plugin>
The above will run in the package phase when you run
mvn clean package
And the dependencies will be copied to the outputDirectory specified in the snippet, i.e. lib in this case.
If you only want to do that occasionally, then no changes to pom.xml are required. Simply run the following:
mvn clean package dependency:copy-dependencies
To override the default location, which is ${project.build.directory}/dependencies, add a System property named outputDirectory, i.e.
-DoutputDirectory=${project.build.directory}/lib
If you want to do this on an occasional basis (and thus don't want to change your POM), try this command-line:
mvn dependency:copy-dependencies -DoutputDirectory=${project.build.directory}/lib
If you omit the last argument, the dependences are placed in target/dependencies.
A simple and elegant solution for the case where one needs to copy the dependencies to a target directory without using any other phases of maven (I found this very useful when working with Vaadin).
Complete pom example:
<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>groupId</groupId>
<artifactId>artifactId</artifactId>
<version>1.0</version>
<dependencies>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>1.1.1</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<phase>process-sources</phase>
<goals>
<goal>copy-dependencies</goal>
</goals>
<configuration>
<outputDirectory>${targetdirectory}</outputDirectory>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
Then run mvn process-sources
The jar file dependencies can be found in /target/dependency
Try something like this:
<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>
<mainClass>MainClass</mainClass>
</manifest>
</archive>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<version>2.4</version>
<executions>
<execution>
<id>copy</id>
<phase>install</phase>
<goals>
<goal>copy-dependencies</goal>
</goals>
<configuration>
<outputDirectory>
${project.build.directory}/lib
</outputDirectory>
</configuration>
</execution>
</executions>
</plugin>
supposing
you don't want to alter the pom.xml
you don't want test scoped (e.g. junit.jar) or provided dependencies (e.g. wlfullclient.jar)
here ist what worked for me:
mvn install dependency:copy-dependencies -DincludeScope=runtime -DoutputDirectory=target/lib
If you want to deliver a bundle of your application jar, together with all its dependencies and some scripts to invoke the MainClass, look at the appassembler-maven-plugin.
The following configuration will generate scripts for Window and Linux to launch the application (with a generated path referencing all the dependency jars, download all dependencies (into a lib folder below target/appassembler). The assembly plugin can then be used to package the whole appassembler directory to a zip which is installed/deployed along with the jar to the repository.
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>appassembler-maven-plugin</artifactId>
<version>1.0</version>
<executions>
<execution>
<id>generate-jsw-scripts</id>
<phase>package</phase>
<goals>
<goal>generate-daemons</goal>
</goals>
<configuration>
<!--declare the JSW config -->
<daemons>
<daemon>
<id>myApp</id>
<mainClass>name.seller.rich.MyMainClass</mainClass>
<commandLineArguments>
<commandLineArgument>start</commandLineArgument>
</commandLineArguments>
<platforms>
<platform>jsw</platform>
</platforms>
</daemon>
</daemons>
<target>${project.build.directory}/appassembler</target>
</configuration>
</execution>
<execution>
<id>assemble-standalone</id>
<phase>integration-test</phase>
<goals>
<goal>assemble</goal>
</goals>
<configuration>
<programs>
<program>
<mainClass>name.seller.rich.MyMainClass</mainClass>
<!-- the name of the bat/sh files to be generated -->
<name>mymain</name>
</program>
</programs>
<platforms>
<platform>windows</platform>
<platform>unix</platform>
</platforms>
<repositoryLayout>flat</repositoryLayout>
<repositoryName>lib</repositoryName>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.2-beta-4</version>
<executions>
<execution>
<phase>integration-test</phase>
<goals>
<goal>single</goal>
</goals>
<configuration>
<descriptors>
<descriptor>src/main/assembly/archive.xml</descriptor>
</descriptors>
</configuration>
</execution>
</executions>
</plugin>
The assembly descriptor (in src/main/assembly) to package the direcotry as a zip would be:
<assembly>
<id>archive</id>
<formats>
<format>zip</format>
</formats>
<fileSets>
<fileSet>
<directory>${project.build.directory}/appassembler</directory>
<outputDirectory>/</outputDirectory>
</fileSet>
</fileSets>
</assembly>
If you make your project a war or ear type maven will copy the dependencies.
It's a heavy solution for embedding heavy dependencies, but Maven's Assembly Plugin does the trick for me.
#Rich Seller's answer should work, although for simpler cases you should only need this excerpt from the usage guide:
<project>
<build>
<plugins>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.2.2</version>
<configuration>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
</plugin>
</plugins>
</build>
</project>
You can use the the Shade Plugin to create an uber jar in which you can bundle all your 3rd party dependencies.
Just to spell out what has already been said in brief. I wanted to create an executable JAR file that included my dependencies along with my code. This worked for me:
(1) In the pom, under <build><plugins>, I included:
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.2-beta-5</version>
<configuration>
<archive>
<manifest>
<mainClass>dk.certifikat.oces2.some.package.MyMainClass</mainClass>
</manifest>
</archive>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
</plugin>
(2) Running mvn compile assembly:assembly produced the desired my-project-0.1-SNAPSHOT-jar-with-dependencies.jar in the project's target directory.
(3) I ran the JAR with java -jar my-project-0.1-SNAPSHOT-jar-with-dependencies.jar
If you're having problems related to dependencies not appearing in the WEB-INF/lib file when running on a Tomcat server in Eclipse, take a look at this:
ClassNotFoundException DispatcherServlet when launching Tomcat (Maven dependencies not copied to wtpwebapps)
You simply had to add the Maven Dependencies in Project Properties > Deployment Assembly.
You could place a settings.xml file in your project directory with a basic config like this:
<?xml version="1.0" encoding="UTF-8"?>
<settings xmlns="http://maven.apache.org/SETTINGS/1.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0 https://maven.apache.org/xsd/settings-1.0.0.xsd">
<localRepository>.m2/repository</localRepository>
<interactiveMode/>
<offline/>
<pluginGroups/>
<servers/>
<mirrors/>
<proxies/>
<profiles/>
<activeProfiles/>
</settings>
More information on these settings can be found in the official Maven docs.
Note that the path is resolved relative to the directory where the actual settings file resides in unless you enter an absolute path.
When you execute maven commands you can use the settings file as follows:
mvn -s settings.xml clean install
Side note: I use this in my GitLab CI/CD pipeline in order to being able to cache the maven repository for several jobs so that the dependencies don't need to be downloaded for every job execution. GitLab can only cache files or directories from your project directory and therefore I reference a directory wihtin my project directory.
Related
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>
In eclipse you can easily add dependencies (i.e. a JAR file) to you're project.
Right click on the project and click -> Build Path-> add libraries.
Now a hidden file is createn inside the project, ".classpath".
Inside this file is a classpathEntry added so now I can use the libraries by adding it in a java file:
import foo.bar.*;
This "application" can now be exported to a single jar.
How can I achieve this with Maven and without eclipse?
I switched to emacs... :)
With the command:
mvn archetype:generate -DgroupId=com.mycompany.app -DartifactId=my-cli -DarchetypeArtifactId=maven-archetype-quickstart -DinteractiveMode=false
I get myself a sample start application.
inside a src folder is a App.java file writing "hello World" on a commandline.
with the following in the pom.xml I obtain myself a jar inside my project(maven indedependent deployment) successfully:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<version>2.10</version>
<executions>
<execution>
<id>copy</id>
<phase>package</phase>
<goals>
<goal>copy</goal>
</goals>
<configuration>
<artifactItems>
<artifactItem>
<groupId>com.mycompany.third-party</groupId>
<artifactId>commons-cli-archetype</artifactId>
<version>1.0-SNAPSHOT</version>
<type>jar</type>
<overWrite>false</overWrite>
<!--${project.basedir} ${project.build.directory} -->
<outputDirectory>${project.basedir}/resources/repo</outputDirectory>
<destFileName>optional-new-name.jar</destFileName>
</artifactItem>
</artifactItems>
<outputDirectory>${project.basedir}/resources/repo</outputDirectory>
<overWriteReleases>false</overWriteReleases>
<overWriteSnapshots>true</overWriteSnapshots>
</configuration>
</execution>
</executions>
</plugin>
Now how can I use this jar inside my App.java?
Do I have to create a .classpath file manually?
How can I arrange my classpathentries automatically?
I have been trying to create a manifest.MF with the classpassentries but with no success. I have tried several tutorials.
I had no success with:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<includes>
<include>${project.basedir}
/resources/repo/optional- new-name.jar</include>
</includes>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<configuration>
<archive>
<manifest>
<addDefaultImplementationEntries>true
</addDefaultImplementationEntries>
<addClasspath>true</addClasspath>
<mainClass>your.main.Class</mainClass>
</manifest>
<manifestEntries>
<Class-Path>${project.basedir}/resources/repo</Class-Path>
</manifestEntries>
<manifestFile>
<!--
${project.build.outputDirectory}/META-INF/MANIFEST.MF
-->
${project.basedir}/META-INF/MANIFEST.MF
</manifestFile>
</archive>
<!--
<archive>
<manifest>
<mainClass>com.mkyong.core.App</mainClass>
</manifest>
</archive>
-->
</configuration>
after creating the manifest.MF manually.
after the command
mvn clean install
the manifest.MF remains empty.
+1 for not using eclipse ;^)
If you are looking to reference code from another JAR then try adding the following to your POM:
<dependencies>
<dependency>
<groupId>xxx</groupId>
<artifactId>yyy</artifactId>
<version>zzz</version>
</dependency>
</dependencies>
Where xxx, yyy and zzz are the maven coordinates for the JAR you want to import. You can get these from your Nexus
Edit:
So for example if you were looking to import Joda time it would be
<dependency>
<groupId>joda-time</groupId>
<artifactId>joda-time</artifactId>
<version>2.6</version>
</dependency>
If you are looking to combine the contents of all your dependencies with your code and release them as a single JAR then you might want to take a look at the maven-shade-plugin. See How to package a jar and all dependencies within a new jar with maven
And one other thing, you should never play with the .classpath file. This is something Eclipse specific. Changing it won't effect Maven and will probably confuse Eclipse
Got it!
I followed this tutorial until step 5.
http://www.mkyong.com/maven/maven-create-a-fat-jar-file-one-jar-example/
Instead of doing step 5 I added:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>2.3</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
</execution>
</executions>
</plugin>
To the pom.
and voila:
mvn package
and
java -jar target/dateutils.jar
Now it works.
So thanks for you're help Stormcloud!
So what happened? Still no resources spotted in my .jar.
The jar got shaded.
https://maven.apache.org/plugins/maven-shade-plugin/
What if I want to export my jar on a server without maven. So how to export a complete working jar?
Thanks again!
I would like to execute git describe as part of a maven build and use the resulting output in the manifest for building a .jar package.
I know how to do this in ant via the <exec> task with outputproperty to an ant property variable, but I have very little experience with Maven and don't even know where to look.
Is this possible?
I found this in a sample pom.xml file so adding something to the manifest looks pretty easy:
<project>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>2.6</version>
<configuration>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<mainClass>my.class.here.Myclass</mainClass>
<classpathLayoutType>custom</classpathLayoutType>
<customClasspathLayout>lib/$${artifact.artifactId}-$${artifact.version}$${dashClassifier?}.$${artifact.extension}</customClasspathLayout>
</manifest>
</archive>
</configuration>
</plugin>
</plugins>
</build>
</project>
Not sure how to capture command execution though.
Here is a suggested approach:
Use the Exec Maven Plugin for launching your git commands and write to a properties file (name=value pattern, if possible)
Use the Properties Maven Plugin to load the configuration
The configuration loaded can then be used as properties in your POM. We are basically dynamically creating properties of our build. To do so (to use these properties), the steps above must be executed as early as possible in the build flow (i.e. validate or initialize phase).
Below an example of flow, just tested and work perfectly (on Windows machine):
<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>com.sample</groupId>
<artifactId>generation</artifactId>
<version>0.0.1-SNAPSHOT</version>
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>1.1</version>
<executions>
<execution>
<id>retrieve-config</id>
<phase>validate</phase>
<goals>
<goal>exec</goal>
</goals>
</execution>
</executions>
<configuration>
<executable>echo</executable>
<arguments>
<argument>jar.name=from-exec</argument>
<argument>></argument>
<argument>config.properties</argument>
</arguments>
<workingDirectory>${basedir}/src/main/resources/</workingDirectory>
</configuration>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>properties-maven-plugin</artifactId>
<version>1.0-alpha-2</version>
<executions>
<execution>
<id>read-properties</id>
<phase>initialize</phase>
<goals>
<goal>read-project-properties</goal>
</goals>
<configuration>
<files>
<file>${basedir}/src/main/resources/config.properties</file>
</files>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>2.4</version>
<configuration>
<finalName>${jar.name}</finalName>
</configuration>
</plugin>
</plugins>
</build>
</project>
Basically, the exec plugin attached to the validate phase will be executed at the beginning of the build, writing to a config.properties file (via the echo command) the content jar.name=from-exec.
Then the properties plugin attached to the initialize phase will read that config.properties file and load the properties to be used as part of the build.
Then, as an example, the jar plugin will use that property as part of its configuration (the <finalName>${jar.name}</finalName> part).
Running mvn clean package, you will find the from-exec.jar file in the target folder.
If you can't get a way of having the result of git describe as name=value pattern, you can (worst case) have two Exec Maven Plugin executions, the first writing to the file the property name and the equals character (i.e. via an echo), the second (git describe) appending to the file the property value.
There is a Maven plugin here https://github.com/ktoso/maven-git-commit-id-plugin that will do what you want.
If you hook into your build it will generate a Maven variable named ${git.commit.id.describe} that you can then use Maven's resource filtering to dynamically modify your manifest.
Building on what #A_Di-Matteo said, you can get the git tag into the properties file like this
In the maven exec plugin.
<execution>
<id>set-git-tag</id>
<phase>validate</phase>
<goals>
<goal>exec</goal>
</goals>
<configuration>
<executable>bash</executable>
<arguments>
<argument>-c</argument>
<argument>echo git.tag=`git describe --always --dirty=-modified`</argument>
<argument>></argument>
<argument>config.properties</argument>
</arguments>
<workingDirectory>${basedir}/src/main/resources/</workingDirectory>
</configuration>
</execution>
You can also append to an existing file like so
<execution>
<id>set-git-tag</id>
<phase>validate</phase>
<goals>
<goal>exec</goal>
</goals>
<configuration>
<executable>bash</executable>
<arguments>
<argument>-c</argument>
<argument>echo git.tag=`git describe --always --dirty=-modified`</argument>
<argument>>></argument>
<argument>${basedir}/src/main/resources/config.properties</argument>
</arguments>
</configuration>
</execution>
The limitation here is that it requires bash.
My problem can be reproduced by creating a new project in Netbeans 8:
New Project >> Maven >> JavaFX Application
Then adding the org.springframework spring-context dependency.
Build times go up from a few seconds to more than half a minute, most of it due to running javafxpackager.
I can live with slow release builds but how can I speed up my development builds?
This is my 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>com.mycompany</groupId>
<artifactId>mavenproject1</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
<name>mavenproject1</name>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<mainClass>com.mycompany.mavenproject1.MainApp</mainClass>
</properties>
<organization>
<!-- Used as the 'Vendor' for JNLP generation -->
<name>Your Organisation</name>
</organization>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<version>2.6</version>
<executions>
<execution>
<id>unpack-dependencies</id>
<phase>package</phase>
<goals>
<goal>unpack-dependencies</goal>
</goals>
<configuration>
<excludeScope>system</excludeScope>
<excludeGroupIds>junit,org.mockito,org.hamcrest</excludeGroupIds>
<outputDirectory>${project.build.directory}/classes</outputDirectory>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>1.2.1</version>
<executions>
<execution>
<id>unpack-dependencies</id>
<phase>package</phase>
<goals>
<goal>exec</goal>
</goals>
<configuration>
<executable>${java.home}/../bin/javafxpackager</executable>
<arguments>
<argument>-createjar</argument>
<argument>-nocss2bin</argument>
<argument>-appclass</argument>
<argument>${mainClass}</argument>
<argument>-srcdir</argument>
<argument>${project.build.directory}/classes</argument>
<argument>-outdir</argument>
<argument>${project.build.directory}</argument>
<argument>-outfile</argument>
<argument>${project.build.finalName}.jar</argument>
</arguments>
</configuration>
</execution>
<execution>
<id>default-cli</id>
<goals>
<goal>exec</goal>
</goals>
<configuration>
<executable>${java.home}/bin/java</executable>
<commandlineArgs>${runfx.args}</commandlineArgs>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.1</version>
<configuration>
<source>1.7</source>
<target>1.7</target>
<compilerArguments>
<bootclasspath>${sun.boot.class.path}${path.separator}${java.home}/lib/jfxrt.jar</bootclasspath>
</compilerArguments>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.16</version>
<configuration>
<additionalClasspathElements>
<additionalClasspathElement>${java.home}/lib/jfxrt.jar</additionalClasspathElement>
</additionalClasspathElements>
</configuration>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>4.0.6.RELEASE</version>
</dependency>
</dependencies>
Thanks!
Daniel
You could define the plugin in a profile that is inactive by default. Then, in order to make the production build, you would have to manually specify the activation of that profile (or activate it in any other standard way).
You pom would be something like (only diffs shown):
<?xml version="1.0" encoding="UTF-8"?>
<project ...>
...
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
...
<executions>
<!-- take this out of here
<execution>
<id>unpack-dependencies</id>
...
</execution>
-->
<execution>
...
</execution>
</executions>
</plugin>
...
</plugins>
</build>
<profiles>
<profile>
<id>javafxpackager</id>
<build>
<plugins>
<!-- INSERT THE exec-maven-plugin HERE, ONLY
WITH THE unpack-dependencies EXECUTION -->
</plugins>
</build>
</profile>
</profiles>
</project>
In production run mvn ... -Pjavafxpackager
To complete Nikos' answer, this is the configuration of the maven-assembly-plugin which creates the archive for normal builds.
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<configuration>
<appendAssemblyId>false</appendAssemblyId>
<archive>
<manifest>
<mainClass>${mainClass}</mainClass>
</manifest>
</archive>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
<executions>
<execution>
<id>my-assembly</id>
<phase>package</phase>
<goals>
<goal>assembly</goal>
</goals>
</execution>
</executions>
</plugin>
above solutions dont work. The problem has nothing to do with javafxpackager whatsoever. The cause lies in the maven standard configuration. On every project run Maven performs a project clean by default. This deletes the targets/classes/ folder. Thats the same folder where all the unpacked jar files of your dependencies are placed. If those get deleted on every new run then they have to be unpacked over and over again. Anyway, heres how you can prevent the clean from happening:
<plugin>
<artifactId>maven-clean-plugin</artifactId>
<version>2.4.1</version>
<configuration>
<skip>true</skip>
</configuration>
</plugin>
Add this to your POM.xml. Make sure you get the version correct You can check the version of your maven clean plugin in the effective pom (thats parent pom + project POM combined). In netbeans you can watch the readonly effective pom.xml under the effective tab when you've opened the pom.xml file of your project.
please give me a few +1's i want to get 50 points so that i can finally comment on other peoples answers. Thank you!
EDIT:
Also add skip to default-cli to avoid errors
<execution>
<id>default-cli</id>
<goals>
<goal>exec</goal>
</goals>
<configuration>
<skip>true</skip>
<executable>${java.home}/bin/java</executable>
<commandlineArgs>${runfx.args}</commandlineArgs>
</configuration>
</execution>
EDIT 2:
For those of you who would like to retain the ability to clean heres another method to prevent the maven plugin from deleting all jar files:
<plugin>
<artifactId>maven-clean-plugin</artifactId>
<version>2.4.1</version>
<configuration>
<excludeDefaultDirectories>true</excludeDefaultDirectories>
<filesets>
<!-- delete directories that will be generated when you
start the develpment server/client in eclipse
-->
<fileset>
<directory>target/classes</directory>
<excludes>
<exclude>**/*</exclude>
</excludes>
</fileset>
</filesets>
</configuration>
Again, make sure is correct
TL;DR:
To avoid unpacking dependencies, you don't need to modify the default pom.xml at all. Just change what Netbeans calls when you press Run (or Debug). In nbactions.xml change:
runfx.args: Replace -jar "${project.build.directory}/${project.build.finalName}.jar" with -cp %classpath ${mainClass}. This way, the exec goal will not try to execute any jar but rather run your project from the target/classes directory. So no need to build the jar at all.
goals: replace the "package" goal with "process-classes" (or "test" or any phase you want). We don't need a jar so no need to run the package phase. And no package phase also means no unpacking/repacking etc.
If you ever need the jar file with all the dependencies, just choose "clean and build" in Netbeans or run mvn clean install.
Background:
What happens when you press run in the standard Netbeans JavaFX maven project is:
clean package exec - defined in nbactions.xml, configured in pom.xml:
clean: as usual - deletes the target directory
package:
first as usual - copies resources and compiles sources to target/classes and packs that all to a jar without dependencies
maven-dependency-plugin unpacks all the dependency jar files to target/classes
exec-maven-plugin:unpack-dependencies (the id "unpack-dependencies" is missleading, should be something like "jar-with-dependencies") executes javapackager which builds a jar with dependencies overwriting the first jar
exec:
executes java with ${runfx.args} as arguments (defined in nbactions.xml) i.e. runs the jar
What happens after the changes above:
clean process-classes exec - defined in nbactions.xml, configured in pom.xml:
clean: as usual - deletes the target directory
process-classes:
as usual - copies resources and compiles sources to target/classes
exec:
executes java with ${runfx.args} as arguments (defined in nbactions.xml) i.e. runs the class target/classes/path/to/your/MainClass
Even better:
You may want remove the "clean" goal from nbactions.xml. This way, all the resource files won't be copied each time over and over (although the resource plugin will still keep saying "Copying X resources" - see the comments under https://stackoverflow.com/a/33700970/3519572).
Now, you may also want to only recompile changed classes rather than the whole project by adding useIncrementalCompilation=false (e.g. like <goal>org.codehaus.mojo:exec-maven-plugin:1.2.1:exec -Dmaven.compiler.useIncrementalCompilation=false</goal>). But be sure to read https://stackoverflow.com/a/49700942/3519572!
Therefore, you may also want to add a toolbar button to the "clean" goal to be able to run it manually easily at any time: https://stackoverflow.com/a/26546551/3519572.
BTW:
Finally, you might want to change the NetBeans generated pom.xml anyway. At least my NB 8.2 refers to the deprecated javafxpackager (rename to javapackager). Also the part <bootclasspath>..../lib/jfxrt.jar</bootclasspath> doesn't seem to be necessary with java 8. It actually breaks my build if I run it from the terminal. Removing it seems to fix it and doesn't seem to cause any trouble if started from NB.
You can also use parallel maven build feature to speed up.
By default, Maven does not utilize the full power of your hardware. It builds all modules sequentially rather than in parallel. However, often your project setup does not require it to be sequential. Often you can command Maven to analyze your project including the dependency graph and build the project in parallel where possible. You can either specify the exact number of threads to use for building your project or use a portable version of the parameter and specify the number of thread in terms of CPUs available on the machine.
mvn -T 4 install -- will use 4 threads
mvn -T 1C install -- will use 1 thread per available CPU core
See for more details: https://zeroturnaround.com/rebellabs/your-maven-build-is-slow-speed-it-up/
I can deploy a jar by using the following in my pom.xml and running mvn deploy:
<distributionManagement>
<repository>
<id>releases</id>
<url>http://${host}:8081/nexus/content/repositories/releases</url>
</repository>
<snapshotRepository>
<id>snapshots</id>
<name>Internal Snapshots</name>
<url>http://${host}:8081/nexus/content/repositories/snapshots</url>
</snapshotRepository>
</distributionManagement>
And I can build an executable jar-with-dependencies using the following:
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<executions>
<execution>
<id>create-executable-jar</id>
<phase>deploy</phase>
<goals>
<goal>single</goal>
</goals>
<configuration>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
<archive>
<manifest>
<mainClass>my.company.app.Main</mainClass>
</manifest>
</archive>
</configuration>
</execution>
</executions>
</plugin>
Problem is I don't know how to stitch these together to deploy the executable jar to my Maven repo. I don't really know if this is accomplished by a new plugin or by adding a goal or other step to the existing assembly plugin.
If you bind the assembly to the packaging phase, it will install in your repository both the "regular" jar and the with-dependencies jar when you do a build:
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<configuration>
<archive>
<manifest>
<mainClass>my.company.app.Main</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>
Then simply run mvn clean install deploy to upload both jars to your repository.
In order to build a (so-called) Über JAR and deploy it using maven, you could also use the shade plugin. The following code is taken from their website but I've made one or two projects using this feature.
<project>
...
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>2.0</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<shadedArtifactAttached>true</shadedArtifactAttached>
<shadedClassifierName>jackofall</shadedClassifierName> <!-- Any name that makes sense -->
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
...
</project>
In this configuration you get the Über JAR as one deployment besides the normal JAR. The user of your JAR can then decide to pull the all-in-one package or the JAR with dependencies based on the classifier.
I'll usually use the shade plugin to build Über JARs (or modify the JAR in a way) and use the assembly plugin to build things like installation packages (containing the JAR and possibly other things). I am unsure what the intended goals of the single plugins are however.
The following worked. I'm going to leave this question open a bit because I'm not positive this is best practice, but working is something.
Problems I notice are that I made up the ID name and I don't know if this is usual practice and that I have to hard code the jar name; it isn't inferred from anything else.
<plugin>
<artifactId>maven-deploy-plugin</artifactId>
<version>2.7</version>
<executions>
<execution>
<id>deploy-executable</id>
<goals>
<goal>deploy-file</goal>
</goals>
<configuration>
<file>target/Monitoring-Client-1.0-SNAPSHOT-jar-with-dependencies.jar</file>
</configuration>
</execution>
</executions>
</plugin>
Essentially my difficulty doing this revealed the fact that my pom.xml was way off the rails already. Everything would have snapped into place on its own. I was formerly doing:
Save all the dependencies into a lib folder
Build a jar with a classpath slurping up that lib folder
Use the assembly plugin to make another deployable jar
I think there were several reasons this sort of made sense along the way, especially when my libraries were not well-factored from my applications.
However by deleting 1 and 2 all that is needed is the distributionManagement section and the deploy phase works automagically. So all in all this is an amazing case of literally adding functionality by deleting large swathes of code.
First you shouldn't do the creation of the ueber jar in the deploy phase it's better to do this in the package phase. Furthermore the created jar file is usually automatically attached to your artifact and will be transfered to the remote repository (in your case Nexus). You can check this if you simply try to do a mvn install and take a look at the output if the created jar is installed into the local repository.
To deploy the results into nexus you need to call mvn deploy.