Reputation: 1015
I am trying to load an FXML file (Test1.fxml) that includes another FXML file (Test2.fxml). The included file is supposed to use its own resource bundle (test2.properties), which is specified by the "resources" attribute inside the fx:include tag.
When I run the application, FXMLLoader throws a NullPointerException, caused by the following piece of code.
resources = ResourceBundle.getBundle(value, Locale.getDefault(),
FXMLLoader.this.resources.getClass().getClassLoader());
Through debugging I found that FXMLLoader.this.resources is null, which causes the NPE. At first I thought I had simply given a wrong file path, but note that this happens before ResourceBundle even tries to load the properties file!
Any idea how to fix this so the resources can be loaded?
Below are my files. They are all in the same directory (default package for simplicity).
TestApp.java
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;
public class TestApp extends Application
{
@Override
public void start(Stage primaryStage) throws Exception
{
FXMLLoader loader = new FXMLLoader();
loader.setLocation(getClass().getClassLoader().getResource("Test1.fxml"));
loader.load();
Scene scene = new Scene((Parent) loader.getRoot());
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args)
{
launch(args);
}
}
Test1.fxml
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.*?>
<?import java.lang.*?>
<?import javafx.scene.layout.*?>
<BorderPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/8.0.40" xmlns:fx="http://javafx.com/fxml/1">
<center>
<fx:include source="Test2.fxml" resources="test2" />
</center>
</BorderPane>
Test2.fxml
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.*?>
<?import java.lang.*?>
<?import javafx.scene.layout.*?>
<BorderPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/8.0.40" xmlns:fx="http://javafx.com/fxml/1">
<center>
<Label text="%test" BorderPane.alignment="CENTER" />
</center>
</BorderPane>
test2.properties
test=Test 2
Full stacktrace:
Exception in Application start method
java.lang.reflect.InvocationTargetException
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:497)
at com.sun.javafx.application.LauncherImpl.launchApplicationWithArgs(LauncherImpl.java:389)
at com.sun.javafx.application.LauncherImpl.launchApplication(LauncherImpl.java:328)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:497)
at sun.launcher.LauncherHelper$FXHelper.main(LauncherHelper.java:767)
Caused by: java.lang.RuntimeException: Exception in Application start method
at com.sun.javafx.application.LauncherImpl.launchApplication1(LauncherImpl.java:917)
at com.sun.javafx.application.LauncherImpl.lambda$launchApplication$152(LauncherImpl.java:182)
at com.sun.javafx.application.LauncherImpl$$Lambda$50/1645995473.run(Unknown Source)
at java.lang.Thread.run(Thread.java:745)
Caused by: javafx.fxml.LoadException:
/C:/Eclipse/fx/bin/Test1.fxml:9
at javafx.fxml.FXMLLoader.constructLoadException(FXMLLoader.java:2605)
at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:2583)
at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:2445)
at javafx.fxml.FXMLLoader.load(FXMLLoader.java:2413)
at TestApp.start(TestApp.java:16)
at com.sun.javafx.application.LauncherImpl.lambda$launchApplication1$159(LauncherImpl.java:863)
at com.sun.javafx.application.LauncherImpl$$Lambda$53/1370226249.run(Unknown Source)
at com.sun.javafx.application.PlatformImpl.lambda$runAndWait$172(PlatformImpl.java:326)
at com.sun.javafx.application.PlatformImpl$$Lambda$45/186276003.run(Unknown Source)
at com.sun.javafx.application.PlatformImpl.lambda$null$170(PlatformImpl.java:295)
at com.sun.javafx.application.PlatformImpl$$Lambda$48/1026297962.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at com.sun.javafx.application.PlatformImpl.lambda$runLater$171(PlatformImpl.java:294)
at com.sun.javafx.application.PlatformImpl$$Lambda$47/237061348.run(Unknown Source)
at com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatcher.java:95)
at com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
at com.sun.glass.ui.win.WinApplication.lambda$null$145(WinApplication.java:101)
at com.sun.glass.ui.win.WinApplication$$Lambda$36/2117255219.run(Unknown Source)
... 1 more
Caused by: java.lang.NullPointerException
at javafx.fxml.FXMLLoader$IncludeElement.processAttribute(FXMLLoader.java:1088)
at javafx.fxml.FXMLLoader$Element.processStartElement(FXMLLoader.java:216)
at javafx.fxml.FXMLLoader$ValueElement.processStartElement(FXMLLoader.java:740)
at javafx.fxml.FXMLLoader.processStartElement(FXMLLoader.java:2711)
at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:2531)
... 17 more
Exception running application TestApp
Upvotes: 3
Views: 2055
Reputation: 2193
There is a bug in the FXMLLoader. To workaround the bug:
A possible workaround can be found in the oracle forum: https://community.oracle.com/message/11240449
If you don't need a resourceBundle for the root fxml file (like in your example) you can use this simple workaround:
TestApp.java
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;
public class TestApp extends Application
{
@Override
public void start(Stage primaryStage) throws Exception
{
FXMLLoader loader = new FXMLLoader();
// add the resource wrapper
loader.setResources(new ResourceWrapper());
loader.setLocation(getClass().getClassLoader().getResource("Test1.fxml"));
loader.load();
Scene scene = new Scene((Parent) loader.getRoot());
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args)
{
launch(args);
}
// an empty resource bundle
private static class ResourceWrapper extends ListResourceBundle {
@Override
protected Object[][] getContents() {
return new Object[0][];
}
}
}
Upvotes: 3