Maven project with JavaFX (with jar file in `lib`)

One Two Three picture One Two Three · Mar 7, 2013 · Viewed 48k times · Source

I'm setting up a maven project, that is going to use JavaFX. Since I've heard JavaFX does not come with all versions of Java, I downloaded and put the jfxrt.jar file in a lib directory in my project.

1) How do I specify that the dependency (ie., JavaFX) should not be downloaded, but which is located in lib?

2) Does this then mean the project can be built on any machine with JDK (and not necessary JDK 1.7 - update 9+) ?

Answer

jewelsea picture jewelsea · Mar 8, 2013

2019 Update for Recent JavaFX Versions

As of Java 11, JavaFX has been decoupled from the JDK, so JavaFX libraries are no longer automatically bundled together with a JDK install (as they were for instance in the Oracle JDK 8 distribution). Instead, the JavaFX system is now designed as a set of separate libraries independent from the JDK, which can be downloaded from a repository by a tool such as Maven for use by your application.

openjfx.io have a very short tutorial on using JavaFX 11+ with Maven:

This tutorial recommends use of the OpenJFX JavaFX Maven Plugin and provides the following sample maven pom.xml project file for a "hello, world" style application.

<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/maven-v4_0_0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>org.openjfx</groupId>
  <artifactId>hellofx</artifactId>
  <packaging>jar</packaging>
  <version>1.0-SNAPSHOT</version>
  <name>demo</name>
  <url>http://maven.apache.org</url>

  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  </properties>

  <dependencies>
    <dependency>
      <groupId>org.openjfx</groupId>
      <artifactId>javafx-controls</artifactId>
      <version>12.0.1</version>
    </dependency>
  </dependencies>
  <build>
    <plugins>
      <plugin>
        <groupId>org.openjfx</groupId>
        <artifactId>javafx-maven-plugin</artifactId>
        <version>0.0.2</version>
        <configuration>
          <mainClass>HelloFX</mainClass>
        </configuration>
      </plugin>
    </plugins>
  </build>
</project>

Note that the org.openjfx JavaFX maven plugin used for Java 11+ is different from the com.zenjava JavaFX maven plugin used for Java 8 and 9, so use the appropriate one for your Java version.

Suggested Approach

For building JavaFX apps with Maven:

  1. Use the com.zenjava maven JavaFX plugin with Java 8 and 9 AND/OR
  2. Use Java 8 or 9 and don't specify any kind of Maven dependency for JavaFX OR
  3. Use the org.openjfx maven JavaFX plugin with Java 11+.

Unlike Java 7, with Java 8 it is unnecessary to set JavaFX as a maven dependency, because JavaFX is on the standard Java runtime classpath (similar to the way Swing is today).

Opinion

I think the approach in your question of placing the jfxrt.jar file in a project lib directory is flawed.

The reasons it is flawed are:

  1. JavaFX also includes native libraries, so you would need to include them as well (in a location where jfxrt.jar would be able to find them).
  2. A given version of JavaFX will only be certified to operate against the version of the JDK it is shipped with, so the JavaFX runtime you place in your project's lib directory may not work against a later JDK version, such as JDK 8.
  3. Future versions of the JDK such as JDK 8 will include JavaFX on the default classpath of the JDK, so you may get conflicts with the version you place in your lib directory.

In summary, JavaFX should be treated as part of the Java runtime system, not as a project library.

JavaFX System Dependency Sample

If you must use Java 7 and you don't want to use the JavaFX maven plugin, then you can take the less recommended approach:

This sample is provided for Java 7 only and is not required (and will not work as is) for Java 8. Java 8, places the jfxrt.jar in ${java.home}/lib/ext/jfxrt.jar, which is on the default Java runtime classpath, making a system dependency for Java 8 irrelevant.

<dependency>
  <groupId>javafx</groupId>
  <artifactId>jfxrt</artifactId>
  <version>${java.version}</version>
  <scope>system</scope>
  <systemPath>${java.home}/lib/jfxrt.jar</systemPath>
</dependency>

If you package your application using a system dependency like this, then you need will need to write some execution instructions for your users so that they can add jfxrt.jar to the runtime classpath when running your application on Java 7. This is a very good reason not to use this approach.

If you choose to use the maven system dependency approach, you may also wish to use the maven antrun plugin to embed calls to the JavaFX ant tasks as in this sample. You may also want to use the maven enforcer plugin to ensure that your application is built against at least the minimum required version of Java containing a JavaFX version required by your application to work.