Dimitri Kopriwa
Dimitri Kopriwa

Reputation: 14365

Why do I get NoSuchBeanDefinitionException for bean 'com.mypackage.service.blog.BlogService'

In spring, I am trying to resolve an Unresolved Bean Exception when I try to do from my BlogController:

@Autowired BlogService blogService;

My application class looks like this :

package com.mypackage;

import com.mypackage.core.Core;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.web.MultipartAutoConfiguration;
import org.springframework.context.annotation.ComponentScan;

@SpringBootApplication
@ComponentScan({
        "com.mypackage",
        "com.mypackage.service.blog"
})
public class ApiApplication {

    private static final Logger logger = LoggerFactory.getLogger(ApiApplication.class);

    public static void main(String[] args) throws Exception {
        org.apache.ibatis.logging.LogFactory.useSlf4jLogging();
        SpringApplication.run(ApiApplication.class, args);
        logger.info("Application started!");
    }

}

This is my com.mypackage.controller.blog.BlogController:

@RestController
@RequestMapping("/blogs")
public class BlogController {

  @Autowired
  private BlogService blogService;

  @PostMapping
  @ResponseStatus(HttpStatus.CREATED)
  Long create(@RequestBody Blog blog) {
    blogService.insert(blog);
    return blog.getId();
  }

My com.mypackage.service.blog.BlogService class:

public interface BlogService extends CrudService<Blog, Long> {
}

My com.mypackage.service.blog.impl.BlogServiceImpl class:

@Service
@UserManagementTx
public class BlogServiceImpl extends AbstractCrudService<BlogRepository, Blog, Long> {

    @Autowired
    public BlogServiceImpl(BlogRepository repository) {
        super(repository);
    }

}

I have turned debug log and I am trying to find some hint why the Service is not imported.

org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'com.mypackage.service.blog.BlogService' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}

Should I take some particular classpath to DEBUG and the other to INFO ? I don't see the services creation and classpath in my current DEBUG logs.

Upvotes: 0

Views: 591

Answers (2)

Mehraj Malik
Mehraj Malik

Reputation: 15854

Point #1

@ComponentScan is not needed here, just remove it from your main class of application i.e. ApiApplication and it will work.

Point #2

As we can see BlogServiceImpl does not implement BlogService which means there is no concrete implementation of BlogService hence Bean cannot be created.

You need to implement BlogServiceImpl the interface BlogService to tell the spring that BlogServiceImpl is the implementation of BlogService

public class BlogServiceImpl implements BlogService

and I would highly recommend you to follow package structure As per spring docs then you will not need to include @ComponentScan to get created Beans.

com
 +- example
     +- myproject
         +- Application.java
         |
         +- domain
         |   +- Customer.java
         |   +- CustomerRepository.java
         |
         +- service
         |   +- CustomerService.java
         |
         +- web
             +- CustomerController.java

Upvotes: 1

Anton Tupy
Anton Tupy

Reputation: 969

You can use class below to view which beans was created in context. Mey be this will help.

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import java.util.Arrays;

@Component
class BeansLogger {
    private static final Logger LOGGER = LoggerFactory.getLogger(BeansLogger.class);

    private final ApplicationContext applicationContext;

    @Autowired
    public BeansLogger(ApplicationContext applicationContext) {
        this.applicationContext = applicationContext;
    }

    @PostConstruct
    public void init() {
        final String[] beanDefinitionNames = applicationContext.getBeanDefinitionNames();
        Arrays.sort(beanDefinitionNames);
        LOGGER.debug("Registered beans: {}", Arrays.asList(beanDefinitionNames));
    }
}

Upvotes: 1

Related Questions