AbstractBlueprintContextProvider API is deprecated?
Asked by Russell Bateman:

Hi guys,

A few months ago I was developing a Confluence plugin and all was well. I have since returned with the latest Atlassian SDK. Now when I run the plugin using an 'atlas-run' command the plugin gets disabled.

This is the log output that implies there is an issue some where:

```
[INFO] <PLUGIN-NAME>/hello_blueprint/MyBlueprintListener.java: Some input files use or override a deprecated API.[INFO] <PLUGIN-NAME>hello_blueprint/MyBlueprintListener.java: Recompile with -Xlint:deprecation for details.[INFO] [talledLocalContainer] 2017-04-06 16:21:39,865 ERROR [localhost-startStop-1] [atlassian.plugin.manager.DefaultPluginManager] enableConfiguredPluginModule There was an error loading the descriptor 'null' of plugin '<PLUGIN-NAME>'. Disabling.[INFO] [talledLocalContainer] com.atlassian.plugin.PluginParseException: Unable to load the module's display conditions: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'com.bsquare.emea.plugins.hello_blueprint.HierarchyContextProvider': Unsatisfied dependency expressed through constructor argument with index 0 of type [com.atlassian.confluence.languages.LocaleManager]: No qualifying bean of type [com.atlassian.confluence.languages.LocaleManager] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {}; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [com.atlassian.confluence.languages.LocaleManager] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {}[INFO] [talledLocalContainer] at com.atlassian.confluence.plugins.createcontent.extensions.ContentTemplateModuleDescriptor.getContextProvider(ContentTemplateModuleDescriptor.java:265)[INFO] [talledLocalContainer] at com.atlassian.confluence.plugins.createcontent.extensions.ContentTemplateModuleDescriptor.enabled(ContentTemplateModuleDescriptor.java:232)[INFO] [talledLocalContainer] at com.atlassian.plugin.manager.DefaultPluginManager.notifyModuleEnabled(DefaultPluginManager.java:1991)[INFO] [talledLocalContainer] at com.atlassian.plugin.manager.DefaultPluginManager.enableConfiguredPluginModule(DefaultPluginManager.java:1738)[INFO] [talledLocalContainer] at com.atlassian.plugin.manager.DefaultPluginManager.enableConfiguredPluginModules(DefaultPluginManager.java:1715)[INFO] [talledLocalContainer] at com.atlassian.plugin.manager.DefaultPluginManager.enableDependentPlugins(DefaultPluginManager.java:1227)[INFO] [talledLocalContainer] at com.atlassian.plugin.manager.DefaultPluginManager.addPlugins(DefaultPluginManager.java:1188)[INFO] [talledLocalContainer] at com.atlassian.plugin.manager.DefaultPluginManager.lateStartup(DefaultPluginManager.java:634)[INFO] [talledLocalContainer] at com.atlassian.confluence.plugin.ConfluencePluginManager.lateStartup(ConfluencePluginManager.java:147)[INFO] [talledLocalContainer] at com.atlassian.confluence.plugin.PluginFrameworkContextListener.contextInitialized(PluginFrameworkContextListener.java:79)[INFO] [talledLocalContainer] at org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java:4842)[INFO] [talledLocalContainer] at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5303)[INFO] [talledLocalContainer] at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:147)[INFO] [talledLocalContainer] at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:725)[INFO] [talledLocalContainer] at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:701)[INFO] [talledLocalContainer] at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:717)[INFO] [talledLocalContainer] at org.apache.catalina.startup.HostConfig.deployWAR(HostConfig.java:940)[INFO] [talledLocalContainer] at org.apache.catalina.startup.HostConfig$DeployWar.run(HostConfig.java:1816)[INFO] [talledLocalContainer] at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)[INFO] [talledLocalContainer] at java.util.concurrent.FutureTask.run(FutureTask.java:266)[INFO] [talledLocalContainer] at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)[INFO] [talledLocalContainer] at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)[INFO] [talledLocalContainer] at java.lang.Thread.run(Thread.java:745)[INFO] [talledLocalContainer] Caused by: com.atlassian.plugin.web.conditions.ConditionLoadingException: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name '<PLUGIN-NAME>.HierarchyContextProvider': Unsatisfied dependency expressed through constructor argument with index 0 of type [com.atlassian.confluence.languages.LocaleManager]: No qualifying bean of type [com.atlassian.confluence.languages.LocaleManager] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {}; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [com.atlassian.confluence.languages.LocaleManager] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {}[INFO] [talledLocalContainer] at com.atlassian.confluence.plugin.descriptor.web.ConfluenceWebFragmentHelper.loadComponent(ConfluenceWebFragmentHelper.java:35)[INFO] [talledLocalContainer] at com.atlassian.confluence.plugin.descriptor.web.ConfluenceWebFragmentHelper.loadContextProvider(ConfluenceWebFragmentHelper.java:58)[INFO] [talledLocalContainer] at com.atlassian.confluence.plugins.createcontent.extensions.ContentTemplateModuleDescriptor.getContextProvider(ContentTemplateModuleDescriptor.java:255)[INFO] [talledLocalContainer] ... 22 more[INFO] [talledLocalContainer] Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name '<PACKAGE_NAME>.HierarchyContextProvider': Unsatisfied dependency expressed through constructor argument with index 0 of type [com.atlassian.confluence.languages.LocaleManager]: No qualifying bean of type [com.atlassian.confluence.languages.LocaleManager] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {}; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [com.atlassian.confluence.languages.LocaleManager] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {}[INFO] [talledLocalContainer] at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:749)[INFO] [talledLocalContainer] at org.springframework.beans.factory.support.ConstructorResolver.autowireConstructor(ConstructorResolver.java:185)[INFO] [talledLocalContainer] at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireConstructor(AbstractAutowireCapableBeanFactory.java:1143)[INFO] [talledLocalContainer] at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1046)[INFO] [talledLocalContainer] at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:510)[INFO] [talledLocalContainer] at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:482)[INFO] [talledLocalContainer] at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:342)[INFO] [talledLocalContainer] at sun.reflect.GeneratedMethodAccessor171.invoke(Unknown Source)[INFO] [talledLocalContainer] at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)[INFO] [talledLocalContainer] at java.lang.reflect.Method.invoke(Method.java:498)[INFO] [talledLocalContainer] at com.atlassian.plugin.osgi.spring.DefaultSpringContainerAccessor.createBean(DefaultSpringContainerAccessor.java:97)[INFO] [talledLocalContainer] at com.atlassian.confluence.plugin.ConfluencePluginUtils.instantiatePluginModule(ConfluencePluginUtils.java:150)[INFO] [talledLocalContainer] at com.atlassian.confluence.plugin.descriptor.web.ConfluenceWebFragmentHelper.loadComponent(ConfluenceWebFragmentHelper.java:33)[INFO] [talledLocalContainer] ... 24 more
```

