Inspired by a recent thread on e(fx)clipse user forum “Why some things don’t work out-of-the-box when using JavaFX instead of SWT”. I think its time to take a look at the current state of JavaFX 2.2 on OSGi.
The first thing we need to decide is which deployment strategy we want to use.
The 2 possibilities are:
- Make JavaFX 2.2 a prerequisit on the target system which requires your OS-X/Windows users to install OpenJDK7u6. For Windows users there’s another option because they can install the JavaFX-Runtime seperately
- Ship JavaFX 2.2 with your application as an OSGi-Bundle
The prerequisit deployment
A reason to follow this strategy could be for example that you want to keep your download size as small as possible. If you think this is not a problem then think about the following: If you want to ship only one application “binary” you’d have to package JavaFX 2.2 runtime (Java-Sources+Native libs) 6 times (Mac, Win32_x86, Win32_x86_64, Linux_x86, Linux_x86_64)!
Even even if you require your users to have Java7u6 installed which has the JavaFX-runtime co-installed the JavaFX binaries are not on the bootclasspath, nor are they exported by OSGi by default so your application will fail to start.
The only solution I have found and implemented so far is to Adaptor_Hooks in Equinox to dynamically locate the JavaFX-binaries.
As far as I’ve heard JDK8 will have the javafxrt.jar on the bootclasspath and so that I can be supported by OSGi-Implementations the same way they currently support the usage of swing.
Repackage JavaFX for OSGi deployment
Since 2.0 many problems with JavaFX on OSGi have been solved and so straight repackaging the javafxrt.jar as an OSGi-Bundle should work. One can use the Eclipse wizard to repackage the jar and afterwards only has to add the Bundle-NativeCode-Code header and the native code.
Now on first sight this works but there’s one big problem with this. The code in JavaFX which is detecting the native code follows those steps:
- Locate native code relative to javafxrt.jar if that fails
- Locate native in the java.library.path if that fails
The problematic part in the above strategy is the 2nd one.
Let’s suppose with have repackaged JavaFX 2.2 but the user has installed Java7u5 which has JavaFX 2.1 co-bundled your java.library.path looks like this.
C:\Program Files (x86)\Java\jre6\bin;C:\Windows\Sun\Java\bin;C:\Windows\system32;C:\Windows;C:/Program Files (x86)/Java/jre7/bin/client;C:/Program Files (x86)/Java/jre7/bin;....
Your application will not load the native code from your repackaged JavaFX-OSGi-Bundle (step 3.) but the native code inside your Java7u5 install which is the one from 2.1 which means your Java-Code (2.2) and Native-Code (2.1) won’t match.
Repackageing as a “deployment container bundle”
The approach here is that one repackages the javafxrt.jar and the native code as an OSGi-Bundle with a predefined name (e.g. javafx.osgi) but you don’t export any packages from it but see it only as a deployment unit. At runtime you once more use Equinox-Adaptor_Hooks but instead of locating the jar somewhere on the system you resolve your deployment container bundle and extract the DLLs and javafxrt.jar from there. If you used
"Eclipse-BundleShape: dir" you only have to detect the install location because the jar is already exploded.
Although it looks like the default approach to make use of JavaFX in OSGi would work (Straight Repackageing) fails when taking a closer look and this will not change until JavaFX 3.0 (shipped with JDK8).