One of the weird things I ran into when I first started trying to get JRubyFX to work with JavaFX‘s packaging tools, was that the packager would create these WebStart files and no matter what I tried, I couldn’t seem to get them working. Usually there was no error message, or something very cryptic.
I knew people had gotten JRuby apps working with WebStart before, so I didn’t think it would be impossible to accomplish, but ultimately went with a strategy of just removing the WebStart files after they were generated, as part of JRubyFX’s build task.
But I was persistent. What I ultimately hit upon was this article from March 2008, which mentioned that because JRuby uses reflection internally, the .jar had to be signed, and the .jnlp needed a setting requesting a higher level of security.
The next problem I ran into was that the webstart files created by the javafx packager make sure that there is a copy of the JavaFX library available for the application to use. JRubyFX apps need that library too, of course, but when I tried just signing the jar and then adding the extra lines about security to the packager’s .jnlp file, it still didn’t work. Instead, I got a new error telling me that the main-class could not be cast to
This made sense, and so after some abortive attempts at launching the JRubyFX app from a small JavaFX app, I figured out which part of the .jnlp file ensured that the JavaFX libraries were available, and which part was trying to launch the app as if it was a JavaFX application. Finally, I wrote my own .jnlp file, based on other working WebStart JRuby apps, plus the code to get the JavaFX library, and PRESTO! One working JRubyFX WebStart app.
Let’s write a small sample JRubyFX app, build it into a jar, and then create the WebStart files to launch it.
First create a new project directory, change into it, and create a src dir inside:
Now create a new file inside the
hello.rb, and open it in your favorite editor:
From the main
HelloWebStart directory, build an executable jar using the
jrubyfx-jarify src --main src/hello.rb hello.jar
keytool -genkey -keystore myKeystore -alias myself
This will prompt you with a number of questions, just be sure to remember the passwords you give it. Next we self-certify:
keytool -selfcert -alias myself -keystore myKeystore
This will ask you for that password, so I hope you remember what it was!
Next we sign our jar, again you’ll be prompted for your password:
jarsigner -keystore myKeystore hello.jar myself
If you execute the jar with
java -jar hello.jar you should see:
Now we need to create the jnlp file, which is what will launch the app. In the main
HelloWebStart directory, where your jar file is, create the file
You can read all about WebStart and jnlp on Oracle’s WebStart Deployment Tutorials page, but let’s go over some of this.
The jnlp file is XML, so normal XML syntax rules apply. In the
jnlp tag we have a few attributes. First, we set up the “jfx” namespace. Next we leave codebase as an empty string, because we are running this from our own computer, but if we were hosting this on the internet, codebase would be a url indicating the directory that held the jnlp file. For example, if you download the WebStart JNLP file from the JRuby Homepage’s Try Jruby example, and open it with your text editor, you’ll see their
jnlp tag looks like:
<jnlp codebase="http://jruby.org/tryjruby" href="irb.jnlp" spec="1.0+">
The codebase, combined with the href, provides the full url to the jnlp file, which in that case is
The information tag and its elements is important, so don’t leave it completely blank, as Java uses that information in the dialogs it displays to the user. “offline-allowed” instructs java to allow the program to run, once its been downloaded, even if the user doesn’t have an internet connection. That’s because with WebStart it’s even possible for us to allow the user to create a desktop shortcut and run our application whenever they want.
Next comes a very important part. The
security tag, and its enclosed
all-permissions is what tells Java to expect a signed jar, and to request the additional security permissions we need in order for JRuby to do its internal reflection thing.
There are two
resources tags. The first uses that “jfx” namespace we created earlier to ensure the user has an available and up-to-date copy of the JavaFX library. This is also very important. The second checks for the Java Run Time, and then downloads our executable jar. Normally, if we had this on a server, the href attribute inside the
jar tag would be a url pointing to our jar. To look at the Try JRuby example again, their jnlp uses this tag:
<jar eager="true" href="http://jruby.org.s3.amazonaws.com/tryjruby/jruby-complete-signed.jar" main="true"/>
In this case, since we are running this on our own machine, we need an absolute path to the jar file’s location. On my Ubuntu 12.04 machine, with the jar in the location I have it in,
/home/eric/projects/jrubyfx_projects/test/HelloWebStart/hello.jar works. Similar is likely to work on OSX, though I cannot be sure. On Windows, you will need to experiment a bit and find what works.
application-desc tells java which file inside the jar is the class to launch the application. As long as we are using the jrubyfx-jarify tool, it should always be “org.jruby.JarBootstrapMain”.
If you got all this correct, and you double click on
hello.jnlp you should see a java splash screen followed by a dialog like this:
This is requesting those permissions we’ve discussed. It’s unfortunate, but there is just no way at present to get around this. If you check the box, the disabled “Run” button will become enabled, and your app should start up.
If double-clicking the file did nothing, or just reopened the file in your text editor, you can execute it to test it from the command line with:
Now, we want to see WebStart working from a web page, of course, so let’s set up a very simple web page that will let us download the jnlp file and run our app that way. Create
hello.html and open it up.
hello.jar are all in the same directory and double-click on hello.html to open it in your browser. If you did everything correctly, you should see the following:
Clicking on either the link, or the launch button, should download the jnlp file which you can run. After verifying the security dialog again, your app should begin to run!
I can’t wait to hear your success stories in the comments below, along with any suggestions or criticism. I hope this was helpful, and keep building cool stuff.