Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Handle Scope annotation on extension class #6

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open

Conversation

decebals
Copy link
Member

@decebals decebals commented Dec 6, 2017

No description provided.

@decebals
Copy link
Member Author

decebals commented Dec 6, 2017

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

@decebals
Copy link
Member Author

decebals commented Dec 6, 2017

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.

@goto100
Copy link

goto100 commented Aug 8, 2018

This is useful, release it please~

@decebals
Copy link
Member Author

decebals commented Aug 8, 2018

@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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants