I have an JAVAFX 11 FXML file describing a popup window I use in an application. After refactoring the project structure where I moved the FXML from the "app" project to another project, I get NullPointerException errors, because the XML loader fails to import java.lang.String (and others)
The FXML looks like this:
<?xml version="1.0" encoding="UTF-8"?>
<?import java.lang.String?>
<?import javafx.collections.FXCollections?>
<?import javafx.geometry.Insets?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.ChoiceBox?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.control.Spinner?>
<?import javafx.scene.control.TextField?>
<?import javafx.scene.control.TitledPane?>
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.layout.ColumnConstraints?>
<?import javafx.scene.layout.GridPane?>
<?import javafx.scene.layout.RowConstraints?>
<TitledPane fx:id="GeneticMain"
animated="false"
maxHeight="-Infinity"
maxWidth="-Infinity"
minHeight="-Infinity"
minWidth="-Infinity"
prefHeight="400.0"
prefWidth="400.0"
text="Genetic Scanner Config"
xmlns="http://javafx.com/javafx/8.0.141"
xmlns:fx="http://javafx.com/fxml/1">
<content>
<AnchorPane minHeight="-Infinity" minWidth="-Infinity">
<children>
<GridPane layoutX="10.0"
...
Bottom of Stack trace:
Caused by: java.lang.NullPointerException
at javafx.fxml.FXMLLoader.loadTypeForPackage(FXMLLoader.java:2931) ~[javafx-fxml-12.0.1-linux.jar:?]
at javafx.fxml.FXMLLoader.loadType(FXMLLoader.java:2920) ~[javafx-fxml-12.0.1-linux.jar:?]
at javafx.fxml.FXMLLoader.importClass(FXMLLoader.java:2861) ~[javafx-fxml-12.0.1-linux.jar:?]
at javafx.fxml.FXMLLoader.processImport(FXMLLoader.java:2707) ~[javafx-fxml-12.0.1-linux.jar:?]
at javafx.fxml.FXMLLoader.processProcessingInstruction(FXMLLoader.java:2676) ~[javafx-fxml-12.0.1-linux.jar:?]
at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:2542) ~[javafx-fxml-12.0.1-linux.jar:?]
Effective POM-dependencies to Javafx look like this:
<properties>
...
<dependencyversion.openjfx>12.0.1</dependencyversion.openjfx>
...
</properties>
...
<dependency>
<groupId>org.openjfx</groupId>
<artifactId>javafx-base</artifactId>
<version>12.0.2</version>
</dependency>
<dependency>
<groupId>de.gsi.chart</groupId>
<artifactId>chartfx-chart</artifactId>
<version>11.0.3</version>
<scope>compile</scope>
<exclusions>
<exclusion>
<artifactId>commons-logging</artifactId>
<groupId>commons-logging</groupId>
</exclusion>
<exclusion>
<artifactId>javafx-base</artifactId>
<groupId>org.openjfx</groupId>
</exclusion>
<exclusion>
<artifactId>javafx-web</artifactId>
<groupId>org.openjfx</groupId>
</exclusion>
</exclusions>
</dependency>
I'm happy for any suggestion...
Thanks to fabian I am able to provide a solution to my problem.
The root cause of my problem was that my popup window's class loader, which was called in PopupController.showPopupWindow()
was null. Initial code:
public void showPopupWindow() throws Exception {
Parent popupWindowRoot = null;
try {
URL url = getClass().getResource(url.to.popupFXML.file);
final FXMLLoader fxmlLoader = new FXMLLoader(url);
fxmlLoader.setController(this);
popupWindowRoot = (Parent) fxmlLoader.load();
} catch (final IOException e) {
MessageLogger.logError(getClass(), e);
throw e;
}
...
}
Which was called via an onAction method in the main window:
private void handle_onAction(event onAction) throws Exception {
popupController = new PopupController();
popupController.setParentController(this);
try {
popupController.showPopupWindow();
} catch (final Exception ex) {
APPLOGGER.error(true, true, "Error caught in method showPopupWindow(): ");
}
}
By following Fabian's suggestion, I passed the stage of the main window to method showPopupWindow
and used this stage to set explicitly the classLoader of the popup window. New code:
public void showPopupWindow(Stage parentStage) throws Exception {
Parent popupWindowRoot = null;
try {
URL url = getClass().getResource(url.to.popupFXML.file);
final FXMLLoader fxmlLoader = new FXMLLoader(url);
fxmlLoader.setController(this);
fxmlLoader.setClassLoader(parentStage.getClass().getClassLoader());
popupWindowRoot = (Parent) fxmlLoader.load();
} catch (final IOException e) {
MessageLogger.logError(getClass(), e);
throw e;
}
...
}
The calling method was adjusted accordingly.