0

I'm using a Spring Boot application. For now, the use of the plugins is very simple. I'm just following the tutorial. My plugin is started, I'm trying to find the extensions like this:

final List<MyExtensionPoint> sections = pluginManager.getExtensions(MyExtensionPoint.class);

but Pf4j doesn't return the extensions.

When I'm following the code execution, I can see this code in the AbstractExtensionFinder:

if (type.isAssignableFrom(extensionClass)) {
  ExtensionWrapper extensionWrapper = createExtensionWrapper(extensionClass);
  result.add(extensionWrapper);
  log.debug("Added extension '{}' with ordinal {}", className, extensionWrapper.getOrdinal());
} else {
  log.trace("'{}' is not an extension for extension point '{}'", className, type.getName());
  if (RuntimeMode.DEVELOPMENT.equals(pluginManager.getRuntimeMode())) {
    checkDifferentClassLoaders(type, extensionClass);
  }
}

I can understand the program is not entering inside the condition because I have 2 different classloaders: PluginClassLoader (for the extension) and RestartClassLoader (from Spring for the interface of the extension point).

I don't understand why it will be a problem because I think to instanciate the extension class, the PluginClassloader will use the parent class loader (RestartClassLoader) to find the interface.

Where is my mistake ? How to fix it ?

Thank you.

stefv
  • 429
  • 1
  • 4
  • 19
  • Ok, it looks like if I have another classloader: jdk.internal.loader.ClassLoaders$AppClassLoader. I have the feeling the pluginin don't use RestartClassLoader from Spring but the original class loader of Java. And when the plugin needs to find the class from the parent classloader it's using the wrong classloader. – stefv Sep 09 '22 at 06:47
  • The problem seems coming from the PluginManager. I created my own PluginManager to add attributes to the plugin manifest using a new XML plugin manifest. My PluginManager is created from the Spring ClassLoader when Pf4j is using the Java JRE classloader. – stefv Sep 09 '22 at 11:08

1 Answers1

0

I extended the DevelopmentPluginLoader to pass the Spring classloader.

public class MyDevelopmentPluginLoader extends DevelopmentPluginLoader {

    private ClassLoader parentClassLoader;

    /**
     * @param pluginManager
     */
    public MyDevelopmentPluginLoader(final PluginManager pluginManager, final ClassLoader parentClassLoader) {
        super(pluginManager);
        this.parentClassLoader = parentClassLoader;
    }

    @Override
    protected PluginClassLoader createPluginClassLoader(final Path pluginPath, final PluginDescriptor pluginDescriptor) {
        return new PluginClassLoader(pluginManager, pluginDescriptor, parentClassLoader);
    }
}

and in my custom PluginManager, I created and instance of my PluginLoader:

protected PluginLoader createPluginLoader() {

        final CompoundPluginLoader compoundPluginLoader = new CompoundPluginLoader();
        final PluginLoader developmentPluginLoader = new MyDevelopmentPluginLoader(this, getClass().getClassLoader());
        final PluginLoader jarPluginLoader = new JarPluginLoader(this);
        final PluginLoader defaultPluginLoader = new DefaultPluginLoader(this);

        // @formatter:off
        return compoundPluginLoader.
                add(developmentPluginLoader, this::isDevelopment).
                add(jarPluginLoader, this::isNotDevelopment).
                add(defaultPluginLoader, this::isNotDevelopment);
        // @formatter:on
    }
stefv
  • 429
  • 1
  • 4
  • 19