pf4j-spring icon indicating copy to clipboard operation
pf4j-spring copied to clipboard

pf4j-spring compatibility with Spring Boot

Open Vikcen opened this issue 5 years ago • 13 comments

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.

Vikcen avatar Oct 10 '19 15:10 Vikcen

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

decebals avatar Oct 11 '19 17:10 decebals

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.

Vikcen avatar Oct 14 '19 15:10 Vikcen

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.

decebals avatar Oct 14 '19 17:10 decebals

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?

Vikcen avatar Oct 14 '19 19:10 Vikcen

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 avatar Oct 15 '19 07:10 decebals

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.

decebals avatar Oct 15 '19 07:10 decebals

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.

Vikcen avatar Oct 15 '19 09:10 Vikcen

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.

decebals avatar Oct 15 '19 10:10 decebals

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)

Vikcen avatar Oct 16 '19 14:10 Vikcen

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

decebals avatar Oct 16 '19 17:10 decebals

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

Vikcen avatar Oct 17 '19 10:10 Vikcen

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

  • For building project pf4j-spring-boot-demo: - 1) mvn clean install -Pmain-build - 2) mvn clean install -Pjar-client-build
    Then build project pf4j-spring-boot-demo-jar-plugins: - 3) mvn clean install

  • For running the demo test, run the spring boot app: org.pf4j.demo.boot.MainApp in pf4j-spring-boot-demo project.

I hope this can help.

Vikcen avatar Oct 23 '19 15:10 Vikcen

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

decebals avatar Apr 12 '20 09:04 decebals