Manifest Classpath for Jar files - java

I created a small application which includes an external package called JavaFX. The package contains 4 jar file.
When I create a jar from the command line to the current directory, the jar executes OK (importing classes from the 4 jars). But when I move that jar file from a different directory, the file wont execute. In other words the created jar can't seem to locate the classes in those jar files (JavaFX jars) ?
Below is the manifest file:
Main-Class: QuizMenu
Class-Path:
deploy.jar
javaws.jar
jfxrt.jar
plugin.jar
The textfile does contain a space at the start and end of each line of the jars, and a final carriage return at the last line (Each line apart from the last line does not contain a carriage return). Also the Main-Class: header works OK. (Just the classpath doesn't seem to work).
Can anyone identify the problem with the file?

Recommendation
You should not refer to any of these (deploy.jar javaws.jar jfxrt.jar plugin.jar)
jar files in your mainifest file.
JavaFX Packaging Tools
Instead, you should use JavaFX aware deployment tools such as:
javafxpackager
JavaFX ant tasks
JavaFX maven plugin
JavaFX gradle plugin
NetBeans JavaFX project
Some other compatible tool which might come along in the future.
The above tools will appropriately package your application to use JavaFX.
Background
If you try to bundle the JavaFX, Java deployment and Java plugin jar files with your application, then when you run your application on a different Java version (such as Java 8 or 9), it may not function correctly as JavaFX in all future releases will be defined to be part of the Java runtime platform and not as a separately installed library or a library which can be bundled with an application separate from the rest of the Java runtime.
Additionally, jar files such a jfxrt.jar rely on numerous native dynamically linked libraries (.so, .dll, etc) which differ from platform to platform and have 32 bit and 64 bit variants. The version of jfxrt.jar must match the version of the underlying native libraries (and the underlying native libraries for the appropriate platform must be available to the dynamic load linker) in order for jfxrt.jar (e.g. JavaFX) to function correctly.

Related

Does the jmods directory in jdk/jmods have any role during application runtime?

I have an application which runs in a sandbox environment using an OpenJDK.
The JDK directory has a jmods folder.
The documentation regarding jmods isn't that great. From what I understand, jmods is useful if I want to create another custom JRE using JLink.
Say, if I don't want to do that and just want to have a JDK which can build and run my Java SWT application. Will it be safe to simply remove the jmods directory?
Does the jmods directory in jdk/jmods have any role during application runtime?
No. These are only archives that are used as input to jlink. The class files and other resources that are used during runtime are stored in the lib/modules archive, which is in a custom format that can be read for instance with the jimage tool. (or by JDK code using one of two jimage library implementations in the JDK)
.jmod files are not meant to be used during execution. If you try to put a .jmod file on the module path, you even get an error:
java.lang.module.FindException: JMOD format not supported at execution time: <some.mod>.jmod
Say, if I don't want to do that and just want to have a JDK which can build and run my Java SWT application. Will it be safe to simply remove the jmods directory?
If you use jlink to create a runtime image, it will not contain a jmods directory in the first place. So, there's nothing you should have to remove.

Customizing --module-path for Java

I created a javafx application via the IDE IntelliJ IDEA on ArchLinux. Now, I want to start this program without any IDE, so I created a .jar file. When trying to start the program with java -jar myprogram.jar, then I get the error message that runtime components for javafx are missing. Fine - I'll add these with the --module-path option, and it runs.
However, this --module-path thing only works somehow when I set the module path being somewhere in /lib/... On the other hand, when I try to copy the javafx modules into the folder where the myprogram.jar file is and set the module path there, the modules cannot be found.
My issue is the fact that I want to "self-contain" everything possible in one folder, such that I could copy&paste everything on another machine where the JVM is installed and just run it, and do not want to depend on the specific path where the javafx modules are installed. Maybe there is another way than to customize the --module-path?
Any help? Thanks :-)
Forget about trying to create a single executable jar that includes JavaFX components and depends on a pre-installed JVM (it is not a supported configuration).
However, cwellm's answer here details a method that keeps the modular JavaFX dependencies separate from the created application jar by keeping the JavaFX modules in separate jars added to the module path, I believe that this might be a valid and supported deployment configuration. It does require deploying multiple jar files to the client in the right locations in order for it to work. Another alternative would be to assume a distribution of the JDK such as liberica or corretto which can come with JavaFX included in the base JDK distribution, then you don't need to specify a module path for JavaFX as it will already be present in the default boot module path for the JDK.
Recommended Solutions
Instead create a runtime image using jlink, this can be done by (among other methods) using the openjfx maven plugin.
Or if you want an installer, use jpackage which can also (among other methods) be created using maven, see JPackageScriptFX as an example.
jpackage doesn’t create archlinux native packages. So if you want that, then jpackage wouldn’t be the thing to use. Instead you could use a maven assembly or tar call to create a zip or tar.gz of the jlink output, or use the pacman tool to create a native archlinux package of the same.
Or if you like gradle see the badass jlink and runtime plugins.
Using a build tool (maven or gradle) to include the JavaFX dependencies rather than relying a JavaFX sdk download is preferred IMO. Also, if possible, define a module-info. Then jlink can be used to create the required runtime from your app, it’s dependencies and the jre, as well as the execution script for the app, so that things are self-contained. Native packages in rpm or deb format created by jpackage takes this further. Installing apps packaged this way also ensures all required OS lib dependencies are correct.
If you want to understand more see the contextual info (FAQ section) in this answer:
How to create a standalone .exe in Java (that runs without an installer and a JRE)
It is possible to put several custom module paths into the command --module-path. It is important to really put in the full path of the required modules, including the filename of the module itself. For instance, let's assume I want to include the modules module1.jar and module2.jar for the execution of MyApplication.jar, and all of these files are put into the same folder, say /my/custom/folder. Then the command line command would look like this:
java -jar --module-path /my/custom/folder/module1.jar:/my/custom/folder/module2.jar --add-modules module1,module2 MyApplication.jar

