pf4j / pf4j-spring

Plugin Framework for Spring (PF4J - Spring Framework integration)
Apache License 2.0
346 stars 105 forks source link

pf4j-spring compatibility with Spring Boot #37

Open Vikcen opened 5 years ago

Vikcen commented 5 years ago

Hello, i hope i can get some help.

I have tested successfully in my Spring Boot web application, loading plugins and getting my extensions from the plugin packaged in a jar like in your documentation shows in this way:

FileSystem sistemaFicheros = FileSystems.getDefault();

PluginManager pluginManager = new SpringPluginManager(sistemaFicheros.getPath("/home/vbravo/Escritorio/plugins"));
pluginManager.loadPlugins();

List<Converter> converters = pluginManager.getExtensions(Converter.class);
for (Converter zipToPdfConversion : converters) {
    zipToPdfConversion.getConversionType();
}

But i don't see any example of loading this plugin via @Autowired (in Spring Boot) like you say in the documentation:

Ready, your extension is available in your application via PluginManager or Spring Autowire.

I don't understand very well what you mean exactly with Autowired, Do you mean i could load the plugin in this way as attribute of a class in a Spring Boot context?

@Autowired
Converter zipToPdfConversion;

Where Converter zipToPdfConversion is implemented in the same form of your documentation:

public class HelloPlugin extends SpringPlugin {

    public HelloPlugin(PluginWrapper wrapper) {
        super(wrapper);
    }

    @Override
    public void start() {
        System.out.println("HelloPlugin.start()");
    }

    @Override
    public void stop() {
        System.out.println("HelloPlugin.stop()");
        super.stop(); // to close applicationContext
    }

    @Override
    protected ApplicationContext createApplicationContext() {
        AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
        applicationContext.setClassLoader(getWrapper().getPluginClassLoader());
        applicationContext.register(SpringConfiguration.class);
        applicationContext.refresh();

        return applicationContext;
    }

    @Extension
    public static class HelloGreeting implements Greeting {

        @Autowired
        private MessageProvider messageProvider;

        @Override
        public String getGreeting() {
//            return "Hello";
            // complicate a little bit the code
           return messageProvider.getMessage();
        }

    }

}

Can you show me some example to see how to do that Autowired of a plugin class (extending SpringPlugin) thru Spring Boot?

The idea is to load the plugin without package the plugin in a jar, i have just the plugin in the source code. I want the two ways, load from a jar and load without packaged in jar (is this possible?).

Thank you, greetings.

decebals commented 5 years ago

But i don't see any example of loading this plugin via @Autowired (in Spring Boot) like you say in the documentation

https://github.com/pf4j/pf4j-spring/blob/master/demo/app/src/main/java/org/pf4j/demo/Greetings.java#L30

Vikcen commented 5 years ago

Hello, thanks for answering.

I mean an example of use of this structure public class HelloPlugin extends SpringPlugin written in your example.

How/where i should obtain/instantiate the SpringPlugin in the spring boot application? (i dont see it in the demo)

Greetings.

decebals commented 5 years ago

I don't understand your question, and what you are looking for. Take a look at demo application to see a concrete example. They are some examples/projects available on internet.

How/where i should obtain/instantiate the SpringPlugin in the spring boot application? (i dont see it in the demo)

You don't need to obtain/instantiate the SpringPlugin. You need to obtain only the extensions in your application. A concrete (Spring) plugin is instantiated internally by PF4J. PF4J-Spring is a simple adapter of PF4J for Spring applications.

Vikcen commented 5 years ago

So, if i do something like this, i will obtain that HelloPlugin implementation?

PluginManager pluginManager = new SpringPluginManager();
List<PluginWrapper> helloplugins = pluginManager.getPlugins();

Or how can i access to this HelloPlugin?

decebals commented 5 years ago

So, if i do something like this, i will obtain that HelloPlugin implementation?

SpringPlugin plugin = (SpringPlugin) pluginManager.whichPlugin(MyService.class);

where MyService is a class from your plugin.

You can also try with PluginManager#getPlugin(String pluginId) or PluginManager#getStartedPlugins. The result is a PluginWrapper, but you can continue with PluginWrapper#getPlugin to retrieve the concrete plugin instance.

decebals commented 5 years ago

After I read again the description of the issue I want too add more clarifications:

Can you show me some example to see how to do that Autowired of a plugin class (extending SpringPlugin) thru Spring Boot?

You cannot. In documentation Autowired is used only to inject extensions.

The idea is to load the plugin without package the plugin in a jar, i have just the plugin in the source code. I want the two ways, load from a jar and load without packaged in jar (is this possible?).

Yes. I use this approach in my projects (but I don't use Spring). I run my application in development from my IDE (IntelliJ). In this mode (development) my application together with all the plugins looks like a regular multi module application. In production (deployment mode in PF4J - it's the default) I packages the plugins in JARs.

Vikcen commented 5 years ago

So, if i do something like this, i will obtain that HelloPlugin implementation?

SpringPlugin plugin = (SpringPlugin) pluginManager.whichPlugin(MyService.class);

where MyService is a class from your plugin.

You can also try with PluginManager#getPlugin(String pluginId) or PluginManager#getStartedPlugins. The result is a PluginWrapper, but you can continue with PluginWrapper#getPlugin to retrieve the concrete plugin instance.

That is not correct, it is:

PluginWrapper plugin = pluginManager.whichPlugin(HelloPlugin.class);

But that doesn't work, it returns null (or with getPlugin also returns null). Debugging it, within the class AbstractPluginManager the map plugins is always empty:

/**
     * A map of plugins this manager is responsible for (the key is the 'pluginId').
     */
    protected Map<String, PluginWrapper> plugins;

So, it is returning always null.

Remember, im testing it without package it in a jar, the plugin (that HelloPlugin referenced in your documetantion) is just in source code of my main app.

decebals commented 5 years ago

Debugging it, within the class AbstractPluginManager the map plugins is always empty

My advice for you is to start with quickstart or/and Spring demo. Did you started your application in development mode? Are you sure?

I'm sorry but I cannot help you with more information.

Vikcen commented 5 years ago

I have the project in GitLab, could i share with you? and then you can test it and see what things are wrong or not compatible? the main app is Spring boot (last version)

decebals commented 5 years ago

OK. Please share the project maybe I have some time to take a look.

Vikcen commented 5 years ago

Could you give me permissions to push a new branch (issue/37) , i have cloned this: https://github.com/pf4j/pf4j-spring.git

Vikcen commented 5 years ago

I did a push to master. For running the test:

I hope this can help.

decebals commented 4 years ago

@Vikcen What is the status of this issue? Can we close it?