pf4j-spring
pf4j-spring copied to clipboard
Handle Scope annotation on extension class
From log:
2017-12-06 19:25:05,724 DEBUG org.pf4j.AbstractExtensionFinder - org.pf4j.demo.hello.HelloPlugin$HelloGreeting
2017-12-06 19:25:05,724 DEBUG org.pf4j.spring.ExtensionsInjector - Register extension 'org.pf4j.demo.WhazzupGreeting' as bean
2017-12-06 19:25:05,735 INFO org.pf4j.spring.ExtensionsInjector - Registering org.pf4j.demo.WhazzupGreeting with scope: prototype
2017-12-06 19:25:05,738 DEBUG org.pf4j.spring.ExtensionsInjector - Registering extensions of the plugin 'welcome-plugin' as beans
2017-12-06 19:25:05,738 DEBUG org.pf4j.spring.ExtensionsInjector - Register extension 'org.pf4j.demo.welcome.WelcomePlugin$WelcomeGreeting' as bean
2017-12-06 19:25:05,739 INFO org.pf4j.spring.ExtensionsInjector - Registering org.pf4j.demo.welcome.WelcomePlugin$WelcomeGreeting as singleton
2017-12-06 19:25:05,739 DEBUG org.pf4j.spring.ExtensionsInjector - Registering extensions of the plugin 'hello-plugin' as beans
2017-12-06 19:25:05,739 DEBUG org.pf4j.spring.ExtensionsInjector - Register extension 'org.pf4j.demo.hello.HelloPlugin$HelloGreeting' as bean
2017-12-06 19:25:05,740 INFO org.pf4j.spring.ExtensionsInjector - Registering org.pf4j.demo.hello.HelloPlugin$HelloGreeting as singleton
Found 3 extensions for extension point 'org.pf4j.demo.api.Greeting'
>>> Whazzup
>>> Welcome
>>> Hello
I see a problem when we try to add scope on HelloGreeting
(an extension of Greeting
from HelloPlugin
).
HelloPlugin
extends SpringPlugin
, so it comes with an plugin context (application context) that contains beans that are visible only in this plugin.
@Extension(ordinal=1)
@Scope("prototype")
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();
}
}
The exception is:
Exception in thread "main" org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'greetings': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private java.util.List org.pf4j.demo.Greetings.greetings; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.pf4j.demo.hello.HelloPlugin$HelloGreeting': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private org.pf4j.demo.hello.MessageProvider org.pf4j.demo.hello.HelloPlugin$HelloGreeting.messageProvider; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [org.pf4j.demo.hello.MessageProvider] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}
The idea is that MessageProvider
is a bean defined in plugin application context and we try to register bean definition HelloGreeting
in the big application context, and a MessageProvider
bean doesn't exists.
Of course we can something like:
if (plugin.getPlugin() instanceof SpringPlugin) {
ApplicationContext pluginContext = ((SpringPlugin) plugin.getPlugin()).getApplicationContext();
beanDefinitionRegistry = (BeanDefinitionRegistry) pluginContext.getAutowireCapableBeanFactory();
}
registerExtension(extensionFactory.create(extensionClass), beanDefinitionRegistry);
in ExtensionsInjector
, but the bean will be registered in plugin context and will not be visible from the big application context, from this reason HelloGreeting
will not be in the list with extensions for Greeting
.
Now, when we use register as singleton, the problem discussed above doesn't appear.
It's clear that we can play with an application context hierarchy in Spring but I don't know how. The context child can see the beans from context parent but the context parent doesn't see the beans from the context child.
This is useful, release it please~
@goto100 After I reread my last/previous comment, I see that is a problem in some scenario and from this reason probably I didn't merge this PR to master. I don't use Spring in my projects (but I used in the past) and from this reason I don't have some internal information about Spring. I think that pf4j-spring project needs some help from the Spring people to move things forward.