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.
Related
I am having an executable JAR. Ofcouser I have JDK installed at my end I am giving following command to run my exe JAR from command prompt.
1 Using JRE :-
C:\Users\userName\Desktop\Utility\latest>"C:\Program Files\Java\jre1.8.0_161\bin\java.exe" -jar Utility.jar
2 Using JDK
C:\Users\userName\Desktop\Utility\latest>"C:\Program Files\Java\jdk1.8.0_161\bin\javaw.exe" -jar Utility.jar
Both are working on my desktop but if I tries #1 to run the executable JAR on different machine which has only JRE Version (1.8 onwards) it is not getting opened up.
I tried following links but some links are sayin to download few installers but all I do not want to get that. Is there any way. Or issue with my executable JAR ?
How can I make my executable JAR not need JDK to run
Run a JAR file using a specific JRE
Manifest-Version: 1.0
Rsrc-Class-Path: ./ commons-collections4-4.3.jar poi-3.17.jar poi-ooxm
l-3.17.jar xmlbeans-3.0.1.jar curvesapi-1.06.jar poi-ooxml-schemas-3.
17.jar poi-examples-3.17.jar poi-excelant-3.17.jar poi-scratchpad-3.1
7.jar commons-codec-1.10.jar commons-collections4-4.1.jar commons-log
ging-1.2.jar curvesapi-1.04.jar junit-4.12.jar log4j-1.2.17.jar xmlbe
ans-2.6.0.jar ooxml-schemas-1.3.jar
Class-Path: ./ commons-collections4-4.3.jar poi-3.17.jar poi-ooxml-3.17.jar
xmlbeans-3.0.1.jar curvesapi-1.06.jar poi-ooxml-schemas-3.17.jar poi-examples-3.17.
jar poi-excelant-3.17.jar poi-scratchpad-3.17.jar commons-codec-1.10.jar
commons-collections4-4.1.jar commons-logging-1.2.jar curvesapi-1.04.jar
junit-4.12.jar log4j-1.2.17.jar xmlbeans-2.6.0.jar ooxml-schemas-1.3.jar
Rsrc-Main-Class: DataProcessor.DataProcessor.App
Main-Class: org.eclipse.jdt.internal.jarinjarloader.JarRsrcLoade
It sounds like the issue your are having is more than not having the JDK or knowing where the JRE on the target system is located, it's that you also didn't include the dependencies that your code has.
The jar file you have includes details in the manifest file that tells the JVM the classpath and the main class to load. If you look at the Rsrc-Class-Path, it is add the jars from the current directory. This is fine if you are sending the entire folder structure that includes all the jars in the expected location. But it doesn't work with just the jar.
In order to make a single jar that would run without any additional jars, you need to repackage the jars. There are two common ways to do this
UberJar - where the class of your project is combined with the classes extracted form all of your dependencies into a single jar
JarInJar - where your jar and all the dependecy jars are put into a jar and a custom classloader is used to load the classes from the jars inside the jar.
I'm not sure what build tool you're using, but for Maven the Shade Plugin will create an UberJar.
I personally recommend using the JarInJar option for this reason. The Spring Boot Maven Plugin is what I believe to the easiest
I have a jar that uses a manifest for some of its dependencies which are packed up into a jar using maven.
Is it possible to run the jar with both the internal packaged up jars, which are described in the manifest, and jars that I pass using -cp at application launch?
Or is it one or the other?
I have a Java project in Eclipse with class MainClass having main method in package :
com.nik.mypackage.
The project also references two external libraries, which I copied in the lib folder in Eclipse and then added to build path using ADD JAR function. The libraries being one.jar and two.jar
This library is in lib folder in eclipse and added to the build path.
I want to create a executable JAR of the application using ant script. So that user can access my application using command:
c:>java -jar MyProject-20111126.jar
I know about the Eclipse plugin which directly exports a java application as runnable JAR. But I want to learn ant and the build process so manually want to create the build.xm.
You have two options from your build.xml. You can either unjar the library jars and then bundle their contents with the code compiled for your application. Or, you can put the library jars on the filesystem and supply a ClassPath entry in the manifest file of the MyProject-2011126.jar file.
If you set the classpath in the manifest remember that the path you supply is relative to the MyProject-2011126.jar.
one alternative:
Instead of having only a jar, you build mutiple jars (your jar + libs) +batch file.
So, your built package can be like this structure:
-/package/bin/app.bat
/package/lib/my.jar
/package/lib/one.jar
/package/lib/two.jar
In app.bat you just have the same as your code
java -jar MyProject-20111126.jar
PS: if you want to start learning built tools, ANT may be a bit tool old. I suggest http://maven.apache.org/
Please try one-jar. It helps to redistribute everything packaged as single jar and comes with ant-task . See Easiest way to merge a release into one JAR file.
I have a Java project that utilizes Jython to interface with a Python module. With my configuration, the program runs fine, however, when I export the project to a JAR file, I get the following error:
Jar export finished with problems. See details for additional information.
Fat Jar Export: Could not find class-path entry for 'C:Projects/this_project/src/com/company/python/'
When browsing through the generated JAR file with an archive manager, the python module is in fact inside of the JAR, but when I check the manifest, only "." is in the classpath. I can overlook this issue by manually dropping the module into the JAR file after creation, but since the main point of this project is automation, I'd rather be able to configure Eclipse to generate properly configured JAR automatically. Any ideas?
*NOTE*I obviously cannot run the program successfully when I do this, but removing the Python source folder from the classpath in "Run Configurations..." makes the error go away.
Figured it out, had to add the source folder with the Python module in it as a class folder in the Build Path project properties. Not sure if this next part is necessary or not, but since the module is not compiled, I added the folder again as "Attached Source" after adding the class folder.
Have a look at the maven-jython-compile-plugin and its demo project at http://mavenjython.sourceforge.net/ . It allows bundling jython with dependencies into a standalone jar.
I have a Java application and created a JAR file and deployed it.
The App uses external JARs such as the Log4J JAR. When creating my JAR file, how do I include all external dependent JARs into my archive?
In order to get my App working, I'm having to copy the Log4J JAR into the same directory as my own JAR which kinda defeats the purpose of the jar. Wouldn't it be more elegant to have 1 single JAR file to deploy?
If you use Eclipse, You can extract all included files into one runnable jar like this:
Right click on your project name from Package Explorer and select Export.
In Export screen, select Java -> Runnable JAR file and Next.
Fill in the Runnable JAR File Spec screen and Finish.
You can choose whether to package dependency jars as individual jar files or extract them into the generated JAR.
You could use something like One-JAR to package your Java application together with its dependency into a single executable Jar file (One-JAR uses a custom classloader to make JARs nesting possible).
You have to expand the library jars into the same place where your compiled classes go, then make a jar from that. Depending on how your build process is set up, there may be multiple ways to achieve this. It's not rocket science - a jar is just a zip archive with a META-INF directory at the root level.
Keeping JAR separate is better as it is easy to upgrade only the specific JARs to its new versions without touching any other configuration. As of your issue of having to copy each file to same location as of your JAR, you can always use Java CLASSPATH and include any JAR to your application's class path.
A JAR is not itself capable of nesting other JARs, as you discovered.
Traditionally, one would distribute a ZIP archive or other installer that would unwind the application JAR (yours) as well as any support JARs in the appropriate location for classpath access. Frequently, then, the application was invoked through a script that invoked the primary JAR and created a classpath that listed the support JARs.
As other posters have noted, you have some options to create a super-JAR if that's what you want.
You can use Maven + assembly plugin (http://maven.apache.org/plugins/maven-assembly-plugin/)
BTW, probably that's not the easiest way, if you did not work with maven.