Have you ever had to quickly create an installer for your Java application, but did not want to spend a lot of time on it creating your own? You might be surprised, but such a tool is already present in the standard JDK7.
Short description
javafxpackager is a utility designed to create packages from programs written using JavaFX. Some time after it was created, Oracle decided that the same utility could also create packages for programs written purely in Java. Name decided not to change.
What is served at the entrance? You can submit to the input as a directory with already compiled sources, and already compiled jar. Next, the jar is packaged with the JRE and you can submit it to a user with not yet installed java. This allows you to not force the user to install the JRE themselves. So how to use it?
Examples of using
Suppose we have a HelloWorld project: just the src directory with the helloworld subdirectory and HelloWorld.java in it:
package helloworld; public class HelloWorld { public static void main (String[] args) { System.out.println ("Hello, world!"); } }
At its root is the simplest ant buildov.xml, which can only build class files:
<?xml version="1.0" encoding="UTF-8"?> <project name="Generic" default="compile" basedir="."> <target name="compile"> <mkdir dir="build/classes"/> <javac srcdir="src" destdir="build/classes" executable="${java.sdk}/bin/javac"/> </target> </project>
So, just build the project:
$ ant compile
Using javafxpackager, you can build jar's, which we will do (after creating the dist directory):
$ javafxpackager -createjar -srcdir build/classes -outfile dist/HelloWorld.jar -appclass helloworld.HelloWorld
If you look at the contents of the created jar, we will see that it is somewhat different from the standard created:
$ unzip -l dist/HelloWorld.jar Archive: dist/HelloWorld.jar Length Date Time Name --------- ---------- ----- ---- 0 2013-04-29 15:50 META-INF/ 158 2013-04-29 15:50 META-INF/MANIFEST.MF 0 2013-04-29 15:50 helloworld/ 353 2013-04-29 15:50 helloworld/HelloWorld.class 0 2013-04-29 15:50 com/ 0 2013-04-29 15:50 com/javafx/ 0 2013-04-29 15:50 com/javafx/main/ 2671 2013-04-29 15:50 com/javafx/main/Main$1.class 5633 2013-04-29 15:50 com/javafx/main/NoJavaFXFallback.class 19218 2013-04-29 15:50 com/javafx/main/Main.class 1747 2013-04-29 15:50 com/javafx/main/Main$2.class --------- ------- 29780 11 files
Unpacking it and opening MANIFEST.MF, we also see that the inclusion method is also slightly different from the standard one (it is typical for JavaFX):
Manifest-Version: 1.0 JavaFX-Version: 2.2 JavaFX-Application-Class: helloworld.HelloWorld Created-By: JavaFX Packager Main-Class: com/javafx/main/Main
Next, we proceed to the creation of the packages. By default, the deploy directive creates only jnlp and html with a built-in plugin.
But if you specify the -native all directive, then a package is created that is specific for this operating system: deb and rpm for Linux (any that contain dpkg or rpmbuild for each of the packages, respectively), exe and msi for Windows (unfortunately, there is a limit and The following utilities should be installed: Inno Setup to create exe and WiX Toolset for msi) and an app with dmg for MacOS X. Let's immediately create native packages (we’ve supposedly created the jar already):
$ javafxpackager -deploy -v -srcdir dist -outdir dist -outfile HelloWorld -appclass helloworld.HelloWorld -native all
After that some time there will be an assembly. Now we have different bundles in the dist directory: 2 package packages (different for different OSs) and 1, which is essentially an unpacked package: the HelloWorld directory, in which the HelloWorld binary runs, which we immediately get the result:
Hello, world!
This code starts with the JRE already packed in the directory.
And packages can already be installed.
But how to add such an assembly to the project?
There are 2 ways: you can use the same javafxpackager, adding it to your, for example, Ant-scripts, using, for example, exec'a. But you can do much cooler. The same java delivery includes the ant-javafx.jar package, which allows you to add the same to your ant-scripts. What do you need to do for this?
- Add support for ant-javafx: in the root element of the project xml-tree set the parameter
xmlns: fx = "javafx: com.sun.javafx.tools.ant"
and add in his body
<taskdef resource="com/sun/javafx/tools/ant/antlib.xml" uri="javafx:com.sun.javafx.tools.ant" classpath=".${path.separator}${java.sdk}/lib/ant-javafx.jar"/>
, while you must have $ {java.sdk} variable set in the JDK root. - jar:
<fx:jar destfile="dist/HelloWorld.jar"> <fx:application name="HelloWorld" mainClass="helloworld.HelloWorld" /> <fx:fileset dir="build/classes" /> <fx:manifest> <fx:attribute name="Implementation-Vendor" value="meAndMyCompany"/> <fx:attribute name="Implementation-Title" value="HelloWorld"/> <fx:attribute name="Implementation-Version" value="1.0"/> </fx:manifest> </fx:jar>
- deploy:
<fx:deploy width="100" height="100" nativeBundles="all" outdir="dist" outfile="HelloWorld"> <fx:application name="HelloWorld" mainClass="helloworld.HelloWorld"/> <fx:resources> <fx:fileset dir="dist" includes="*.jar"> </fx:resources> <fx:info title="HelloWorld" vendor="myAndMyCompany"/> </fx:deploy> </pre>
docs.oracle.com/javafx/2/deployment/javafxpackager001.htm - javafxpackager documentation
docs.oracle.com/javafx/2/deployment/javafx_ant_task_reference001.htm - Antovical Tasks Documentation
docs.oracle.com/javafx/2/deployment/self-contained-packaging.htm - additional information
UPD: All those that are not working here works in modern versions of the JDK.