where to put bouncycastle jar to have it be a crypto service provider with Java JDK?

I installed Java SE Development Kit 16.0.2 on Windows 10 and it looks like the Java binary was installed to C:\Program Files\Common Files\Oracle\Java\javapath.
I'd like to install BouncyCastle as a crypto service provider and to do so I guess I need to put the Jar file in the java-home/jre/lib/ext/ directory. There isn't a jre directory at C:\Program Files\Common Files\Oracle\Java\javapath nor is there a lib directory.
So where do I put the Jar file?
short answer: For every app you run, you set up the classpath explicitly. All you need to ensure is that the bouncycastle jar is inside.
But, isn't there a bootclasspath?
Yes; it contains things like java.lang.String. You can't change a JDK to have more on the bootclasspath than the standard set without hackery. You don't want this hackery.
What about the extension mechanism?
No longer exists.
What about the CLASSPATH environment variable?
A remnant of a bygone age. All java apps are started via launchers, IDEs or build tools that explicitly specify a classpath (in which case, CLASSPATH the env var is ignored), or by launching a jar, which defines its own classpath in its manifest, and again CLASSPATH is ignored. Java still supports the CLASSPATH environment variable. No app you ever run with a JVM should use it, though. Java supports java.util.Vector, even in jdk16. Doesn't mean you should use it.
But I want a java app I did not write to use bc.
That's generally not easily possible. We're back to some fairly specific hackery.
How do I make a jar that uses bc?
Look into how the Class-Path entry in jar manifests work. You can ship the bc jar in your zip file with your app (or have an installer), so that when you run your app it's in the same directory as your main app. All you'd need is Class-Path: thatbcjar.jar in your jar manifest and it'll be used (and that jar is resolved relative to the directory that the app jar is in, so this works no matter what the working directory is when you launch your java jar).

Java Netbeans GUI builder make executable jar

