delucasvb
delucasvb

Reputation: 5813

Strange NoSuchBeanDefinitionException in Spring

I get a classic org.springframework.beans.factory.BeanCreationException:

Exception in thread "main" org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'Server': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private MyClass Server.myClass; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [MyClass] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:334)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1214)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:543)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:482)
    at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:306)
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:302)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:772)
    at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:839)
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:538)
    at org.springframework.context.annotation.AnnotationConfigApplicationContext.<init>(AnnotationConfigApplicationContext.java:84)
    at root.package.Application.main(Application.java:14)
Caused by: org.springframework.beans.factory.BeanCreationException: Could not autowire field: private MyClass Server.myClass; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [MyClass] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:573)
    at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:88)
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:331)
    ... 12 more
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [MyClass] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.raiseNoSuchBeanDefinitionException(DefaultListableBeanFactory.java:1373)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1119)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1014)
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:545)
    ... 14 more

"MyClass" in the stack trace above is of course the FQN of my class, which I replaced in this case (I can't show my package). It's a simple Netty Handler:

@Service
public class MyClass extends SimpleChannelInboundHandler<Protocol> implements Visitor {
    @Autowired
    private RestTemplate restTemplate;

    protected void channelRead0(ChannelHandlerContext channelHandlerContext, Protocol protocol) throws Exception {
        channelHandlerContext.writeAndFlush(protocol.accept(this, channelHandlerContext));
    }

    public Object visit(Protocol protocol, ChannelHandlerContext channelHandlerContext) {
        return restTemplate.exchange(...);
    }
}

The class that depends on MyClass:

@Component
public class Server {
    @Autowired
    private MyClass myClass;

    private ChannelFuture serverChannelFuture;

    @PostConstruct
    public void start() throws Exception {
        serverChannelFuture = bootstrap().bind(tcpPort()).sync();
    }

    @PreDestroy
    public void stop() throws Exception {
        serverChannelFuture.channel().close();
        serverChannelFuture.channel().closeFuture().sync();
    }

    private ServerBootstrap bootstrap() {
        // Bootstrap setup
    }
}

And my configuration:

@Configuration
@ComponentScan("root.package")
public class SpringConfig {
    @Bean
    public RestTemplate restTemplate() {
        return new RestTemplate();
    }

    @Bean
    public Logger logger() {
        return Logger.getLogger(InternalLoggerFactory.class.toString());
    }
}

All my classes are in either root.package or a subpackage of it. MyClass is in a subpackage as well.

I have no idea why this would cause the above Exception. I have other Services in my root.package package that are being autowired just fine! Does any one have an idea?

EDIT: after some further testing, it appears the "visit" method is the problem. If I rename it, the application boots fine. Could this be a bug in Spring?

EDIT 2: I celebrated too early. I renamed the method in my Visitor interface and now I'm back to the same problem. Even if I comment out my interface, I cannot have any method with the same name as that interface. MyClass is the only class that implements Visitor that is a Spring bean.

Upvotes: 1

Views: 3371

Answers (3)

delucasvb
delucasvb

Reputation: 5813

This answer set me on my way: Spring instantiates bean but can't use it

The problem was that I use Spring aspects as well, which are configured with

@EnableAspectJAutoProxy

However, by default, this enables JDK proxies, which work differently (see the answer of that question for more info).

@EnableAspectJAutoProxy(proxyTargetClass=true)

Enables CGLIB proxies, which was the solution to my problem.

Upvotes: 0

John Giotta
John Giotta

Reputation: 16984

The thing about Spring annotations is that classes must reside in the same package tree as the runner or context.

For example, if your Spring application class is in com.dippity.dot.myapp all other classes annotated as @Service, @Component, etc must also be down the com.dippity.dot.myapp package tree.

A @Service annotated package could live com.dippity.dot.myapp.service and work.

Upvotes: 0

UKoehler
UKoehler

Reputation: 131

Your class MyClass has no package name?

"No qualifying bean of type [MyClass]" 

in your Configuration you set the componentscan to a specififc package

@ComponentScan("root.package")

so Spring could not found your beans.

to fix: remove ("root.package") or add the package "root.package" to your classes

Upvotes: 1

Related Questions