Coming Up for Air

JavaFX and Maven

Monday, Jun 9, 2014 |

JavaFX and Maven

Jason lee 2014-06-09

I've been tinkering with a couple of different JavaFX projects for a while now. Due to other commitments, they've been largely ignored recently, but I made some time this weekend to return to them. Since I last looked at them, Java 8, and, thus, JavaFX 8, have been release, so I decided to see how the tooling in NetBeans has changed to stay apace with the development of the libraries. While there are certainly updates, it seems new projects are still built using Ant. Yuck. igniter.fx project, so I took a look to see what that POM does to support JavaFX. As it turns out, it's pretty simple. For those interested, I have extracted here the basic POM:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>MY_GROUP</groupId>
    <artifactId>MY_ARTIFACT</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>jar</packaging>
    <name>ARTIFACT_NAME</name>

    <dependencies>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.11</version>
            <scope>test</scope>
        </dependency>
    </dependencies>
    <build>
        <defaultGoal>clean package</defaultGoal>
        <plugins>
            <plugin>
                <artifactId>maven-dependency-plugin</artifactId>
                <version>2.6</version>
                <executions>
                    <execution>
                        <id>unpack-dependencies</id>
                        <phase>package</phase>
                        <goals>
                            <goal>unpack-dependencies</goal>
                        </goals>
                        <configuration>
                            <excludeScope>system</excludeScope>
                            <excludeGroupIds>junit,org.mockito,org.hamcrest</excludeGroupIds>
                            <outputDirectory>${project.build.directory}/classes</outputDirectory>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
            <plugin>
                <groupId>org.codehaus.mojo</groupId>
                <artifactId>exec-maven-plugin</artifactId>
                <version>1.2.1</version>
                <executions>
                    <execution>
                        <id>package-jar</id>
                        <phase>package</phase>
                        <goals>
                            <goal>exec</goal>
                        </goals>
                        <configuration>
                            <executable>${env.JAVA_HOME}/bin/javafxpackager</executable>
                            <arguments>
                                <argument>-createjar</argument>
                                <argument>-nocss2bin</argument>
                                <argument>-appclass</argument>
                                <argument>MAIN_CLASS</argument>
                                <argument>-srcdir</argument>
                                <argument>${project.build.directory}/classes</argument>
                                <argument>-outdir</argument>
                                <argument>.</argument>
                                <argument>-outdir</argument>
                                <argument>${project.build.directory}</argument>
                                <argument>-outfile</argument>
                                <argument>${project.artifactId}-app</argument>
                                <argument>-v</argument>
                            </arguments>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>
    <properties>
        <maven.compiler.source>1.8</maven.compiler.source>
        <maven.compiler.target>1.8</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>
</project>

The interesting parts are the two plugins, maven-dependency-plugin and exec-maven-plugin. The first takes all of the non-system-scoped dependencies, and extracts the jars into ${project.build.directory}/classes. This makes the dependencies available to the application without having to manage a bunch of jars, which is helpful when distributing the app. Speaking of which, the next plugin, exec-maven-plugin, packages the application as a JAR using the javafxpackager tool in JAVA_HOME (make sure you change MAIN_CLASS ;). Once you package the app, it can be run with a simple java -jar target/ARTIFACT_NAME-app.jar.

While this POM differs a bit from Adam's POM (e.g., I keep the resources, such a .fxml files, in the standard Maven location), NetBeans is more than happy with it, and my JavaFX hacking is a bit simpler.