So, since the jar generated by Netbeans requires the lib folder that it also generates, how do I go about adding the lib folder to the generated jar and change the Manifest so that it launches without any command line usage?
..so that it launches without any command line usage?
If it has a GUI, launch it using Java Web Start.
JWS provides many appealing features including, but not limited to, splash screens, desktop integration1, file associations, automatic update (including lazy downloads and programmatic control of updates), partitioning of natives & other resource downloads by platform, architecture or Java version, configuration of run-time environment (minimum J2SE version, run-time options, RAM etc.), easy management of common resources using extensions..
Desktop integration: desktop shortcut & menu item on supported platforms - no more Command Line based launch!
See Enabling Java Web Start in the NetBeans IDE to get started.
Although there are many ways to do it, they mostly involve modification of the Ant build.xml. This is the best tutorial I've found so far. FYI, there are other SO questions that are very similar.
NetBeans IDE handles all these automatically.
New Project -> Java / Java Desktop Application
Press next, fill everything and also check "Use dedicated folder for storing libraries", press finish
Go to the Files view, double click build.xml and from the "Ant targets" list, find the "jar" target, right click "Run target".
This way the generated .jar file will contain all dependencies and have a manifest with the Main-Class set:
Manifest-Version: 1.0
Ant-Version: Apache Ant 1.8.1
Created-By: 1.6.0_26-b03 (Sun Microsystems Inc.)
Main-Class: desktopapplication1.DesktopApplication1
Class-Path: lib/appframework-1.0.3.jar lib/swing-worker-1.1.jar
Edited: this does not package libraries into the .jar, but puts them next to it in a separate lib. See #user845279
I ended up using ninjacave.com/jarsplice to compile it all (libraries included) into one executable jar. (I got an error with the background color being the default color even though I had set it to a different color, so I modified the code that jarsplice uses to launch your program using java rather than the path to java)

Create java application jar file in eclipse

I have created a java application in eclipse, wich needs comm.jar and jexcel.jar and .property files so i have added to libray. I want to make a jar file out of my java appliction, including the external jar files added to the appliction.
How can I do it? To run serialport programs I have copied win32.dll into java_home/bin and comm.jar into java_home/jre/lib and javax.comm.properties into java_home/jre/lib, but when delivering the product it should run only by needing the jre.
How can I solve this? Please help me.
Thanks in advance,
suma
Although your question is not totally clear I suggest using the Fat Jar Plugin should allow you to achieve what you want.
You can use File > Export > Executable Jar which includes all libraries. There is also a checkbox to generate an ant build file as well as the jar in order to customize it further (I for instance make all the paths relative and remove the main-class flag).
You have two "path" issues. The Java Classpath and the path from which dlls are loaded.
If you were using a Java EE app server or OSGi then controlling these paths is addressed by the respective runtimes. Both Java EE and OSGi are likely to be overkill for small projects.
In which case you are delivering:
Your application JAR
The dependent jars
The DLLs
I suggest that on installing your app you place these artefacts into a suitable directory structure, for example .../myapp/lib for the jars and .../myapp/bin for the dlls. Don't copy them into the infrastructure directories, for example the JRE lib and bin, or into Windows32 - that just leads to version nightmares and mysteries when someone installs a new jre.
Having got that structure, how to control the paths? For the classpath, look at the Manifest.mf file. tutorial
For the DLL path, I know of no good alternative to setting OS level environment variables ** before ** launching the JVM. Hence you need a little batch/shell script to launch your app, setting the PATH appropriately.
You can also check maven.
You can right click on the project and say "Export". Now select "Java" in tree of choices. Under that select "Jar File". It'll guide you through the process and will allow you to export you project as a jar file.
Hope thats what you are looking for.
The recently released Eclipse 3.5 has a Export as runnable Jar which allows to put all dependent jars in a subfolder to the jar file, and get the Manifest right.
It is an adaption of the FatJar plugin. Works nicely!

Categories