问题
I'm adding module-info.java
s to Ikonli packages and I'm running into trouble with their service classes. ikonli-core
defines an interface called IkonHandler. ikonli-fontawesome5-pack
has a service provider for the IkonHandler
called FontAwesomeSolidIkonHandler. These service prodivers are used by ikonli-javafx
's IkonResolver.
Given this, I created these module definitions:
module org.kordamp.ikonli.core {
exports org.kordamp.ikonli;
}
module org.kordamp.ikonli.javafx {
exports org.kordamp.ikonli.javafx;
uses org.kordamp.ikonli.IkonHandler;
requires javafx.graphics;
requires org.kordamp.ikonli.core;
}
module org.kordamp.ikonli.fontawesome5 {
exports org.kordamp.ikonli.fontawesome5;
provides org.kordamp.ikonli.IkonHandler with org.kordamp.ikonli.fontawesome5.FontAwesomeBrandsIkonHandler, org.kordamp.ikonli.fontawesome5.FontAwesomeRegularIkonHandler, org.kordamp.ikonli.fontawesome5.FontAwesomeSolidIkonHandler;
requires org.kordamp.ikonli.core;
requires org.kordamp.jipsy;
}
They might not be complete, but they are complete enough so that when my application starts, it fails with this error:
java.lang.UnsupportedOperationException: Cannot resolve 'fas-user'
which is throw when no handler managed to load the icon:
public IkonHandler resolveIkonHandler(String value) {
requireNonNull(value, "Ikon description must not be null");
for (IkonHandler handler : HANDLERS) {
if (handler.supports(value)) {
return handler;
}
}
throw new UnsupportedOperationException("Cannot resolve '" + value + "'");
}
The reason why that is happening is that HANDLERS
is empty. HANDLERS
is loaded at startup by this code:
ClassLoader classLoader = IkonResolver.class.getClassLoader();
ServiceLoader<IkonHandler> loader = ServiceLoader.load(IkonHandler.class, classLoader);
for (IkonHandler handler : loader) {
HANDLERS.add(handler);
handler.setFont(Font.loadFont(classLoader.getResource(handler.getFontResourcePath()).toExternalForm(), 16));
}
but with the module definitions quoted above, ServiceLoader.load(IkonHandler.class, classLoader)
finds no service providers.
What am I missing?
回答1:
What I was missing was requiring fontawesome5
in the module-info.java
of my application:
requires org.kordamp.ikonli.fontawesome5;
回答2:
"My app was not requiring the the fontawesome5 module." Your app doesn't need to require it. In fact, your app shouldn't require it. You're missing the point of uses/provides.
Edit You make a provider available by putting it on the modulepath and watching the module system go to work. Your ikonli.javafx module uses the IkonHandler interface, and your ikonli.fontawesome5 module provides an implementation of the IkonHandler interface. That's all the module system needs to bind them together. It's wrong for ikonli.javafx to require ikonli.fontawesome5. ikonli.fontawesome5 shouldn't even export the package that it's exporting, because that allows anyone who requires ikonli.fontawesome5 to access the provider classes like FontAwesomeBrandsIkonHandler directly.
来源:https://stackoverflow.com/questions/51221802/what-else-am-i-missing-to-load-service-providers-using-the-new-java-module-syste