It seems that something in my HierarchyContextProvider method is deprecated. This is taken from the example class in the "intermediate" blueprint example that uses this class to generate a page title. The tutorial (that is found here: <https://developer.atlassian.com/confdev/confluence-plugin-guide/confluence-blueprints/write-an-intermediate-blueprint-plugin>) doesn't seem to reflect this change.

It should also be noted that I had changed my pom.xml to reflect the new changes to the Atlassian Spring Byte Code Scanner. The changes follow this guide: <https://bitbucket.org/atlassian/atlassian-spring-scanner.>

I'm unfamiliar with Java Spring but I had placed a "@Hardwired" directive about the method to see if that would achieve anything. I'm not sure it did!

If anyone has a fix/workaround for this, any help would be much appreciated!

Thanks,

Russell Bateman


Answers:
author: Panos
body: What is your scanner version? 2 and higher or 1.xx?

First do this:

1. Mark your class with @Scanned
2. Mark the LocaleManager with @ComponentImport
3. Mark the constructor of the class with @Inject

It should look like this:

```
@Scannedpublic class HierarchyContextProvider{    @ComponentImport    private final LocaleManager localeManager;    @Inject    public HierarchyContextProvider(LocaleManager localeManager){        this.localeManager=localeManager;    }}
```

Otherwise, you need to use \<component-import\> in the atlassian-plugin.xml file to import the localemanager, remove the @Scanned, @ComponentImport and replace the @Inject with @Autowired (not @hardwired)

Atlassian scanner for \>2.x version will complain if \<component\> or \<component-import\> are found in the atlassian-plugin.xml so you can't mix both.

Edit: It is not deprecated, just Spring can't find the bean

comments: author: Russell Bateman
body: Hi Panos,

Thank you for your detailed answer! However when I make these changes I get these compilation errors:

```
[ERROR] Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.6.1:compile (default-compile) on project <PROJECT_NAME>: Compilation failure: Compilation failure:[ERROR] <PROJECT_NAME>/hello_blueprint/HierarchyContextProvider.java:[14,52] cannot find symbol[ERROR] symbol:   class Scanned[ERROR] location: package org.springframework.beans.factory.annotation[ERROR] <PROJECT_NAME>/hello_blueprint/HierarchyContextProvider.java:[15,52] cannot find symbol[ERROR] symbol:   class ComponentImport[ERROR] location: package org.springframework.beans.factory.annotation[ERROR] <PROJECT_NAME>/hello_blueprint/HierarchyContextProvider.java:[16,13] cannot find symbol[ERROR] symbol:   class inject[ERROR] location: package javax <PROJECT_NAME>/hello_blueprint/HierarchyContextProvider.java:[22,2] cannot find symbol[ERROR] symbol: class Scanned[ERROR] <PROJECT_NAME>/hello_blueprint/HierarchyContextProvider.java:[25,6] cannot find symbol[ERROR] symbol:   class ComponentImport[ERROR] location: class <PROJECT_NAME>/hello_blueprint/HierarchyContextProvider.java:[30,6] cannot find symbol[ERROR] symbol:   class Inject[ERROR] location: class <PROJECT_NAME>.HierarchyContextProvider
```

I have added these imports to the top of my HierarchyContextProvider.java file:

```
import org.springframework.beans.factory.annotation.Autowired;import org.springframework.beans.factory.annotation.Scanned;import org.springframework.beans.factory.annotation.ComponentImport;import javax.inject;
```

Any assistance would be appreciated!


author: Panos
body: Post your pom.xml and these are the imports

```
import org.springframework.beans.factory.annotation.Autowired;import com.atlassian.plugin.spring.scanner.annotation.component.Scanned;import com.atlassian.plugin.spring.scanner.annotation.imports.ComponentImport;import javax.inject.Inject;
```

Remember, either (Scanned and Inject) or Autowired


author: Russell Bateman
body: Hi Panos,

Those imports allieviated the compiliation errors I was getting! There is still an issue somewhere. The example featured other Java components that I will probably need to go through and add these "Scanned", "Inject" or "Autowire" directives to.

Here is the copy of my pom.xml: <https://pastebin.com/bjgNHJ3H>

What specifies which directive I need for a class/method?

Once again thanks for all the help


author: Panos
body: Still an issue? Are you still getting the same error or other errors?


author: Russell Bateman
body: There still is an issue I'm afraid, but at least its different! This is the error log:

\[INFO\] \[talledLocalContainer\] 2017-04-07 14:27:05,581 INFO \[localhost-startStop-1\] \[atlassian.plugin.manager.DefaultPluginManager\] broadcastPluginDisabling Disabling \<PLUGIN_NAME\>  
\[INFO\] \[talledLocalContainer\] 2017-04-07 14:27:05,583 ERROR \[localhost-startStop-1\] \[plugin.osgi.factory.OsgiPlugin\] logAndClearOustandingDependencies Plugin 'PLUGIN_NAME' never resolved service '\&helloService' with filter '(\&(objectClass=\<PLUGIN_NAME\>.HelloService)(objectClass=\<PLUGIN_NAME\>.HelloService))'

It's got something to do with the 'HelloService.java' file (taken from the example mentioned earlier). There is hardly any code inside it, but I have not placed the directives there yet.

Also in my atlassian-plugin.xml I have these tags:

```
<!-- import from the product container --> <component-import key="applicationProperties" interface="com.atlassian.sal.api.ApplicationProperties" /> <!-- import from the product container -->  <component-import key="eventPublisher" interface="com.atlassian.event.api.EventPublisher"/> <component key="eventListener" class="com.bsquare.emea.plugins.hello_blueprint.MyBlueprintListener"/>
```

Should they be removed?


author: Panos
body: Good. Now on your HelloService class add @ExportAsService. That should fix it. If not instead of above use @Component. Since you use 1.2.13 scanner you dont have to remove from thr xml, but if you do you need to use @ComponentImport


author: Panos
body: In the class! Not interface


author: Russell Bateman
body: What would be the imports for the "ExportAsService" and "Component" directives?


author: Russell Bateman
body: Okay I added the directives for ExportAsService next to the HelloService class. So now it looks like this:

```
@ExportAsServicepublic class DefaultHelloService implements HelloService{    @Override    public String getFriendlyDate()    {        return DateFormat.getDateInstance(DateFormat.LONG).format(new Date());    }    @Override    public String getFriendlyDateTime()    {        return DateFormat.getDateTimeInstance(DateFormat.LONG, DateFormat.LONG).format(new Date());    }}
```

The error still seems to persist. So I placed an "@Component" directive instead of an "@ExportAsService". However this seemed to generate compiliation errors (symbol not found) when I imported this package: import org.springframework.stereotype.Component;.

Thanks for all your help so far!

Any assistance you can give with this would be much appreciated!


author: Panos
body: oh you need also the @named along with @exportasservice. Sorry it slipped my mind:

```
import javax.inject.Named;

@ExportAsService
@Named("defaultHelloService")public class DefaultHelloService implements HelloService{    @Override    public String getFriendlyDate()    {        return DateFormat.getDateInstance(DateFormat.LONG).format(new Date());    }    @Override    public String getFriendlyDateTime()    {        return DateFormat.getDateTimeInstance(DateFormat.LONG, DateFormat.LONG).format(new Date());    }}
```


author: Russell Bateman
body: Hi Panos,

Thanks for your reply! I have tried putting the @Named directive in the class definition as you recommended but I still get the same issue.

In the tutorial it gives you an example component ("MyPluginComponent"). In there it seems to have all of these "@" directives. I've noticed that the "@ExportAsService" directive has a name at the end of it, here is what it looks like:

```
@ExportAsService ({MyPluginComponent.class})@Named ("myPluginComponent")public class MyPluginComponentImpl implements MyPluginComponent{     @ComponentImport      private final ApplicationProperties applicationProperties;      @Inject      public MyPluginComponentImpl(final ApplicationProperties  applicationProperties)       {                this.applicationProperties = applicationProperties;        }      public String getName()      {         if(null != applicationProperties)         {             return "myComponent:" + applicationProperties.getDisplayName();         }          return "myComponent";       }}
```

I tried putting "@ExportAsService ({HelloService.class})" in the service class but this made no difference.

Any other ideas?

Thanks,

Russell Bateman


author: Panos
body: a) You miss the @Scanned. If you are using componets from confluence, you need the scanned. In your case you are using the ApplicationProperties

