10 Minute JavaFX Tutorial - Develop and deploy JavaFX Applets and Applications while online and offline
Hello! and welcome back to another JavaFX tutorial. Today, I will walk you through deploying a JavaFX application as an applet in the browser and through Java Webstart. Additionally, I will to point you to a method and provide sample code for developing JavaFX applications offline. Instead of writing a new application, I will continue to use the “Hello, World!” application we wrote in the 10 Minute Tutorial - JavaFX: Hello World article.
Before I begin, I have both some good news and some bad news about this tutorial. The bad news first: due to a disgusting lack of documentation, this tutorial caused me plenty of plenty of headaches. I experienced moments when I almost threw my hands up in surrender and at other times, just caught my fist as it reflexively tried to pucnh a hole through my monitor. But, the good news: you shall benefit from my pain. I hope to provide you with enough information so that you won’t experience any of the issues I did and your JavaFX applications will deploy correct the first time…and every time after.
So, let’s get started!
Prerequisites
- All the prerequisites defined in 10 Minute Tutorial - JavaFX: Hello World.
- The Java SE Development Kit (JDK) 6 Update 11.
QuickStart
If you want to see the end result of this tutorial and you have installed all the prerequisites, then please download the ZIP file below, unzip it and open the helloworld-applet-online.html file in your browser. You should see text that says “Hello World” in the upper left corner.
- Hello World Deploy Sample (you may read this software’s license here)
If you want to see the sample in action right now, use the links below:
- Hello World JavaFX applet
- Hello World JavaFX Webstart application (you may need to save the JNLP file first, then open it)
Lesson
Step 1: Create the application JAR file
JavaFX applets and JavaFX Webstart applications expect your code to reside in a JAR file. So, we to put the code written in 10 Minute Tutorial - JavaFX: Hello World into a JAR file. As a refresher, I will post the code, stored in a file named “HelloWorld.fx”, in full here:
import javafx.scene.Scene;
import javafx.scene.text.Font;
import javafx.scene.text.Text;
import javafx.stage.Stage;
Stage {
title: "Die, Ajax! - Hello World"
width: 250
height: 50
scene: Scene {
content: [
Text {
content: "Hello World!"
x:0
y:12
font: Font {
name: "Sans Serif"
size: 12
}
}
]
}
}
Just like Java, JavaFX uses the concept of “packages” in order to organize code. As of right now, this code resides in the “default” package, since it lacks a package declaration. Typically Java develoeprs frown on this practice, especially when deploying the code inside a JAR file. So, let’s add a package delcaration to the top of the file:
package hello;
import javafx.scene.Scene;
import javafx.scene.text.Font;
import javafx.scene.text.Text;
import javafx.stage.Stage;
Stage {
...
Now, to compile the code. We will use a slightly different command than the last time:
"C:\Program Files\JavaFX\javafx-sdk1.0\bin\javafxc.exe" -d . HelloWorld.fx
The “-d” command line option tells the compiler to create directories for the packages defined in the class files. So, the result of running this command creates a directory called “hello” in our current working directory and puts the compiled version of HelloWorld.fx source code into it.
Remember, I provide full paths to executables in my examples, but you will not need to use full paths if you put the commands in your PATH variable. Also, if you installed JavaFX or Java in a different place besides the default directories, then you will need to change paths accordingly.
Now, use the “jar” command, which ships with the Java JDK, to put those classes in a JAR file:
"C:\Program Files\Java\jdk1.6.0_11\bin\jar.exe" cvf HelloWorld.jar hello\HelloWorld*.class
This command makes a JAR file out of the compiled files in the “hello” directory created during compilation. Note, as the last parameter to the command, we pass a wild card that tells the JAR command to pick up all the “.class” files in the directory which start with the characters “HelloWorld”.
We will use this JAR file throughout the rest of the tutorial and deploy it both as an applet and through Java Webstart.
Step 2: Create the HTML
Deploying this application as an applet in the browser requires some sort of HTML file to host it. So, create a file named “helloworld-applet-online.html” and put this code in it:
<html>
<head>
<title>Hello World Applet</title>
</head>
<body>
<script src="http://dl.javafx.com/dtfx.js"></script>
<script>
javafx(
{
archive: "HelloWorld.jar",
draggable: true,
width: 150,
height: 100,
code: "hello.HelloWorld",
name: "HelloWorld"
}
);
</script>
</body>
</html>
The first <script> element points to a Javascript file named “dtfx.js”, which lives on Sun’s servers. This file contains (or imports) all the code necessary to detect whether the user’s systems runs the correct version of Java to allow your application to work, and also create an <applet> tag for you via the javafx function, called in the next <script> block. The javafx function will spit out a correct <applet> tag based on the parameters you pass in. If you use Firebug, you can see what this <applet> tag looks like. I have posted an example below:
<applet width="150" height="100" archive="HelloWorld.jar,
http://dl.javafx.com/applet-launcher__V1.0.0.jar,
http://dl.javafx.com/javafx-rt__V1.0.0.jar,
http://dl.javafx.com/jmc__V1.0.0.jar,http://dl.javafx.com/Decora-SSE__V1.0.0.jar,
http://dl.javafx.com/Decora-HW__V1.0.0.jar,
http://dl.javafx.com/Decora-D3D__V1.0.0.jar,
http://dl.javafx.com/emptyJarFile-1229491715375__V1.0.0.jar" code="org.jdesktop.applet.util.JNLPAppletLauncher" mayscript=""/>
If, like me, you haven’t dealt with the <applet> tag in many, many years, then you may want to refresh yourself on its attributes. Basically, you can see that it downloads all the necessary JARs, both our own (HelloWorld.jar) and the ones needed for JavaFX.
If you look closely at the “code” attribute of this <applet> tag, then you will see that it uses a class named JNLPAppletLauncher. This class appears to have come out of the javadesktop project and according to the site it is “a general purpose JNLP-based applet launcher class for deploying applets that use extension libraries containing native code. It allows applets to use extensions like Java 3D, JOGL, and JOAL very easily, with just a few additional parameters to the <applet> tag, on Java SE versions as far back as 1.4.2.”. So, this class allows JavaFX to do cool things like access your 3D hardware (for Windows developers, that “Decora-D3D__V1.0.0.jar” file should pique your interest
). But, it also means, we will need to create a JNLP file for our applet.
So, let’s do it.
Step 3: Create the browser JNLP file
If you’ve never created a JNLP file before, it stands for Java Network Launching Protocol and it basically allows you to launch a desktop Java application from a URL. It really sits at the core of the Java Webstart technology architecture. So, given that JavaFX leverages both applets and Java Webstart, hopefully, it has begun to dawn on you that JavaFX blends the best of applets (running in a browser) with the best of Java Webstart (access to native libraries).
Fortunately, the JNLP syntax remains pretty straight forward even for the uninitiated. Create a file named “HelloWorld_browser.jnlp” and put this code in it:
<?xml version="1.0" encoding="UTF-8"?>
<jnlp spec="1.0+">
<information>
<title>Hello World</title>
<vendor>Acme Corporation</vendor>
<description>Hello World Applet</description>
</information>
<resources>
<j2se version="1.5+"/>
<jar href="HelloWorld.jar" main="true" download="eager"/>
<extension name="JavaFX Runtime" href="http://dl.javafx.com/javafx-rt.jnlp"/>
</resources>
<applet-desc main-class="com.sun.javafx.runtime.adapter.Applet" name="HelloWorld" height="200" width="200">
<param name="MainJavaFXScript" value="hello.HelloWorld"/>
</applet-desc>
</jnlp>
I highlighted the elements of most interest. The <jar> element points to our JAR file and tells the JNLP Client (i.e. the browser plug-in) to completely download it as soon as possible. Next, the <extension> element makes the browser plug-in download the necessary components (additional JAR files) needed to run JavaFX applications. Jumping down to the <applet-desc> tag, in its “main-class” attribute it takes an class that derives from java.applet.Applet named com.sun.javafx.runtime.adapter.Applet, which one could assume represents an applet specifically tailored for JavaFX. Finally, the <param> element underneath points to the full class path of our JavaFX class.
You probably noticed some duplication between this JNLP file and the <applet> tag described in Step 2. And if you look at the JNLP file at http://dl.javafx.com/javafx-rt.jnlp, you can see it contains some of the same JARs as the <applet> tag. I confess not truly knowing what overlaps where and why. Perhaps multiple systems, not quite intended to talk to each other, need the duplication as a sort of “XML glue”. I suppose any duplicate downloads get cancelled out by the Java Plug-in JAR cache, so it doesn’t concern me…much.
Go ahead and open the “helloworld-applet-online.html” file. A JavaFX applet should load and print “Hello, World!” in the upper-left corner of the browser.
Note, the JavaFX load time leaves much to be desired, so it may take a while for you JavaFX applets to render the first time.
Now, for Java Webstart.
Step 3: Create the desktop JNLP file
As I stated early, JNLP sits at the core of Java Webstart, so launching a desktop JavaFX application through Java Webstart simply requries a similar, but different JNLP file than the one we used for the applet. Open a file named “HeloWorld.jnlp” and put this code in it:
<?xml version="1.0" encoding="UTF-8"?>
<jnlp spec="1.0+" codebase="file:/C:\Documents and Settings\David Miles\My Documents\javafx\deploy-hello-world">
<information>
<title>Hello World</title>
<vendor>Acme Corporation</vendor>
<description>Hello World Webstart</description>
</information>
<resources>
<j2se version="1.5+"/>
<jar href="HelloWorld.jar" main="true" download="eager"/>
<extension name="JavaFX Runtime" href="http://dl.javafx.com/javafx-rt.jnlp"/>
</resources>
<application-desc main-class="hello.HelloWorld"/>
</jnlp>
I highlighted the parts different from the JNLP file created in Step 3. The “codebase” attribute added to the <jnlp> element points to the base directory for all relative paths specificed in “href” attributes (i.e. the “href” attribute in the <jar> element). When you officially deploy your code, this will point to a directory on your web server using the “http://” protocol. For now, go ahead and change this path to the absolute directory of your current working folder (unless your name is “David Miles”
).
Additionally, the <application-desc> element replaces the <applet-desc> applet, which makes sense. And, the “main-class” attribute gives Java Webstart the full class path of the main JavaFX class to load.
Of course, every Java Webstart application needs an HTML file, so…
Step 3: Create the Java Webstart HTML file
Open a file named “helloworld-webstart.html” and put this code in it:
<html>
<head>
<title>Hello World Webstart</title>
</head>
<body>
<a href="HelloWorld.jnlp">Hello World Webstart</a>
</body>
</html>
Not very difficult at all. When you click on this link, your browser should ask you to download/open the JNLP file. Once you open it, you should see a window containing the “Hello World!” text.
If when you click on the link, it just opens the raw JNLP file in your browser, try downloading the file first (doing a right-click, “Save As”) and then running the JNLP file once it finishes downloading.
Now we know how to deploy JavaFX applications on the desktop (discussed in 10 Minute Tutorial - JavaFX: Hello World), through Java Webstart and as an applet. So, we can all go home, right?
Not quite :).
I quickly want to discuss one more potentially useful technique.
Step 4: Develop JavaFX applets and applications offline
Both the versions of the JNLP files and the applet declaration reference files found at “dl.javafx.com”. But, if you don’t always have Internet access, you will not be able to download the necessary files, preventing you from developing JavaFX applications. To fix this, Thomas Ng wrote up a series of steps explaining how to develop and run JavaFX appications and applets offline. I won’t re-print them here, but his instructions basically tell you to remove the direct references to “dl.javafx.com” from the Javascript files and download all the necessary JavaFX runtime files to the Java file cache. When you have all the JavaFX runtime files cached, you should see them under “Resources” in the selection in the Java Cache Viewer, reached by opening the Java Control Panel and viewing you temporary files. The JAR files cached should look similar to the JAR files declared in the <applet> tag in Step 2. It might help to clean the cache first.
If you don’t want to edit the files yourself, you can download my JavaFX Hello World sample code which contains edited versions of the files. You’ll want to start by looking at the “helloworld-applet-offline.html” file in that archive.
After you make the necessary changes, disconnect from the network, and turn on full logging in the Java console, you will see something like this message, when loading the JavaFX app:
Validating file:/C:/Documents%20and%20Settings/David%20Miles/My%20Documents/javafx/deploy-hello-world/HelloWorld.jar , version null...
JNLP JREDesc in Component ignored: http://dl.javafx.com/javafx-rt.jnlp
I assume the “Component ignored” message means Java pulled from the cache rather than downloading the JavaFX runtime files again.
While this technique allows you to work offline, I would venture a guess that Sun decided to host the Javascript files for a reason. It allows them to easily upgrade the Javascript code and have all JavaFX applications in the wild benefit. So, if you employ this technique, keep in mind that your Javascript files may get out of sync with Sun’s at some point.
Update
A few weeks after I writing this tutorial, I learned about one more command line tool to help build JavaFX applications. The SDK ships with an executable named “javafxpackager” (in the C:\Program Files\JavaFX\javafx-sdk1.0\bin folder by default for JavaFX 1.0 on Windows). I haven’t found much documentation on it, but if you simply run this program, it will print out and describe all its avaiable options. It can build this HelloWorld application in one line:
javafxpackager -src "C:\Documents and Settings\David Miles\My Documents\javafx\deploy-hello-world" -appClass hello.HelloWorld -draggable
Your directories may vary.
This command creates the four necessary files: the HTML file, the browser JNLP, the Webstart JNLP and the code JAR and adds them to a new directory named “dist”. The automatically generated JNLP files deserve some scrutiny; they enable more, potentially undesirable options than in bare bones JNLP in this tutorial. Speaking of which, although creating JNLPs by hand provides an excellent learning experience, I don’t doubt that Sun recommends using the javafxpackager tool, if only to keep developers in sync with any updates to the deployment process.
Conclusion
This tutorial probably didn’t look too tough, but believe me I suffered plenty, and spent long hours staring at a spinning Java logo wondering why my JavaFX applet wouldn’t load. So, I want to breifly share some trouble shooting tips with you before I leave.
The spinning Java logo of death
If you get the spinning Java logo of death, and you have the correct version of Java installed and given the Java runtime plenty of time to startup, then go ahead and check the Java console (in Windows, I do this by right-clicking on Java icon in the System tray and selecting “Open Console”. When I did this, I found myself frequently getting this error:
exception: null.
java.io.FileNotFoundException: JNLP not available: HelloWorld_browser.jnlp
at sun.plugin2.applet.JNLP2Manager.loadJarFiles(Unknown Source)
at sun.plugin2.applet.Plugin2Manager$AppletExecutionRunnable.run(Unknown Source)
at java.lang.Thread.run(Unknown Source)
Exception: java.io.FileNotFoundException: JNLP not available: HelloWorld_browser.jnlp
It kept saying “java.io.FileNotFoundException: JNLP not available: HelloWorld_browser.jnlp”, even though I knew full well that file existed. However, when I turned on full tracking (according to the instructions, pressing the ‘5′ key while in the Java Console), and then tried to reload the applet, it gave me fulll-blown stack trace that helped me discover the problem. In one case, I created an applet JNLP file using code from a NetBeans-generated JNLP file. Of course, the NetBeans file had an invalid “codebase” attribute (you’ll notice that the JNLP file I created in Step 3 has none) and also had an “href” attribute that pointed to a JNLP file which didn’t exist. Once I removed those, it worked. (Note, familiarity with the JNLP Syntax can help immensely in troubleshooting JavaFX applet load problems).
Of course, had Sun made the exception a bit clearly, that would have helped immensely, too.
It also helps to frequently clean the cache when working with JNLP files that constantly change because Java likes to cache those JNLP files. I tried to turn caching off completely, but the Java runtime got mad at me and said Java Webstart applications won’t work without it…which, of course, makes sense.
One man’s pain is another man’s pleasure…or something like that. :). In any case, I hope you benefit from this tutorial, and stay tuned for more JavaFX goodness.
Related Posts:
Comments
3 Responses to “10 Minute JavaFX Tutorial - Develop and deploy JavaFX Applets and Applications while online and offline”




You are right about the JNLP exception messages. At best, they are opaque and are more likely to be simply misleading. Great tutorial. Thx.
[…] Vote 10 Minute JavaFX Tutorial - Develop and deploy JavaFX Applets and … […]
[…] Develop and deploy JavaFX Applets and Applications while online and offline - After posting this tutorial on dzone over a month ago, I received some very positive feedback. Recently, I updated it to include information about the “javafxpackager” tool that ships with the JavaFX SDK. […]