javaspring-bootcomponent-scan

org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'com.example.simple.RealApplication' available


I am having trouble understanding on why my Bean RealApplication is not registered / found.

File DemoApplication.java:

package com.example.simple;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

@SpringBootApplication
public class DemoApplication
{
    public static void main(String[] args)
    {
        SpringApplication.run(DemoApplication.class, args);

        AnnotationConfigApplicationContext ctx = 
            new AnnotationConfigApplicationContext();
        ctx.refresh();

        RealApplication app = ctx.getBean(RealApplication.class);
        app.run();

        ctx.close();
    }
}

File RealApplication.java:

package com.example.simple;

import org.springframework.stereotype.Component;

@Component
public class RealApplication
{
    public void run()
    {
        System.out.println("Hello World!");
    }
}

However, strangely, this piece of code works:

File DemoApplication.java:

package com.example.simple;

import org.springframework.boot.SpringApplication;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class DemoApplication
{
    public static void main(String[] args)
    {
        SpringApplication.run(DemoApplication.class, args);

        AnnotationConfigApplicationContext ctx = 
            new AnnotationConfigApplicationContext("com.example.simple");

        RealApplication app = ctx.getBean(RealApplication.class);
        app.run();

        ctx.close();
    }
}

The class RealApplication was unchanged.

Output was:

Hello World!

My maven pom.xml looks like this:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    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>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.1.6.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.example</groupId>
    <artifactId>simple-boot</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>demo</name>
    <description>Demo project for Spring Boot</description>

    <properties>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>

        <!-- https://mvnrepository.com/artifact/javax.inject/javax.inject -->
        <dependency>
            <groupId>javax.inject</groupId>
            <artifactId>javax.inject</artifactId>
            <version>1</version>
        </dependency>

    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

For some strange reason, the component-scan is not picking up the RealApplication Bean when i only use the @SpringBootApplication annotation, even though the two classes are the same package.

But it is able to find it when i specify the package to scan in the constructor to AnnotationConfigApplicationContext


Solution

  • Are you showing the wrong codes ? The codes you show are always creating two application contexts , one is AnnotationConfigApplicationContext and other is created using spring-boot way which involves using SpringApplication and @SpringBootApplication.

    And you always get the RealApplication bean from the context created by the AnnotationConfigApplicationContext but not from the context created by the spring boot. To test if the RealApplication bean is really created in the latter case , you have to get the bean from the context returned from SpringApplication.run():

    ApplicationContext context = SpringApplication.run(DemoApplication.class, args);
    RealApplication app = context.getBean(RealApplication.class);
    app.run();