b) Check your resources/META-INF/spring/plugin-context.xml file. Should looke like

```
<?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://www.springframework.org/schema/beans"       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"       xmlns:atlassian-scanner="http://www.atlassian.com/schema/atlassian-scanner"       xsi:schemaLocation="http://www.springframework.org/schema/beans        http://www.springframework.org/schema/beans/spring-beans-2.5.xsd        http://www.atlassian.com/schema/atlassian-scanner        http://www.atlassian.com/schema/atlassian-scanner/atlassian-scanner.xsd">    <atlassian-scanner:scan-indexes/></beans>
```


author: Russell Bateman
body: Hi Panos,

Thanks for the prompt reply. I checked my plugin-context.xml file and it does match your example correctly. Theres still an issue with the HelloService class, this is what it currently looks like:

```
import com.atlassian.plugin.spring.scanner.annotation.export.ExportAsService;import javax.inject.Named;import java.text.DateFormat;import java.util.Date;/** * An unnecessary service that shows how a ContextProvider can retrieve information from *any* plugin-available * Component. * * @since 5.0 */ @ExportAsService ({HelloService.class}) @Named ("defualtHelloService")public class DefaultHelloService implements HelloService{    @Override    public String getFriendlyDate()    {        return DateFormat.getDateInstance(DateFormat.LONG).format(new Date());    }    @Override    public String getFriendlyDateTime()    {        return DateFormat.getDateTimeInstance(DateFormat.LONG, DateFormat.LONG).format(new Date());    }}
```

