kordamp / ikonli

Icon packs for Java applications
http://kordamp.org/ikonli/
Apache License 2.0
502 stars 50 forks source link

Scene Builder cannot load FXML with Ikonli 12.0.0 #124

Closed sheydrich closed 3 years ago

sheydrich commented 3 years ago

Hey,

thanks for your work on Ikonli!

I just updated from v11.5.0 to v12.0.0. I cannot open any of my existing FXMLs that contain FontIcons with an iconLiteral anymore. That is, when the file contains only an "empty" FontIcon, everything works. When the iconLiteral is defined, i get

java.lang.UnsupportedOperationException: Cannot resolve 'fa-bug'
    at org.kordamp.ikonli.AbstractIkonResolver.resolve(AbstractIkonResolver.java:73)
    at org.kordamp.ikonli.javafx.FontIcon.setIconLiteral(FontIcon.java:232)

Of course, I updated the JARs for Ikonli inside SceneBuilder.

Any idea what might be the problem?

reardenSteel1964 commented 3 years ago

Same here!

aalmiray commented 3 years ago

Thank you for your report. Are you saying that an FXML like the following no longer works? sampler.fxml

sheydrich commented 3 years ago

Yes, this is correct. The file you posted does produce the same UnsupportedOperationException for 'fa-circle-thin' when opening with SceneBuilder, where these are the imported Libraries in SceneBuilder: grafik

aalmiray commented 3 years ago

Here's the sampler-javafx app running, consuming the sampler.fxml file as is

sampler-javafx-fa

And here is the ikonli-browser displaying the legacy FontAwesome icon pack

ikonli-browser-fa

I suspect there's some specific issue in SceneBuilder. The given exception occurs when no suitable IkonHandler has been found. This tells me SB failed to load org.kordamp.ikonli.fontawesome.FontAwesomeIkonHandler, which should be loaded using ServiceLoader regardless of classpath or modulepath, although arguably JavaFX 9+ should always run on the modulepath.

aalmiray commented 3 years ago

The other thing that could be related to this problem is how IkonHandler instances are resolved in 12.0.0. The code in question is https://github.com/kordamp/ikonli/blob/master/core/ikonli-javafx/src/main/java/org/kordamp/ikonli/javafx/IkonResolver.java#L46-L51

    private static ServiceLoader<IkonHandler> resolveServiceLoader() {
        if (null != IkonHandler.class.getModule().getLayer()) {
            return ServiceLoader.load(IkonHandler.class.getModule().getLayer(), IkonHandler.class);
        }
        return ServiceLoader.load(IkonHandler.class);
    }

@eugener would you happen to have an idea how SceneBuilder loads new JARs when a ModuleLayer is available?

aalmiray commented 3 years ago

Well, I can replicate the problem with SceneBuilder 11.0.0

Steps:

  1. Add ikonli-core, ikonli-javafx, ikonli-fontawesome-pack to Scenebuilder via the "JAR/FXML Manager" option found in the library section (left side).
  2. Add a FontIcon element to the main container. Configure fa-bug as the value for `iconLiteral. Notice that Scenebuilder does not render the icon.
  3. Save the FXML file and quit SceneBuilder.
  4. Launch SceneBuilder and load the previously saved FXML file.
  5. The reported exception occurs.

Given the error message I can tell Ikonli did not find a suitable IkonHandler for icons with fa- as prefix. This could be related to loading handlers using the ModuleLayer variant.

aalmiray commented 3 years ago

Well, it turns SecneBuilder is cheeky and loads custom jars into the unnamed module, making the ModuleLayer null as a result. This makes the loading code in IkonResolver fail as shown before. The ServiceLoader.load(IkonHandler.class) will fail as well. the only way to make it work is by passing a specific classloader.