Understanding the JavaFX Runtime Components Error

When developing JavaFX applications with custom controls like ControlsFX using Maven and modular Java (JPMS), developers frequently encounter the following error during execution:

Error: JavaFX runtime components are missing, and are required to run this application
Command execution failed.
org.apache.commons.exec.ExecuteException: Process exited with an error: 1

This issue typically occurs when the JVM attempts to launch a class extending javafx.application.Application directly from the classpath rather than the module path, or when your IDE (such as NetBeans) overrides your Maven plugin configurations at runtime.

Why Does This Happen?

  • IDE Command Overrides: NetBeans automatically appends arguments like -Dexec.args="... -classpath %classpath com.example.App" when executing Maven goals. This overrides the custom <configuration> block defined in your pom.xml for the exec-maven-plugin.
  • Module Path vs. Classpath: JavaFX 11+ requires native libraries and modular initialization. If the Java launcher initializes a class extending Application without the JavaFX modules present on the module path, the launcher aborts immediately.

Solution 1: Use the Official JavaFX Maven Plugin (Recommended)

The cleanest and most robust solution for managing JavaFX applications in Maven is replacing or supplementing raw exec-maven-plugin configurations with the official javafx-maven-plugin provided by OpenJFX.

Update your pom.xml build plugins section:

<build>
  <plugins>
    <plugin>
      <groupId>org.openjfx</groupId>
      <artifactId>javafx-maven-plugin</artifactId>
      <version>0.0.8</version>
      <configuration>
        <mainClass>app/com.example.App</mainClass>
        <options>
          <option>--add-exports</option>
          <option>javafx.base/com.sun.javafx.event=org.controlsfx.controls</option>
          <option>--add-exports</option>
          <option>javafx.controls/com.sun.javafx.scene.control.behavior=org.controlsfx.controls</option>
        </options>
      </configuration>
    </plugin>
  </plugins>
</build>

You can then run your application directly using the plugin goal:

mvn javafx:run

Solution 2: Create a Non-Extending Main Launcher Class

If you prefer to launch via traditional classpath or rely on IDE execution defaults, a quick workaround is creating a separate entry point class that does not extend javafx.application.Application.

Create a launcher class in your project:

package com.example;

public class Main {
    public static void main(String[] args) {
        App.main(args);
    }
}

Update your target execution main class in your IDE or Maven build configuration to com.example.Main instead of com.example.App. Because Main does not extend Application, Java's standalone launcher checks won't trigger, allowing JavaFX to initialize properly at runtime.

Solution 3: Fix NetBeans Action Overrides (nbactions.xml)

If you must use NetBeans' built-in "Run Project" command, NetBeans generates or uses an nbactions.xml file in your project root. Modify this file to pass module path options rather than forcing standard classpath execution:

<actions>
  <action>
    <actionName>run</actionName>
    <packagings>
      <packaging>jar</packaging>
    </packagings>
    <goals>
      <goal>process-classes</goal>
      <goal>org.codehaus.mojo:exec-maven-plugin:3.6.3:exec</goal>
    </goals>
    <properties>
      <exec.vmArgs>--module-path %modulepath --add-modules app,org.controlsfx.controls --add-exports javafx.base/com.sun.javafx.event=org.controlsfx.controls --add-exports javafx.controls/com.sun.javafx.scene.control.behavior=org.controlsfx.controls</exec.vmArgs>
      <exec.args>${exec.vmArgs} -m app/com.example.App</exec.args>
      <exec.appArgs></exec.appArgs>
      <exec.mainClass>com.example.App</exec.mainClass>
      <exec.executable>java</exec.executable>
    </properties>
  </action>
</actions>

Summary

The standard Java launcher checks for JavaFX components on startup when a main class extends javafx.application.Application. Switching to javafx-maven-plugin or using a dedicated launcher entry-point resolves module path discrepancies across NetBeans and Maven environments.