NullPointerException in MaterialDesignIconFactory because of module encapsulation

Issue #70 new
Robin created an issue

When using the latest version of materialdesignfont in a modular JavaFX application on Java 11, a NullPointerException is thrown when using:

MaterialDesignIconFactory.get().createIconButton()

The problem here is that de.jensd.fx.glyphs.GlyphsFactory is in the module de.jensd.fx.fontawesomefx.commons, but wants to access the resource /de/jensd/fx/glyphs/materialdesignicons/materialdesignicons-webfont.ttf in the module de.jensd.fx.fontawesomefx.materialdesignicons.

But since Java 9 the behaviour of getting resources has changed so that:

A resource in a named module may be encapsulated so that it cannot be located by code in other modules. Whether a resource can be located or not is determined as follows:

  • If the resource name ends with ".class" then it is not encapsulated.
  • A package name is derived from the resource name. If the package name is a package in the module then the resource can only be located by the caller of this method when the package is open to at least the caller's module. If the resource is not in a package in the module then the resource is not encapsulated.

In the above, the package name for a resource is derived from the subsequence of characters that precedes the last '/' in the name and then replacing each '/' character in the subsequence with '.'. A leading slash is ignored when deriving the package name. As an example, the package name derived for a resource named "a/b/c/foo.properties" is "a.b.c". A resource name with the name "META-INF/MANIFEST.MF" is never encapsulated because "META-INF" is not a legal package name.

(copied from https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/lang/Module.html#getResourceAsStream(java.lang.String))

Attached to this issue is a minimal gradle example project which shows the behaviour. When executing ./gradlew run, it produces the following output:

Exception in Application start method
java.lang.reflect.InvocationTargetException
  at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
  at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
  at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
  at java.base/java.lang.reflect.Method.invoke(Method.java:566)
  at javafx.graphics/com.sun.javafx.application.LauncherImpl.launchApplicationWithArgs(LauncherImpl.java:464)
  at javafx.graphics/com.sun.javafx.application.LauncherImpl.launchApplication(LauncherImpl.java:363)
  at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
  at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
  at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
  at java.base/java.lang.reflect.Method.invoke(Method.java:566)
  at java.base/sun.launcher.LauncherHelper$FXHelper.main(LauncherHelper.java:1051)
Caused by: java.lang.RuntimeException: Exception in Application start method
  at javafx.graphics/com.sun.javafx.application.LauncherImpl.launchApplication1(LauncherImpl.java:900)
  at javafx.graphics/com.sun.javafx.application.LauncherImpl.lambda$launchApplication$2(LauncherImpl.java:195)
  at java.base/java.lang.Thread.run(Thread.java:834)
Caused by: java.lang.RuntimeException: java.lang.NullPointerException
  at de.jensd.fx.fontawesomefx.commons/de.jensd.fx.glyphs.GlyphsFactory.loadFont(GlyphsFactory.java:64)
  at de.jensd.fx.fontawesomefx.commons/de.jensd.fx.glyphs.GlyphsFactory.<init>(GlyphsFactory.java:38)
  at de.jensd.fx.fontawesomefx.materialdesignicons/de.jensd.fx.glyphs.materialdesignicons.utils.MaterialDesignIconFactory.<init>(MaterialDesignIconFactory.java:28)
  at de.jensd.fx.fontawesomefx.materialdesignicons/de.jensd.fx.glyphs.materialdesignicons.utils.MaterialDesignIconFactory.get(MaterialDesignIconFactory.java:33)
  at HelloFX.main/foo.bar.HelloApp.start(HelloApp.java:23)
  at javafx.graphics/com.sun.javafx.application.LauncherImpl.lambda$launchApplication1$9(LauncherImpl.java:846)
  at javafx.graphics/com.sun.javafx.application.PlatformImpl.lambda$runAndWait$12(PlatformImpl.java:455)
  at javafx.graphics/com.sun.javafx.application.PlatformImpl.lambda$runLater$10(PlatformImpl.java:428)
  at java.base/java.security.AccessController.doPrivileged(Native Method)
  at javafx.graphics/com.sun.javafx.application.PlatformImpl.lambda$runLater$11(PlatformImpl.java:427)
  at javafx.graphics/com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatcher.java:96)
  at javafx.graphics/com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
  at javafx.graphics/com.sun.glass.ui.win.WinApplication.lambda$runLoop$3(WinApplication.java:174)
  ... 1 more
Caused by: java.lang.NullPointerException
  at de.jensd.fx.fontawesomefx.commons/de.jensd.fx.glyphs.GlyphsFactory.loadFont(GlyphsFactory.java:62)
  ... 13 more
Exception running application foo.bar.HelloApp

FAILURE: Build failed with an exception.

I’m not sure what the best way to fix this properly would be. But i think the easiest way should be to move materialdesignicons-webfont.ttf out of the package structure to some place which is not regarded as a proper package. Then the resource should be available to other modules (de.jensd.fx.fontawesomefx.commons in this case).

Comments (2)

  1. Log in to comment