The maven dependencies are not added to the jar in eclipse - java

I'm coding a maven project with eclipse 2018.09 under java 11 and I've a problem with the maven jar creation. When I clean package the project, it delivers me a jar but no dependencies are added into and i sometimes have warning in eclipse like:
classpath entry junit(for example) will not be exported it may result a ClassNotFoundException.
Which is in fact what's happening when i launch my jar project.
Thanks.

it delivers me a jar but no dependencies are added into [it]
it is totally normal. By default, when Maven builds a jar, it does not add any dependencies in it, but only the .class and resources of your current project.
When you run your programm you want it to find your dependencies otherwise you will face ClassNotFoundException. So you must configure your classpath to reference the dependencies.
1- if you want to run you programm from your local computer with Maven, use the exec Maven plugin with the <java> goal defined in your pom like explained here: https://www.mojohaus.org/exec-maven-plugin/usage.html#Java_goal
alternatively you can run it from a launcher in your IDE. The IDE will build the classpath for you and the classpath will corectly contain your dependencies.
2- if you want to run from the command line on any computer, you have to copy all of you dependencies in one directory (using Maven's dependency plugin mvn dependency:copy) and run you jar like this:
java -cp myProgram.jar:dependencyDirectory/* com.blabla.MainClass
(beware the use of ';' or ':' and '/' or '\' depending on Linux/Windows)
3- as an alternative you can run your jar with java -jar myprogram.jar but only if it contains a correct MANIFEST.MF where the location of all the dependencies are hardcoded.
My advice is to target solution 1 or 2 first.
PS: you can also create "fat jars" or "uber jars" containing your dependencies but I would advise you do not target this solution at first.

You can simply add this to your pom.xml (under the < plugins > tag):
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<configuration>
<archive>
<manifest>
<mainClass>App</mainClass>
</manifest>
</archive>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
<executions>
<execution>
<id>make-assembly</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
Remember to change the mainclass to your entrypoint (which class the static void main(string[args]) is).
Now when you run the command mvn clean install there will be a jar in the targets folder with name yourproject-version-SNAPSHOT-jar-with-dependencies.jar

Related

Maven : Distributing maven jar

I have a sample.jar created from a Maven project with all the dependencies (fat jar using maven assembly plugin) it requires. I use this jar in a client's application by using mvn install:install-file and including the dependency in the client application's pom.xml. This works.
But is there a way such that I do not have to build the sample.jar as a fat jar?
Instead let the client application's pom resolve the dependencies required by sample.jar as well by reading the sample.jar's pom.xml, if all of the dependencies of sample.jar are available from Maven central repo?
UPDATE:
My maven assembly plugin.
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<configuration>
<archive>
<manifest>
<mainClass>myMainClass</mainClass>
</manifest>
</archive>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
<appendAssemblyId>false</appendAssemblyId>
</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>
In your repository of choice (Central, a proprietary Artifactory etc.), you need to upload both the pom and the (thin) jar.
When you declare a dependency in the client project, Maven will automatically look for both. It will use the pom to determine the transitive dependencies and will compile against the jar.
There are a few things to note here.
You didn't specify how exactly you generate the fat jar but normally maven-assembly-plugin will create an additional file next to the thin (regular) jar file it creates. You can check if that is the case by looking at your project's target folder.
Unless otherwise configured, maven-assembly-plugin would also make any artifact it creates a project artifact. When you run mvn install all project artifacts will be installed in the local Maven repo. That means you probably already have both the thin and the fat jar in your local Maven repo.
Assuming the above statements hold true in your particular case and your client project has a standard dependency record (with no special types, qualifiers, ...) it is most likely that it already uses the thin jar. You can check if that is the case by running mvn dependency:tree in your client project.
Please check this answer. Worth adding that either generatePom or pomFile options in the mvn install command are crucial for Maven to be able to resolve transitive dependencies if you use the thin version of your jar. Alternatively, you may upload your thin jar into an artifactory, if possible, that should also do it.
Useful references:
Installing an artifact with a custom POM
Generating a generic POM

How maven jar project works when it is packaged to jar?

I am new to maven. I have created a maven project which will be packaged to JAR. I did clean package then jar is created. When i extracted the same jar, i could not see any dependencies (jars) i added in pom.xml inside the packaged jar. If i give this jar to third party clients how will the code work without any dependent jars ? Please help me how maven manages the jars?
Thanks!
Maven handles dependencies based on how you configure the dependency plugin.
See this reference for a simple example of how to do this.
In this example, the following code configures where your dependencies will end up:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<version>2.5.1</version>
<executions>
<execution>
<id>copy-dependencies</id>
<phase>package</phase>
<goals>
<goal>copy-dependencies</goal>
</goals>
<configuration>
<includeGroupIds>log4j</includeGroupIds>
<outputDirectory>${project.build.directory}/dependency-jars/</outputDirectory>
</configuration>
</execution>
</executions>
</plugin>
Then this code sets up the classpath for your main jar, which will allow anyone running it to find these dependencies
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>2.4</version>
<configuration>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<mainClass>com.mkyong.core.App</mainClass>
<classpathPrefix>dependency-jars/</classpathPrefix>
</manifest>
</archive>
</configuration>
</plugin>
Your other option would be to create a single jar, with all dependencies included, by following this example here
You could distribute the jar and the POM file if you want to try and provide your users with the files in that manner, but they'd need to be able to access your Maven repository where those dependencies are kept.
Core maven doesn't handle this. Maven is a build tool, its work is to build an artifact (a jar in your case). Dependencies you define in your module's pom.xml file are needed to get the code compiled. You'll need maven plugins to do so.
Now, you're asking not about the build, but the distribution of your compiled binaries.
If I understand it should be a lot of jars (your and your dependencies). Alternatively you may distribute the code as a jar + dependencies inside.
Example:
A first case:
If your code resides in module A (say, the code is in packages org.a.*) and depends on some thirdparty (say, log4j, whose classes reside in org.apache.log4j) than you can expect that you jar will only contain the classes of module a and you expect that the log4j will be added by the user of your module automatically (The first case).
A second case:
module a.jar will contain both org.a.* and org.apache.log4j.* classes, everything in the same module.
In general the first approach is more "healthy" and in this case you shouldn't do anything in maven. Maybe your distribution tool/documentation should contain this information.
If someone uses the module a in his/her code like a thirdparty (if you develop a framework or something) and if his/her project is mavenized, than the fact you've defined a dependency on log4j will make the maven to download the log4j as well as your a.jar (In maven notation, this is called "transitive dependencies").
If you're interested in the second case (this can be relevant if you define some "client application", like "jndi client for some server" for example) you might want to take a look on Maven shade plugin
Beware this can lead to dependency hell (what if the application that uses your client also makes use of log4j? what if the log4j-s are of different version)/
Bottom line, you probably want the first approach, think twice before you decide the second approach :)
One more tip, if you just want to download all the dependencies of your module "a" you might want to use maven dependency plugin - type the following in the command prompt
mvn dependency:copy-dependencies
and you'll find all the dependencies in target/dependencies folder
Hope this helps and happy mavening
The simplest solution to the problem is to use the maven-assembly-plugin which can create such jar with dependencies like the following:
<build>
<plugins>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.4</version>
<executions>
<execution>
<id>distro-assembly</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
<configuration>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
Afterwards you can distribute the created jar xyz-1.0-jar-with-dependencies which contains the defined dependencies.
If you need more control on how the resulting artifact is created or if some files needed to be overwritten etc. you might take a deeper look into maven-shade-plugin

Maven: Export jar with 3rd-party jars added to classpath in manifest

I am developing a Java maven project with Eclipse and want to export a jar that includes all referenced libraries. These referenced libraries fall into one of these two categories:
They are explicit (or implicit) dependencies in the pom.xml
I have some libraries not available as maven artifacts and have put them in /lib (and added them to the build path in Eclipse)
There's the maven-assembly-plugin, which works fine for 1). However, I'm unable to find a maven plugin that also includes non-maven-dependencies, e.g. "all jars in /lib".
Then there's the Eclipse FatJar plugin, which sort of works, but hasn't been updated since 2009, so it seems unmaintained. Also I prefer an export method that I can directly specify in the pom.xml.
Can anyone point me to a maven plugin or the like to export all referenced libraries, including those from case 2) ? That only needs to involve putting them in the jar and referencing them in the manifest's classpath.
Thanks!
I think the best way to handle this is to include your custom libs into a local maven repository. Now you can inlcude your libraries as maven dependencies and you can export all your dependencies specified in your pom with the maven-assembly-plugin.
Here is a tutorial, how to put your libs into a local repository in maven to use it in your pom. http://www.mkyong.com/maven/how-to-include-library-manully-into-maven-local-repository/
And in your pom.xml:
<!-- setup jar manifest to executable with dependencies -->
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<configuration>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
<archive>
<manifest>
<mainClass>your.main.class</mainClass>
</manifest>
</archive>
</configuration>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
This looks like a task for Tycho. It is a set of maven plugins that allows to create eclipse plugins with maven. Tycho considers manifest entries as build dependencies.
However I'm not aware of how to package all those dependencies in a single jar. This may also be conflicting with the osgi spec. But if you wish to ignore osgi you could just try the jar-with-dependencies assembly.

creating jar file of maven projects with netbeans

I am using netbeans to work on a project. I am using svn, so that I can commit to newer versions and revert to an older version in case I mess up. Now I want to create a jar file of this project but the build tab in the project properties does not display the packaging option, it only displays one option and that is of 'compile'.
If I create a new project (Java Application) it does show the packaging option and then I can easily create a jar file, but this maven project that I am working on does not work like this.
Please suggest me a way to create jar file out of my maven project.
Thanks,
Based on #yatskevich answer, you could go to your NetBeans Project Properties > Actions and add package to the Execute Goals of the following Actions:
Build project
Clean and Build project
Build with dependencies
Plus any other you feel should also package
I did this on NetBeans 7.2.1
PS: this will create the JAR on every change you make, so choose wisely where to add package. I don't mind it building a JAR for small projects on every build.
Open cmd (if you are on Windows) or any shell (if you are on Linux)
Navigate to your project directory (use cd command)
Run mvn clean package there.
Your jar will be in <project dir>/target.
Include maven-assembly-plugin plugin in your .pom file. It will instruct Maven to assemble your application with all it's dependencies.
Later when you will build your Netbeans project you will see your newly builded jar with all it's dependencies.
<build>
<sourceDirectory>src</sourceDirectory>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.4</version>
<configuration>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
<archive>
<manifest>
<mainClass>com.my.class</mainClass>
</manifest>
</archive>
</configuration>
<executions>
<execution>
<id>make-assembly</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
Check out to learn more about creating Jar file with Maven: https://javatutorial.net/create-java-jar-file-with-maven

Running jar, setting classpath

I've got a project I've made with Maven. I compile a JAR, with "mvn package", and now I want to run it, preferably without setting some insane classpath, as it depends on Spring and half the internet or something. Is there any way I can run it easily? Something like "mvn run" would be great, or an option to throw in all dependencies into the jar so I can do "java -jar" would also be splendid.
How do you deal with this, and what do you recommend doing? Because exporting a CLASSPATH based on ~/.m2 would probably just be hurtful ;-)
Setting CLASSPATH and calling java -jar myjar.jar wouldn't work anyway. Because the java -jar command ignores the CLASSPATH environment variable as well as the -cp flag.
In this case you had to add the classpath entries to the jar's MANIFEST at the Class-Path key, like:
Class-Path: jar1-name jar2-name directory-name/jar3-name
Use the Maven Assembly Plugin - it will automatically build your JAR with all included dependencies, and you can set the main class parameter to make the JAR executable.
The documentation can be confusing, so here is an example of what your POM will look like:
<build>
<plugins>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.1</version>
<configuration>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
<archive>
<manifest>
<mainClass>package.of.my.MainClass</mainClass>
<packageName>package.of.my</packageName>
</manifest>
</archive>
</configuration>
</plugin>
</plugins>
</build>
And then you can run as:
mvn assembly:assembly
You will want to look into the Maven Assembly Plugin. And then once you have created the XML file required by the plugin and have modified your POM file to work with the plugin, you can run it with:
mvn assembly:assembly
This will create the JAR with all of its dependencies.

Categories