Reputation: 14365
In spring, I am trying to resolve an Unresolved Bean Exception
when I try to do from my BlogController
:
@Autowired BlogService blogService;
org.springframework.stereotype.Service
service annotation.ApiApplication
application class is annotated with @ComponentScan("com.mypackage")
.@Service
and is in com.mypackage.service.blog.BlogService"
Autowired
, but it's @Repository
used by the service and located in com.mypackage.repository.blog.BlogRepository
can be imported by the controller.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
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 Bean
s.
com
+- example
+- myproject
+- Application.java
|
+- domain
| +- Customer.java
| +- CustomerRepository.java
|
+- service
| +- CustomerService.java
|
+- web
+- CustomerController.java
Upvotes: 1
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