Build a JavaFX + LeapMotion application with gradle

For SlideshowFX (which is an app I’m developing in JavaFX and using the LeapMotion controller) I am trying to use gradle as build and dependencies management system instead of the very well-known  maven. There are few steps I had to fight with to successfully build a self-contained application (aka native bundle). For those don’t knowing what that means take a look at the Oracle Documentation.

Disclaimer : I’m new in the gradle’s world so maybe a lot of things could be improved.


  • Having a JDK 8 up and running
  • Having the JAVA_HOME environment variable defined to point the the JDK 8 installation
  • Having gradle installed properly (version 1.11 used at the time this article was written)
  • Knowing gradle a little bit


The javafxpackager

In order to package a JavaFX application you can use the javafxpackager tool provided with the JDK. It allows you to create the application JAR and then the native bundle for your application.

To create the jar you will use the following command:

javafxpackager -createjar ...

You will also need to define some attributes according your application, like -classpath for the list of JARs and libraries your application is using, -appclass for indicating what is the Application class of your application, -srcdir and -srcfiles for indicating which files should be included in your JAR, -outdir for indicating where the JAR file will be created and -outfile for the name of the JAR file.

To create the native bundle you will use the following command:

javafxpackager -deploy -native ...

Building with gradle

In order to build your application with gradle, we will invoke the javafxpackager tool from gradle itself. A JavaFX plugin for gradle exists but I didn’t succeed in using it for my purpose. Indeed for LeapMotion you need some DLL and dylib files that weren’t included in the final JavaFX bundle so I decided to do it myself using gradle tasks. And this also allowed to have a better understanding of the javafxpackager tool instead of just using an IDE to generate my bundle.


In the build.gradle file, I configured all projects with the Java plugin and the source and target compatibility:

subprojects {
  apply plugin: 'java'
  sourceCompatibility = 1.8
  targetCompatibility= 1.8

Dependencies and libraries

For SlideshowFX I decided to use file dependencies. So first of all I declared the dependencies at the beginning of the build.gradle file:

ext {
  allLibs = new File(rootDir, '/lib')
  felix = fileTree(dir: allLibs, include: 'Felix/*.jar')
  json = fileTree(dir: allLibs, include: 'json/*.jar')
  jsoup = fileTree(dir: allLibs, include: 'jsoup-1.7.3.jar')
  junit = fileTree(dir: allLibs, include: 'junit-4.11.jar')
  leapmotion = fileTree(dir: allLibs, include: 'Leap/*')
  markdown = fileTree(dir: allLibs, include: 'markdown/*.jar')
  scribe = fileTree(dir: allLibs, include: 'Scribe/*.jar')
  textile = fileTree(dir: allLibs, include: 'WikiText/*.jar')
  velocity = fileTree(dir: allLibs, include: 'Velocity/*.jar')
  vertx = fileTree(dir: allLibs, include: 'Vert.x/*.jar')
  zxing = fileTree(dir: allLibs, include: 'ZXing/*.jar')

  jdk = System.env.'JAVA_HOME'

Those files collections will be used further for declaring dependencies for each project. For LeapMotion, all files are included: JARs, DLL, and dylib.

Build the jar

To build the JAR I decided to overwrite the default JAR task present in the Java plugin of gradle. We are going to follow these steps:

  • Copy all dependencies of the project to the libsDir folder
  • Build the -classpath attribute for the javafxpackager tool. Each JAR used by the application is adde to the classpath
  • Build the -srcdir/-srcfiles attributes for the javafxpackager tool. There will be many of these attributes because there are classes and resources
  • Build the javafxpackager command to execute
  • Execute the command

Knowing that here is the task definition:

task jar(overwrite: true) << {

  if (jdk != null && !jdk.isEmpty()) {

    if(!libsDir.exists()) libsDir.mkdirs()

    // Copying libs
    copy {
      from(new File(project(':SlideshowFX-markup').libsDir, project(':SlideshowFX-markup').archivesBaseName + ".jar"))


    def classpath = ""

    fileTree(dir: libsDir, include: '*.jar', exclude: archivesBaseName + ".jar").each {
      f ->
      classpath += + ","

    classpath += "."

    def javafxpackager = exec {
      workingDir "${project.projectDir.absolutePath}"

      commandLine "${jdk}/bin/javafxpackager",
                  "-createjar", "-v",
                  "-appclass", "",
                  "-classpath", "${classpath}",
                  "-outdir", "${buildDir}${File.separator}${}",
                  "-outfile", "${project.archivesBaseName}",
                  "-srcdir", "${}/classes/main", "-srcfiles", "com",
                  "-srcdir", "${}/resources/main", "-srcfiles", "com"

Build the native bundle

Now that we have the JAR, let’s make the native bundle. For this we will also create a task for achieving this.

task buildJavaFXBundle << {

  if (jdk != null && !jdk.isEmpty()) {

    def javafxpackager = exec {
      workingDir "${project.projectDir.absolutePath}"

      commandLine "${jdk}/bin/javafxpackager",
                  "-name", "SlideshowFX",
                  "-outdir", "${}${File.separator}dist",
                  "-outfile", "SlideshowFX",
                  "-srcdir", "${}${File.separator}${}",
                  "-appclass", ""

Tasks’ dependencies

Now that we have the needed tasks, let’s add some dependencies between them in order to include everything in the gradle lifecycle:

tasks['jar'].dependsOn 'classes'
tasks['jar'].dependsOn ':SlideshowFX-markup:jar'
tasks['buildJavaFXBundle'].dependsOn 'jar'
tasks['assemble'].dependsOn 'buildJavaFXBundle'

Now calling the assemble task makes it.