NoSuchBeanDefinitionException: No qualifying bean of type 'com.atlassian.confluence.pages.AttachmentManager'

Hi folks,

I’m getting the following error while I installing and trying to enable my plugin in Confluence 8.8.

org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'substitutorFactoryImpl': Unsatisfied dependency expressed through constructor parameter 3; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'com.atlassian.confluence.pages.AttachmentManager' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {}
	at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:801)
	at org.springframework.beans.factory.support.ConstructorResolver.autowireConstructor(ConstructorResolver.java:224)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireConstructor(AbstractAutowireCapableBeanFactory.java:1372)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1222)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:582)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:542)
	at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:335)
	at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234)
	at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:333)
	at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:208)
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:955)
	at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:929)
	at org.eclipse.gemini.blueprint.context.support.AbstractDelegatedExecutionApplicationContext.access$1600(AbstractDelegatedExecutionApplicationContext.java:57)
	at org.eclipse.gemini.blueprint.context.support.AbstractDelegatedExecutionApplicationContext$4.run(AbstractDelegatedExecutionApplicationContext.java:322)
	at org.eclipse.gemini.blueprint.util.internal.PrivilegedUtils.executeWithCustomTCCL(PrivilegedUtils.java:85)
	at org.eclipse.gemini.blueprint.context.support.AbstractDelegatedExecutionApplicationContext.completeRefresh(AbstractDelegatedExecutionApplicationContext.java:287)
	at org.eclipse.gemini.blueprint.extender.internal.dependencies.startup.DependencyWaiterApplicationContextExecutor$CompleteRefreshTask.run(DependencyWaiterApplicationContextExecutor.java:137)
	at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
	at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
	at java.base/java.lang.Thread.run(Thread.java:834)
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'com.atlassian.confluence.pages.AttachmentManager' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {}
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.raiseNoMatchingBeanFound(DefaultListableBeanFactory.java:1801)
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1357)
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1311)
	at org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:911)
	at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:788)
	... 19 more

So I have a impl class dependent on AttachmentManager and annotated it as a component


import com.atlassian.confluence.pages.AttachmentManager;

@Component
public class SubstitutorFactoryImpl implements SubstitutorFactory {

    @Autowired
    public SubstitutorFactoryImpl(
        final SkinManager skinManager, 
        final BootstrapManager bootstrapManager, 
        final SpaceManager spaceManager, 
        @ConfluenceImport final AttachmentManager attachmentManager) {
        // Do something...
    }
}

I’m switching my project to adopting Atlassian-spring-scanner to prepare for platform 7. This SubstitutorFactoryImpl previously was defined as a component through the old-school mechanism <component> module, with the changes of adopting Atlasian-spring-scanner, I simply just annotated it with @Component.

When I installed and enabling the plugin, it gave me the error above. I also tried to follow the guide on this page which is used @ConfluenceImport to access Confluence Components, ended up getting the same error message.

This is how I set up the configuration of Spring scanner:
pom.xml

<plugin>
                <groupId>com.atlassian.plugin</groupId>
                <artifactId>atlassian-spring-scanner-maven-plugin</artifactId>
                <version>${atlassian.spring.scanner.version}</version>
                <executions>
                    <execution>
                        <goals>
                            <goal>atlassian-spring-scanner</goal>
                        </goals>
                        <!-- process-classes seems to be skipped if you are using scala
                             so perhaps use prepare-package -->
                        <phase>process-classes</phase>
                    </execution>
                </executions>
                <configuration>
                    <!-- Enable this to get build-time logging of annotations atlassian-spring-scanner-maven-plugin has noticed -->
                    <verbose>false</verbose>
                    <scannedDependencies>
                        <dependency>
                            <groupId>com.atlassian.plugin</groupId>
                            <artifactId>atlassian-spring-scanner-external-jar</artifactId>
                        </dependency>
                    </scannedDependencies>
                </configuration>
            </plugin>

