I stumbled on a weird behaviour of Confluence regarding dependency injection using the new Spring Scanner (@Scanned
/@ComponentImport
) approach (see Bitbucket). It cost me a few hours to find out what was going on in my Confluence app after all of a sudden the dependency injection of the PluginSettingsFactory
stopped working. So I can answer this question myself but I thought I’d share this with the community just in case someone else encounters the same situation.
I’m writing a Confluence plugin targeting Confluence 6.6.0 which needs access to the PluginSettingsFactory
to store and read the plugin settings in several places (as described here Storing plugin settings). I have two classes, which need this factory:
- a Webwork action which is used for the plugin configuration page
- a REST controller which wants to read the plugin configuration
At first I wrote my Webwork action class which receives the PluginSettingsFactory
through setter injection. The class looks roughly like this (no annotations necessary):
public class AdminConfigurationAction extends ConfluenceActionSupport implements FormAware {
public void setPluginSettingsFactory(PluginSettingsFactory pluginSettingsFactory) {
this.pluginSettingsFactory = pluginSettingsFactory;
}
// ...
}
This worked without any issues. The factory was properly injected and everything was fine.
Next I extended my existing REST controller so that it could access and read the plugin settings. I added the PluginSettingsFactory
as a new parameter to the controller’s constructor which at the time declared other Spring components to be injected. The controller class now looked like that:
@Scanned
@Path("/configuration")
public class RestPluginConfigurationService {
@ComponentImport
private PluginLicenseManager pluginLicenseManager;
@ComponentImport
private UserAccessor userAccessor;
@Inject
public RestPluginConfigurationService(PluginLicenseManager pluginLicenseManager, PluginSettingsFactory pluginSettingsFactory, UserAccessor userAccessor) {
this.pluginLicenseManager = pluginLicenseManager;
this.userAccessor = userAccessor;
// do something with the plugin settings factory...
}
// ...
}
After I redeployed my changes, the dependency injection in the Webwork action suddendly stopped working altogether. The setter AdminConfigurationAction#setPluginSettingsFactory()
wasn’t invoked anymore and subsequently I got a NullPointerException
whenever the PluginSettingsFactory
was accessed.
Now I was at a loss. I tried to add @Scanned
and @ComponentImport
annotations to the Webwork action and temporarily replaced setter-based injection with constructor-based injection. All I achieved by that was to summon eerie NoSuchBeanDefinitionExceptions
telling me that there is no such thing as a PluginSettingsFactory
object eligible for injection.
What could I do? The solution follows in my answer below.