Below is my Jar structure. This is standalone jar.
MyApp.jar
--> .settings
--> com
--> lib
--> META-INF
--> resources
--> .classpath
--> .project
I am attempting to execute this jar file from bat file.
I have mentioned classpath and main class in MANIFEST.MF file under META-INF folder from MyApp.jar
Manifest-Version: 1.0
Class-Path: ./lib/jar1.jar ./lib/jar2.jar ./lib/jar3.jar
Main-Class: com.bank.Main
Inside my bat file:
java -jar D:\app\MyApp.jar
Is it correct way to lib folder inside jar?
But still i am facing ClassNotFoundException.
Exception in thread "main" java.lang.NoClassDefFoundError: javax/jms/JMSException
Anything i missed out Please advise me.
Put the lib folder outside of your current main jar [MyApp.jar] directory and execute it.
You have packaged the jar dependency inside your main jar. The intention of Class-Path is to add an external jar to the classpath, with the path relative to the location of the main jar.
Packaging a jar within a jar is not supported by standard Java classloaders. If you want, you can explode the inner jar into the main jar, though. Maven can do this for you.
Fat jar is not supported in Java by default. There are two options.
You can define a custom class loader which has to load jars inside lib directory programmatically.
You can manually merge all packages of jars inside lib directory to make a one jar and run it. Refer [https://dzone.com/articles/java-8-how-to-create-executable-fatjar-without-ide ]
Related
In my project I have this code that tell class loader to load Driver.class like so:
Class.forName(org.gjt.mm.mysql.Driver);
In Eclipse it runs with no problems and I have created the Jar file of the project. But I don't know how to insert the
mysql-connector-java-5.1.7-bin.jar
into a Jar file of my project. The folder structure look like this:
MANIFEST file:
Manifest-Version: 1.0
Main-Class: server.MultiServer
I am assuming that you finally just want to run your code as
java -jar myjar.jar
There are two options.
Keep mysql-connector-java-5.1.7-bin.jar next to your jar in the same folder and add classpath: mysql-connector-java-5.1.7-bin.jar to the manifest.
Copy all the classes in mysql-connector-java-5.1.7-bin.jar to your jar. Do not copy the jar but the classes in the jar. This is called a fat jar or uber jar. You can automate the same using maven shade plugin.
When you invoke your application jar add the -cp or -classpath option and provide the path to the dependent libraries, here the mysql-connector-java-5.1.7-bin.jar.
for example refer the below example
java -jar -classpath C:\myproject\lib\mysql-connector-java-5.1.7-bin.jar myproject.jar
I have a executable jar containing an embedded Tomcat which is created thanks to tomcat7-maven-plugin: tomcat7:exec-war.
I need to provide an additional classpath for some Jar because I cannot include them directly in my executable Jar. How can I provide this classpath ?
I cannot execute export CLASSPATH before I launch my executable Jar because catalina.sh/.bat erase the CLASSPATH value.
I cannot provide a setenv.sh/.bat because the executable Jar is created by the maven plugin.
I cannot update property common.loader from catalina.properties because I don't have control on this file which is generated by maven plugin.
Note: I don't want to specify a hardcoded path to the lib in the executable Jar.
Actually whatever jar files are inside WAR file at WEB-INF/lib are in classpath for WAR file classloader.
So, you can package your additional jar into war.
I'm not familiar with maven tomcat plugin, but just look to its options. It must have ability to put additional jars into war file (maybe just through dependencies in compile or 'runtime` scope. It is a standard feature.
If your additional jar must be outside of war you have to give it in system classpath for Java when you run your executable jar (through -cp parameter, I guess). Or you can define path to it in the MANIFEST.MF file of your jar.
The structure of my first app is simple:
libs
opencsv-3.8.jar
yamlbeans-1.0.jar
out
artifacts
...
production
...
src
META-INF
MANIFEST.MF
pl.krzysiu
App.java
CsvReplacer.java
Everything is fine during the compile and running the program. After building artifact jar file in the default out\artifacts directory, I get
java.lang.NoClassDefFoundError: net/sourceforge/yamlbeans/YamlException
when I try to run it by java -jar CsvReplacer.jar command
The libraries are included inside the jar file (they are there after unpacking it) - they are added to Libraries section in Project Structure (separately - one file per one lib), the whole libs dir is included in the Dependencies tab of Modules section (with export checkbox checked) and the libs dir is added in Output Layout of Artifacts section similarily.
The manifest file contains:
Manifest-Version: 1.0
Class-Path: libs\yamlbeans-1.0.jar libs\opencsv-3.8.jar
Main-Class: pl.krzysiu.App
Why the libs aren't visible for the App? If I copy this dir manually to the CsvReplacer.jar file's location - everything works fine.
The structure inside CsvReplacer.jar file looks like:
libs
opencsv-3.8.jar
yamlbeans-1.0.jar
META-INF
MANIFEST.MF
pl
krzysiu
App.java
CsvReplacer.java
IDE: Intellij IDEA 2016.3
The standard Java classloaders cannot find a JAR file embedded inside another JAR file.
You have two choices when making an executable JAR with dependencies.
Create a so-called uberJAR file by merging the contents of the dependent JARs into your main JAR.
References:
IntelliJ IDEA export Runnable program as Uber Jar
https://blog.jetbrains.com/idea/2010/08/quickly-create-jar-artifact/
Give your JAR a "Class-Path" manifest attribute to tell it where the (external!) dependent JARs are located.
You can't give a -cp and a -jar option together. But another alternative would be to get rid of the -jar option and use a -cp argument to specify the classpath.
Alternatively, you could implement a custom classloader that can load from a jar inside a jar, or use something like one-jar or Spring Boot.
My java project uses javax.mail.jar. So, in netbeans, I created a new folder Libraries, copied the jar file there and added this in project properties. I added this folder to git and this runs fine on netbeans. But when I build the project with ant on another machine and run the project jar with
java -jar myproject.jar
I get the error
Exception in thread "main" java.lang.NoClassDefFoundError:
javax/mail/MessagingException
I can see that myproject.jar contains the dependent library
$jar tf TakServer.jar
Libraries/
Libraries/javax.mail.jar
...
I'm not sure what is going wrong. Any idea how to get it to run?
Solution: As #Gimby pointed out, the jar files from Netbeans and ant build are different. Netbeans includes a lib/ folder containing all dependencies in dist/ folder and its MANIFEST.ML adds lib/ to classpath. The Libraries folder inside the main jar is not used at all.
The ClassPath in the manifest points to the filesystem outside the jar.
It it not possible to use jars inside jars
https://docs.oracle.com/javase/tutorial/deployment/jar/downman.html
I am using Java Simple Plugin Framework. I export a jar that has my plugin implementation. The implementation depends on a library, which I have as a jar. That jar gets exported within the lib directory of my jar, and added to the classpath of my jar.
But when I load my jar with JSPF, it fails with "NoClassDefFound" because it can't find the jar in the lib director of my jar.
My apologies if my approach off base; I just need to know how this is supposed to be done. How should I bundle my plugin implementation as a jar if it depends on another jar?
I used JSPF and achieved this requirement the following way:
place the library jar file in a folder called lib outside the plugin jar file. (So that
the lib folder and the plugin jar file is in the same folder). Then I added lib/"name_of_libjar" to the classpath entry in the manifest.mf file of the plugin jar file (Which should be inside the plugin jar files META-INF folder), and it worked fine for me.