Is it possible to create a JAR file that requires external dependencies without including those dependencies in the JAR file?
My google-fu has failed to give me an answer; everything that I have found shows how to include them in the JAR file, but not what to put in the manifest file to say "I haven't got them, look in the user's classpath". I would assume that the dependencies are properly installed and configured on the user's classpath.
In my case, my dependencies are Apache Commons CLI and Math.
Edit:
Inside my JAR file, I have Main.class.
My manifest file looks like:
Manifest-Version: 1.0
Created-By: 1.6.0 (Sun Microsystems Inc.)
Main-Class: Main
My CLASSPATH looks like
.;C:\Program Files\Java\jre1.6.0_06\lib\ext\QTJava.zip;C:\java_lib\commons-cli-1.2.jar;C:\java_lib\commons-math-2.0\commons-math-2.0.jar
If I include the dependencies in the JAR in /lib and add the line Class-Path: lib/commons-math-2.0.jar lib/commons-cli-1.2.jar to the manifest, then it does work.
I've tried adding Class-Path: commons-math-2.0.jar commons-cli-1.2.jar to the manifest without including the files in the JAR just to see if that would work, but it didn't.
Use the Class-Path entry in the META-INF/MANIFEST.MF to tell where to look for dependencies relatively to your JAR. For example:
Class-Path: servlet.jar ../foo/bar.jar acme/beans.jar
It certainly is possible. One way to think about it is that every time you create a jar, you are depending on the classes in the jre, and it is not necessary to include them in your jar. The jre will automatically look for them in the classpath. If they are not found you will see a NoClassDefFoundError.
Related
I have included 'ibmzjos' Jar file in java Build Path and jar file is included in Referenced Libraries. In MAINFEST.MF file mentioned the same.
Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: JavaProject
Bundle-SymbolicName: JavaProject
Bundle-Version: 1.0.0
Bundle-RequiredExecutionEnvironment: JavaSE-1.6
Import-Package: com.ibm.cics.server;version="1.300.0"
Bundle-ClassPath: Referenced Libraries/ibmjzos.jar,
.
CICS-MainClass: com.citi.cards.javaMain
In src all error were removed and code looks good. When I created a bundle and execute the program in mainframe server It's failed as "com.ibm.jzos cannot be resolved:".
How to resolve this issue?
EDIT: Updated to include specifics of including JZOS.
The problem here is that the JZOS classes cannot be found. I suspect this is because they're not actually included in your bundle.
To test this, unzip (or otherwise explore) the exported bundle (JAR file). According to your MANIFEST.MF, I would expect there to be a folder called Referenced Libraries in the root of the JAR, with a file called ibmjzos.jar inside that. However, I expect that it does not exist.
To fix this problem, you need to ensure that the Bundle-ClassPath is pointing to a real file. Note that Referenced Libraries is not a real folder, but rather a pseudo-folder that Eclipse places inside the project that shows what is being brought in on the build path.
Make sure ibmjzos.jar is inside the project, such as in the root of the project or in a folder named lib (I'll assume the latter).
Change the Bundle-ClassPath of your MANIFEST.MF so that it correctly points to this file:
Bundle-ClassPath: lib/ibmjzos.jar
Ensure that the bundle knows to include this JAR in your exported bundle by modifying the property that defines the exported files in the build.properties file:
bin.includes = META-INF/,\
.,\
lib/ibmjzos.jar
Note that steps 2-3, as well as adding the JAR to your build path so everything compiles in the IDE, can be automated by using the 'Add...' button in the 'Classpath' section of the 'Runtime' tab of your MANIFEST.MF editor.
As a further twist, JZOS is a special case because it's so useful on z/OS, and for that reason it's exported by the system bundle from CICS version 5.1 onwards. Therefore, there's not a need to include it in the Bundle-ClassPath, but instead you need to have Import-Package statements for the relevant packages - for example, you're using com.ibm.jzos. To make your IDE happy, you'll need to have a fake bundle in your development environment that exports those packages.
I am trying to send my jar file to other people without the need to send multiple jar files to a person for them to run my application. Is there a way to include a secondary jar file inside of my jar and have it as my Class-path instead of it being in my working directory?
This is my manifest for when i create the Jar.
Manifest-Version: 1.0
Main-Class: MultipleLinearRegression
Class-Path: Jama.jar
This is how I am creating my jar file
jar cvfm MyApplication.jar manifest.txt Jama.jar *.class
With Maven and the Shade plugin you can create an Uber JAR, containing all dependend JARs in one JAR file. There is also a Shade Plugin for Gradle. (If you don't use Maven or Gradle, you should really consider to do so.)
There is an interesting article here: Creating Executable Uber Jar’s and Native Applications with Java 8 and Maven
There are other similar tools like One-JAR.
for creating a jar file, we can follow these steps,
1) Class-Path: <lib1.jar> <lib2.jar> <path/lib3.jar>
2) Main-Class: <classname>
3) Place a new line at the end of this file
I am trying to build my application jar (non executable jar) with all it's dependenices jar files also to unpack.
Simply to explain my issue, in eclipse, to export runnable/executable jar, there is an option
"Extract required libraries into generated Jar"
Please help me the same option for non-runnable jar also.
Thanks
No there isn't.
Just as background: Packaging dependencies within a JAR file (sometimes called a fat jar or app jar) is not a native Java mechanism but is grafted on using custom ClassLoaders or start scripts packaged in the JAR.
If you create a runnable JAR file with Eclipse it uses a wrapper to run your application which can read the packaged libraries. You can see this if you open the exported JAR file and look at it's Manifest:
Manifest-Version: 1.0
Rsrc-Class-Path: ./ [removed]
Class-Path: .
Rsrc-Main-Class: com.example.Test
Main-Class: org.eclipse.jdt.internal.jarinjarloader.JarRsrcLoader
The JarRsrcLoader sits between your applications Main-Class and the Java Runtime and can then load the packaged dependencies before executing your code. In a library there is no such hook that Eclipse can hook into since the loading is done by someone using your library and you can't control the loading process.
There are mechanisms to combine JAR files into a single one by unpacking the dependencies and then repackaging them into your JAR. Look here for example: How to combine two Jar files
Note though that by repackaging a 3rd party JAR you might run into issues with signed classes or conflicting Metadata.
If you want to publish a library and/or manage dependencies properly I recommend looking into build systems like Maven (http://maven.apache.org/) or Gradle (http://www.gradle.org/). I personally much prefer Gradle.
Edit: This project seems promising: https://github.com/puniverse/capsule
Use Capsule. It does everything you want including set JVM configuration right in the manifest.
With capsule you have the option of packing all of your JARs and native libs right into the capsule JAR, or you can specify your Maven dependencies in the Manifest, and let them be downloaded the first time the capsule is launched.
I have seen this question asked a lot, but I still can't figure out a solution to it. Well a solution that works for me. I have a project that is using Apache POI, and I made sure to include all the external JARs. The project compiles and runs fine in eclipse but when I run the jar with "java -jar Test.jar" I get this error:
Exception in thread "main" java.lang.NoClassDefFoundError: org/apache/poi/ss/usermodel/Sheet
I'm not sure if this is useful information, but I created a lib folder for my project and put the poi library in there. This means that the dependcies are in the JAR file when I create it, I figured I should mention this because I saw a few solutions about just having your external jars right next to your executable jar. I also tried setting my classpath to the directory of the project.
What do I seem to be doing wrong?
The Apache POI JAR file is not on your runtime classpath. Rebuild Test.jar with the following manifest entry in the MANIFEST.MF file
Class-Path: poi-3.9-20121203.jar
When the java -jar [filename].jar command fails, it's almost always because of one of two things:
Your MANIFEST.MF is messed up and doesn't list dependencies properly. Make sure all jar dependencies in your manifest file point to jars, relative to your jar's parent directory.
You are missing .class files, either in your specific jar or in one you depend on. Ensure your jar contains org/apache/poi/ss/usermodel/Sheet.class or that your manifest hierarchy points to a jar that contains that class.
You will need to provide classpath in Jar file's manifest file. See this official doc
An Example
We want to load classes in MyUtils.jar into the class path for use in MyJar.jar. These two JAR files are in the same directory.
We first create a text file named Manifest.txt with the following contents:
Class-Path: MyUtils.jar
First check if your target jar (Test.jar) is a fat jar containing all the required dependencies.
$ jar tf Test.jar
You should see your lib/ folder there containing all the required dependencies (including Apache POI). If that's the case do what others suggested, add Apache POI to your MANIFEST.MF.
About having your jar dependencies in a separate folder, as you suggested, that's also possible. Imagine your dependencies where stored in a lib/ folder outside your Test.jar. You could run your code with this command:
$ java -cp ".:lib/*" org.Test.Main
It simply adds all the .jars within lib/ folder to your classpath. In this case you also need to specify the name of the main class (full name).
I also got this problem and tried to google it..
i have found out that i have to read the error log
I cant save my file to .xls so
in my case after reading the error i found that a jar file is missing
i just added the jar file poi-3.7-20101029 located in the ext folder of my ireport
ex.YourIReportFolder/ireport/modules/ext-poi.x.x-xxxx
hope this helps :)
I am in the final step of my application release and so creating jar, called App.jar. I have other jars on which App.jar is dependent, so I rather included it within App.jar. When trying to run, it works if App.jar is put into the folder of the main project. However, when put outside it (for example on the dekstop), it does not work completely, meaning that some GUi components are not displaying. My question is:
Besides other jars on which my App.jar is dependent, can it be dependent on some other files or under some other conditions?
EDIT:
I am working in Eclipse, to build jar I just exported it and chose the option "packaged required libraries into generated JAR", which put all the jars I need to run into App.jar. My MANIFEST.MF then looks like this:
Manifest-Version: 1.0
Rsrc-Class-Path: ./ JTattoo.jar plugin.jar docking-frames-common-1.1.1
-SNAPSHOT.jar jl1.0.jar swt-3.7M5-win32-win32-x86.jar worldwind.jar a
ccess-bridge.jar sunpkcs11.jar looks-2.0.1.jar tools.jar OfficeLnFs_2
.7.jar jce.jar jna_WindowUtils.jar dom4j-2.0.0-ALPHA-2.jar junit-4.5.
jar rt.jar mysql-connector-java-5.1.21-bin.jar sunmscapi.jar glasslib
.jar resources.jar jxl.jar dnsns.jar sunec.jar jogl.jar mp3spi1.9.4.j
ar docking-frames-core-1.1.1-SNAPSHOT.jar DJNativeSwing.jar tritonus_
share.jar dom4j-2.0.0-ALPHA-2-sources.jar zipfs.jar MozillaInterfaces
-1.8.1.3.jar jfr.jar DJNativeSwing-SWT.jar gluegen-rt.jar jaxen-1.1.1
.jar gdal.jar localedata.jar jna-3.2.4.jar charsets.jar sunjce_provid
er.jar jsse.jar jaccess.jar
Class-Path: .
Rsrc-Main-Class: org.cnstar.wiki.app.GreatPlaces
Main-Class: org.eclipse.jdt.internal.jarinjarloader.JarRsrcLoader
SplashScreen-Image: images/splash_screen.png
You should set the classpath properly to include all the jars required.
Yes there can be more jars dependency due to transitive dependency. Your App.jar may be dependent on a jar, which may be dependent on another jar. Using Maven you can be away from all such worries as it automatically downloads all the dependencies.