1

I stack with above mentioned exception and really don't understate why it is appeared. I am using spring boot and declare bean through the annotation.

Application is executed by this class:

@SpringBootApplication
public class Application extends SpringBootServletInitializer {


@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {

    return application.sources(Application.class);
}

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

}

My problem bean has the following declaration:

@Service
public class OrderSvc extends AbstractService implements DAOService {

I try to put it in the following bean:

@RestController
public class OrderController {

@Autowired
CarSvc carSvc;

@Autowired
OrderSvc orderSvc;

and the exception is appeared: Could not autowire field: biz.Services.OrderSvc biz.controllers.rest.administrator.OrderController.orderSvc; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [biz.Services.OrderSvc] 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)}

I have also CarSvc bean that is located at the same package as OrderSvc and extends the same classes but there are no problems with it injection

@Service
public class CarSvc extends AbstractService implements DAOService<Car> {

Do you have any ideas why this exception appears ?

Bizon4ik
  • 2,604
  • 4
  • 20
  • 46

3 Answers3

3

Spring creates proxies for classes that declare @Transactional, so that it is able to add the transactional behaviour and intercepted calls to your object. If the bean extends any interface Spring is going to create a Dynamic Proxy using the JDK Reflection API and this can only be done by interface. The proxy is a new object implementing the same interface. So your target bean is not your implementation but a proxy. That is why you were getting a non qualify bean exception.

CGLIB, on the other hand, can create a proxy by subclassing.

So, to get it working, you need to change your bean type to the interface or you can configure cglib using @EnableTransactionManagement(proxyTargetClass = true).

alfcope
  • 2,327
  • 2
  • 13
  • 21
1

Try to to autowire your beans using interfaces rather than implementations :

@RestController
public class OrderController {

    @Autowired
    @Qualifier("carSvc")
    DAOService carSvc;

    @Autowired
    @Qualifier("orderSvc")
    DAOService orderSvc;

}

Edit : But before that you have to give names to your services :

@Service("carSvc")
public class CarSvc extends AbstractService implements DAOService<Car> {}

@Service("orderSvc")
public class OrderSvc extends AbstractService implements DAOService<Order> {}

What's going on here is that Spring generate proxies of your services based on the CarSvc, OrderSvc and implement the DAOService but does not extend the CarSvc, OrderSvc.

//somthing like this
class CarSvcProxy implement DAOService {

    public Object getOrder(Long id) {

        try {

            // ...

            txManager.commit();

        } catch (Exception ex) {
            txManager.rollback();
        }
    }
}

@RestController
public class OrderController {

    //So when you do this :
    @Autowired
    CarSvc carSvc;

    //it's somehow like if you did : 
    CarSvc carSvc = new CarSvcProxy(); //carSvc != CarSvcProxy

    //But this will work :
    DAOService carSvc = new CarSvcProxy(); //because CarSvcProxy implement DAOService

}
Mouad EL Fakir
  • 3,609
  • 2
  • 23
  • 37
0

I found the code which leads to exception but I really don't undestand why.

In my OrderSvc there is the following method:

@Transactional(readOnly = true)
public Object getOrder(Long id) {
    final Order order = getDAO().findOne(id);
    OrderDTO orderDTO = modelMapper.map(order, OrderDTO.class);
    return orderDTO;
}

So if the annotation @Transactional(readOnly = true) was excluded the application can be excecuted without problem... Do you have any ideas why this annotation lead to NoSuchBeanDefinitionException ?

Bizon4ik
  • 2,604
  • 4
  • 20
  • 46