spring-scanner.xml

<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/2"
       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/2
        http://www.atlassian.com/schema/atlassian-scanner/2/atlassian-scanner.xsd">
    <atlassian-scanner:scan-indexes/>
    <bean id="accessModeCompatService" class="com.atlassian.confluence.compat.api.service.accessmode.impl.DefaultAccessModeCompatService"/>
    <bean id="attachmentMimeTypeTranslator" class="com.atlassian.confluence.util.AttachmentMimeTypeTranslator"/>
<beans>

Due to the lack of familiarity with the Atlassian spring scanner(and also Java spring), I couldn’t figure out what causing this.

Any help would be appreciated!

Hm, looks good at the first view:

  • You don’t need an interface, just implement the class
  • Maybe try @Named and @Inject instead of @Component / @Autowired

Else:

  • Some logs in Maven?
  • provide full examples (where possible), pom.xml, atlassian-plugin.xml, code…

Our minimal spring-scanner.xml looks like this:

<?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/2"
       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/2
        http://www.atlassian.com/schema/atlassian-scanner/2/atlassian-scanner.xsd">
    <atlassian-scanner:scan-indexes/>
</beans>

Hey @amoerchen , would you mind elaborating more on what you mean by just implementing the class?

This is the my pom.xml

<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xmlns="http://maven.apache.org/POM/4.0.0"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>

    <parent>
        <groupId>com.adaptavist.confluence</groupId>
        <artifactId>ca-parent-pom</artifactId>
        <version>25</version>
    </parent>

    <artifactId>engine</artifactId>
    <groupId>com.adaptavist.confluence.theme</groupId>
    <version>1.8.4</version>

    <packaging>atlassian-plugin</packaging>
    <properties>
        <java.version>11</java.version>
        <atlassian.plugin.key>${project.groupId}.${project.artifactId}</atlassian.plugin.key>

        <atlassian.spring.scanner.version>2.2.3</atlassian.spring.scanner.version>
        <confluence.version>8.0.0</confluence.version>
        <gson.version>2.8.9</gson.version>
        <jersey.version>1.19.5-atlassian-9</jersey.version>
        <okhttp.version>4.10.0</okhttp.version>
        <opensymphony.oscore.version>2.3.0-atlassian-5</opensymphony.oscore.version>
        <opensymphony.propertyset.version>1.5</opensymphony.propertyset.version>
        <opensymphony.sitemesh.version>2.5-atlassian-11</opensymphony.sitemesh.version>
        <plugin.testrunner.version>2.0.2</plugin.testrunner.version>
        <platform.version>6.5.2</platform.version>
        <jsoup.version>1.7.2</jsoup.version>
        <testenv.version>1.7.1</testenv.version>
        <bouncycastle.version>1.75</bouncycastle.version>
        <hazelcast.version>3.8.6</hazelcast.version>
        <bitbucket.slug>builder-${project.artifactId}</bitbucket.slug>
        <metrics.version>3.1.5</metrics.version>
        <quick.reload.version>2.0.1</quick.reload.version>

        <ao.version>3.1.7</ao.version>
    </properties>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>com.atlassian.platform.dependencies</groupId>
                <artifactId>platform-public-api</artifactId>
                <version>${platform.version}</version>
                <type>pom</type>
                <scope>import</scope>
                <exclusions>
                    <exclusion>
                        <groupId>com.atlassian.crowd</groupId>
                        <artifactId>crowd-events</artifactId>
                    </exclusion>
                </exclusions>
            </dependency>
            <dependency>
                <groupId>com.atlassian.platform.dependencies</groupId>
                <artifactId>platform-deprecated-public-api</artifactId>
                <version>${platform.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <dependencies>
        <dependency>
             <groupId>com.atlassian.confluence</groupId>
             <artifactId>confluence</artifactId>
             <version>${confluence.version}</version>
             <scope>provided</scope>
        </dependency>
       <!-- other dependencies -->
    </dependencies>
    <build>
        <plugins>
            <plugin>
                <groupId>com.atlassian.plugin</groupId>
                <artifactId>atlassian-spring-scanner-maven-plugin</artifactId>
                <version>${atlassian.spring.scanner.version}</version>
                <executions>
                    <execution>
                        <goals>
                            <goal>atlassian-spring-scanner</goal>
                        </goals>
                        <!-- process-classes seems to be skipped if you are using scala
                             so perhaps use prepare-package -->
                        <phase>process-classes</phase>
                    </execution>
                </executions>
                <configuration>
                    <!-- Enable this to get build-time logging of annotations atlassian-spring-scanner-maven-plugin has noticed -->
                    <verbose>false</verbose>
                    <scannedDependencies>
                        <dependency>
                            <groupId>com.atlassian.plugin</groupId>
                            <artifactId>atlassian-spring-scanner-external-jar</artifactId>
                        </dependency>
                    </scannedDependencies>
                </configuration>
            </plugin>
            <plugin>
                <groupId>com.atlassian.maven.plugins</groupId>
                <artifactId>confluence-maven-plugin</artifactId>
                <version>${amps.version}</version>
                <extensions>true</extensions>
                <configuration>
                    <productVersion>${confluence.test.version}</productVersion>
                    <productDataVersion>${confluence.data.version}</productDataVersion>
                    <jvmArgs>-Xmx4g -Xms2g -XX:-UseGCOverheadLimit -Dsynchrony.proxy.enabled=false</jvmArgs>

                    <allowGoogleTracking>false</allowGoogleTracking>
                    <extractDependencies>false</extractDependencies>
                    <compressResources>false</compressResources>
                    <enableQuickReload>true</enableQuickReload>

                    <systemPropertyVariables>
                        <atlassian.darkfeature.site-wide.synchrony.opt-in.disable>true</atlassian.darkfeature.site-wide.synchrony.opt-in.disable>
                        <atlassian.darkfeature.site-wide.shared-drafts.disable>true</atlassian.darkfeature.site-wide.shared-drafts.disable>
                    </systemPropertyVariables>
                    <banningExcludes>
                        <exclude>com.google.guava:guava</exclude>
                        <exclude>com.atlassian.plugins.rest:atlassian-rest-common</exclude>
                        <exclude>javax.servlet:javax.servlet-api</exclude>
                    </banningExcludes>
                    <instructions>
                        <Atlassian-Plugin-Key>${atlassian.plugin.key}</Atlassian-Plugin-Key>
                        <Atlassian-Scan-Folders>META-INF/plugin-descriptors</Atlassian-Scan-Folders>
                        <Spring-Context>*</Spring-Context>
                        <Import-Package>
                            com.atlassian.plugin.osgi.bridge.external,
                            com.atlassian.confluence.*;resolution:="optional",
                            com.atlassian.confluence.plugin.descriptor.web.conditions,
                           *
                        </Import-Package>
                        <Export-Package>
                             com.google.gson;version="${gson.version}",
                             com.google.gson.reflect;version="${gson.version}",
                        </Export-Package>
                    </instructions>
              </configuration>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.6.1</version>
                <configuration>
                    <source>${java.version}</source>
                    <target>${java.version}</target>
                    <forceJavacCompilerUse>true</forceJavacCompilerUse>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

Try keeping your dependencies up to date and your pom.xml clean, i.e. Atlassian Spring Scanner is already 4.0.0, remove everything, you don’t need.

I mean, you don’t need an interface at all, just implement your service without an interface. Probably doesn’t solve your problem, but simplifies your code…

@Named
public class SubstitutorFactory {

    private final AttachmentManager attachmentManager;

    @Inject
    public SubstitutorFactory(@ComponentImport AttachmentManager attachmentManager) {
        this.attachmentManager= attachmentManager;
    }
}
1 Like