pf4j-spring: Injecting an application bean into an Extension object

32 views
Skip to first unread message

Allain Legacy

unread,
Sep 23, 2022, 3:09:56 PM9/23/22
to pf4j
Hi,
Can someone confirm whether my understanding is correct and that I am doing this in the "right" way?   I know that it is possible to inject an Extension into an application object via auto-wiring, but when it comes to doing the reverse (i.e., injecting an application bean into an Extension) what is the recommended/best/right way of doing that?

Let's say I have an Extension defined like the following, and I want to inject a bean of type ApplicationCallbackService which the application (not the plugin) instantiates via a @Component or @Service.

```
@Extension
public class MyExtension implements ExtensionPoint {
     @Autowired
     private ApplicationCallbackService callbackService;

    ...
}
```

The application fails to load with this error:

```
Field dataSourceService in com.example.MyExtension required a bean of type 'com.company.services.ApplicationCallbackService' that could not be found.
```

But the application definitely has a bean of that type.

If I change the implementation of createApplicationContext method of my plugin's subclass of SpringPlugin to use `.scan("com.company.services")` rather than `.register(MyConfiguration.class)` then that works, but that implies that the Plugin implementor needs to be aware of the packages to be scanned in the application that will eventually use that plugin.  That seems like an odd assumption to be made by a plugin implementor.    e.g.,:

@Override
protected ApplicationContext createApplicationContext() {
log.info("creating application context");
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
applicationContext.setClassLoader(getWrapper().getPluginClassLoader());
//applicationContext.register(MyConfiguration.class);
applicationContext.scan("com.company.services");
applicationContext.refresh();

return applicationContext;
}


Also,  while experimenting with this I noticed that if I set the `.scan(...)` packages too broadly (i.e., scan("com")) that it ended up in some kind of infinite loop in what seemed to be the SpringPluginManager loading over and over again.   

What's the recommended way of doing this?   

Should the application pass in the lists of paths that need to be scanned to the plugin manager somehow?

Allain Legacy

unread,
Sep 23, 2022, 6:46:12 PM9/23/22
to pf4j
To answer my own question... I was able to make it work using the setParent(...) call described in this response:

Like this:

@Override
protected ApplicationContext createApplicationContext() {
log.info("creating application context");
// Get the parent context otherwise the extensions will not be able to autowire any application beans.
SpringPluginManager manager = (SpringPluginManager)wrapper.getPluginManager();
ApplicationContext parent = manager.getApplicationContext();

AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
applicationContext.setParent(parent);
applicationContext.setClassLoader(getWrapper().getPluginClassLoader());
applicationContext.register(MyConfiguration.class);
applicationContext.refresh();

return applicationContext;
}



Is this the best way to do this?  

Reply all
Reply to author
Forward
0 new messages