Is there anything else that should be here?

Also, I took out the \<component\> and \<component-import\> statements from my atlassian-plugin.xml file as it starting failing to validate it, once I had enabled validation in my POM.xml. Could it be something there causing this issue?


author: Panos
body: Weird.. Although the spelling in @named is wrong, that shouldnot be the case. I can only suggest fix the spelling (just hurts my eyes :) ) and then add a default constructor


author: Russell Bateman
body: I fixed the spelling of "default" in the @Named directive and tried adding a default constructor to the class but its still getting the same error.

<br />

Thanks for your help anyway! I'll mark your initial response as the answer as it fixed the original issue. I'll see if anyone on the dev-forums can think of anything else. But really I could just remove the HelloService component altogether as it doesn't do much.


author: Panos
body: Can you post your source code to the github or something public? I am really curious...


author: Russell Bateman
body: Hi Panos,

Yeah I'll put it up on GitHub later if you want to take a look at it. I'll post a link when it's up!

Thanks for all the help!


author: Russell Bateman
body: Here is the repo:

<https://github.com/RussellSBateman/EMEAConfluencePlugin>

Thanks again,

Russell Bateman


author: Panos
body: So, a) your \<export\> in pom.xml is wrong. You are exporting some api package, but the helloservice interface exists in another package.

