Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Deploying a JavaFX 2 application with referenced jars, using Ant

I have written a JavaFx 2 application (using Eclipse on a Windows platform) and now I want to deploy it to a "clickable" jar-file. My application uses resource-code from a separate jar-file (in Eclipse, this resource code is a separate Project from the JavaFx application project).

With my Ant build.xml, I have compiled the code for both the application and the resource code and created two jar-files:

  1. fxdemo.jar - A jar for my JavaFx application code
  2. guifw.jar - A jar for the resource code referenced by the JavaFx application.

As a last step (I thought), using the JavaFX Ant tasks, I wanted to bundle these two jar-files to a "clickable" jar that starts my JavaFX application. I tried doing just that with the below extract from my build.xml.

<target name="deployFx" depends="fxdemo.jar" description="Releases FxDemo">
    <taskdef resource="com/sun/javafx/tools/ant/antlib.xml"      
              uri="javafx:com.sun.javafx.tools.ant"
              classpath=".:${fxgui.javaHome}\lib\ant-javafx.jar"/>

    <copy file="${fxgui.lib_guifw_path}" tofile="delivery/lib/guifw.jar"/>          

    <fx:application id="FxDemoGUI" name="Fx Demo GUI" MainClass="com.demo.main.MainGUI"/>

    <fx:resources id="jars">
        <fx:fileset dir="delivery/lib" includes="fxdemo.jar"/>
        <fx:fileset dir="delivery/lib" includes="guifw.jar"/>
    </fx:resources>

    <fx:jar destfile="deploy/fxDemoGui.jar">
        <!-- Define what to launch  -->
        <fx:application refid="FxDemoGUI"/>

        <fx:platform javafx="2.1+">
            <fx:jvmarg value="-Xms32m"/>
            <fx:jvmarg value="-Xmx32m"/>
            <property name="com.util.fxguifw.setup" value="com/util/fxguifw/demo/demo.properties"/>
            <property name="user.language" value="en"/>
            <property name="user.country" value="GB"/>
            <property name="CSS_ID" value="NIGHT"/>
        </fx:platform>

        <fx:resources>
            <fx:fileset dir="delivery/lib" includes="fxdemo.jar"/>
            <fx:fileset dir="delivery/lib" includes="guifw.jar"/>
        </fx:resources>

        <manifest>
            <attribute name="Implementation-Vendor" value="${fxgui.vendor}"/>
            <attribute name="Implementation-Title" value="${fxgui.title}"/>
            <attribute name="Implementation-Version" value="1.0"/>
        </manifest>

        <fileset dir="delivery"/>

    </fx:jar>

However, afterwards when I try to start the application (by either clicking the jar or starting from command line with java -jar appname.jar) it seems as the application can not find the Main class:

JavaFX Launcher Error

Unable to find class: com.demo.main.MainGUI

C:\Program Files\Java\jdk1.7.0_09\bin>java -jar C:\MEKMAN\Clearcase_Views\wmarekm_ss_gambau\amb_c2_prototype\javafx\prototypeGUI\deploy\fxDemoGui.jar
java.lang.ClassNotFoundException: com.demo.main.MainGUI
    at java.net.URLClassLoader$1.run(URLClassLoader.java:366)
    at java.net.URLClassLoader$1.run(URLClassLoader.java:355)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.net.URLClassLoader.findClass(URLClassLoader.java:354)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:423)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:356)
    at java.lang.Class.forName0(Native Method)
    at java.lang.Class.forName(Class.java:264)
    at com.javafx.main.Main.getAppClass(Main.java:506)
    at com.javafx.main.Main.launchApp(Main.java:622)
    at com.javafx.main.Main.main(Main.java:805)

When I studie the created MANIFEST.MF (in the created jar-file) it looks pretty much as what I expected.

Manifest-Version: 1.0
JavaFX-Version: 2.1+
implementation-vendor: MyVendor
implementation-title: MyfirstJavaFxDeploy
implementation-version: 1.0
JavaFX-Application-Class:com.demo.main.MainGUI
JavaFX-Class-Path: fxdemo.jar guifw.jar
Created-By: JavaFXPackager
Main-Class: com/javafx/main/Main

... but then again, it doesn't work so obviously I have done something wrong.

I also tried including the classes-directory (the output folders from each of the two Eclipse/projects) by adding:

<fileset dir="../guifw/classes"/>
<fileset dir="classes"/>

Then, the launcher does find my main class (com.demo.main.MainGUI) but failes to run correctly because it lacks the -D argument that I tried to specify with:

<property name="com.util.fxguifw.setup" value="com/util/fxguifw/demo/demo.properties"/>

So, if you have read this far, my questions are:

  1. Why can't the launcher find my main class in the referenced jar (fxdemo.jar)?
  2. What have I done wrong when it comes to specify my -D arguments to the application?

Best regards

like image 861
Förgöraren Avatar asked Nov 28 '12 11:11

Förgöraren


1 Answers

I studied/tested the fix presented in post (2012-apr-12 03:32) in the link from @Anders Petersson:

Link from @Anders Petersson

From what I can see, this is a workaround that unbudles any used jar-file (in my case; guifw.jar & demofx.jar) within the resulting jar file (fxDemoGui.jar), much like adding the classes-folders from my two Eclipse-projects (as described in the question).

I adjusted the example to my build.xml and got it to work after one slight addition:

<target name="dist" depends="fxdemo.jar">

    <taskdef resource="com/sun/javafx/tools/ant/antlib.xml"      
                              uri="javafx:com.sun.javafx.tools.ant"
                              classpath=".:${fxgui.javaHome}\lib\ant-javafx.jar"/>

    <copy file="${fxgui.lib_guifw_path}" tofile="delivery/lib/guifw.jar"/>

    <fx:jar destfile="predeploy/fxDemoGui.jar">
        <!-- ADDITION -> Adds the Launcher's Main class to the resulting jar (com.javafx.main.Main)! -->
        <fx:application id="FxDemoGUI"
                        name="Fx Demo GUI"
                        mainClass="com.demo.main.MainGUI"/>

        <fileset dir="delivery"/>
    </fx:jar>
</target>

In the dist-target from the example, I had to add:

<fx:application id="FxDemoGUI"
                name="Fx Demo GUI"
                mainClass="com.demo.main.MainGUI"/>

Without it, the resulting jar-file did not have the necessary com.javafx.main.Main-class and hence, failed to start.

So, this solution presents a useful workaround for my question 1)

Still, I'd be grateful if anyone comes up with a solution on how to keep the jar-files intact within the resulting jar/file.

like image 156
Förgöraren Avatar answered Sep 21 '22 19:09

Förgöraren