What else am I missing to load service providers using the new Java module system?

三世轮回 提交于 2019-12-10 10:07:14

问题


I'm adding module-info.javas 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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!