b) Your pom.xml uses wrongly the scanner (as if it was v2)

c) You have declared a lot of blueprints without i18n-key:

```
init i18n-name-key is a required attribute of <content-template> for module: com.bsquare.emea.plugins.EMEAPlugin:customermeetings-template
```

d) HelloService must not be marked as @ComponentImport

The fix for a and b is in [here](https://pastebin.com/iAUKYqCZ).   
Or you can clone the whole project [here](https://bitbucket.org/panos_karampis/emeaconfluenceplugin). Apologies for the rebase in a new project, i realized i didn't fork way too late.


author: Russell Bateman
body: Hi Panos,

Thanks very much for your time. The plugin works fine now!

Thanks,

Russell Bateman


author: Sam Hall
body: Hi Russell - Welcome to the community. Since your question is development related, you might want to try asking this over at: <https://community.developer.atlassian.com> as well (if you haven't already).

There are a lot of helpful and experienced people over there, so you will probably get a quicker response.

You can read more about the Developer Community in this article: <https://community.atlassian.com/t5/Feedback-Forum-articles/The-Atlassian-Developer-Community/ba-p/459061>

comments: author: Russell Bateman
body: Hi Sam,

Thank you for your reply! I'll make sure I use the dedicated developer community section in the future.

Thanks,

Russell Bateman


Tags: confluence-app

confluence-development

java