'Spring-MVC - Error creating bean with name 'productsController': Injection of autowired dependencies failed

Im having a problem with a spring-mvc project. The @autowiring is not creating the beans required. Ive worked on this for over 4 days and followed all the search results. But nothing has worked. Can someone please take a look. Thank You

The error stack is this:

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'productsController': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private com.davis.ty.service.ProductsService com.davis.ty.controller.ProductsController.productsService; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [com.davis.ty.service.ProductsService] 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)} org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:292)

My servlet.xml is:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:mvc="http://www.springframework.org/schema/mvc"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:tx="http://www.springframework.org/schema/tx"
    xmlns:p="http://www.springframework.org/schema/p"
    xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd
        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
        http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd">


    <!-- DispatcherServlet Context: defines this servlet's request-processing infrastructure -->
    <context:annotation-config />
    <context:component-scan base-package="com.davis.ty" />

    <!-- Handles HTTP GET requests for /resources/** by efficiently serving up static resources in the ${webappRoot}/resources directory -->
    <mvc:resources mapping="/resources/**" location="/resources/" />

    <!-- Resolves views selected for rendering by @Controllers to .jsp resources in the /WEB-INF/views directory -->
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/WEB-INF/views/" />
        <property name="suffix" value=".jsp" />
    </bean>

    <bean id="propertyConfigurer"
        class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"
        p:location="/WEB-INF/jdbc.properties" />

    <bean id="messageSource"
        class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
        <property name="basename" value="classpath:messages" />
        <property name="defaultEncoding" value="UTF-8" />
    </bean>

    <bean id="dataSource"
        class="org.apache.commons.dbcp2.BasicDataSource" destroy-method="close"
        p:driverClassName="${jdbc.driverClassName}"
        p:url="${jdbc.databaseurl}" p:username="${jdbc.username}"
        p:password="${jdbc.password}" />


    <bean id="sessionFactory"
        class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
        <property name="dataSource" ref="dataSource" />
        <property name="configLocation">
            <value>classpath:hibernate.cfg.xml</value>
        </property>
        <property name="configurationClass">
            <value>org.hibernate.cfg.AnnotationConfiguration</value>
        </property>
        <property name="hibernateProperties">
            <props>
                <prop key="hibernate.dialect">${jdbc.dialect}</prop>
                <prop key="hibernate.show_sql">true</prop>
            </props>
        </property>
    </bean>

    <tx:annotation-driven />
    <bean id="transactionManager"
        class="org.springframework.orm.hibernate3.HibernateTransactionManager">
        <property name="sessionFactory" ref="sessionFactory" />
    </bean>

</beans>

My controller is:

package com.davis.ty.controller;

import java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

import com.davis.ty.domain.Products;
import com.davis.ty.service.ProductsService;

@Controller 
public class ProductsController {

    @Autowired 
    private ProductsService productsService;

     @RequestMapping(value = "/index", method = RequestMethod.GET)
     public String listProducts (Map<String, Object> map) {

         System.out.println("index");

            map.put("products", new Products());
            map.put("productsList", productsService.listProducts());

            return "index";
     }     


    @RequestMapping(value = "/add", method = RequestMethod.POST)
    public String addProducts(@ModelAttribute("products")
        Products products, BindingResult result) {

            productsService.addProducts(products);

            return "redirect:/index";
        }

    @RequestMapping("/delete/{Id}")
    public String deleteProducts(@PathVariable("Id")
        Integer Id) {

            productsService.removeProducts(Id);

            return "redirect:/index";
        }
}       

My service program is:

package com.davis.ty.service;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.davis.ty.dao.ProductsDAO;
import com.davis.ty.domain.Products;

@Service
public class ProductsServiceImpl {

    @Autowired
    private ProductsDAO productsDAO;

    @Transactional
    public void addProducts(Products products){

        productsDAO.addProduct(products);
    }

    @Transactional
    public List<Products> listProducts() {

        return productsDAO.listProducts();

    }

    @Transactional
    public void removeProducts(Integer id) {

        productsDAO.removeProducts(id);

    }
}   


Solution 1:[1]

Well, your ProductsServiceImpl class doesn't implement ProductsService... so there's no way that bean is injected in a field of type ProductsService.

Solution 2:[2]

From my experience, I just add @Repository at my DAO, maybe you can try to use it too

@Repository
public class ProductsDAO
{
}

Solution 3:[3]

How Spring autowire works is, Spring application context scans for all the classes inside the package and sub packages, specified by the component scan and internally creates a map by Type and Name. Incase of Type, value can be List of implementing classes, and by name its one.

Then whenever a @Autowire if encounter,

  • first it check by Type, so if you autowire using interface, it checks for all the implementation of that interface, and if only 1 if found then inject the same. (In case more then 1 is found, then you need to qaulify using the Qualifier and give proper name.

  • If above fails, if check by name, and injects.

If both fails, if gives NoSuchBeanDefinitionException,

So in your case, you have set the component scan, which is correct. Then while autowiring, you are giving Interface class name and the implementation class does not implements interface. So type check is failing, and also the by name is also failing, and hence you are getting NoSuchBeanDefinitionException.

To fix this, you will need to do what @JB Nizet is suggesting, so that #1 works and bean gets injected properly.

Solution 4:[4]

Add implements ProductService after public class ProductsServiceImpl

Solution 5:[5]

create a service interface and implement the interface method in service Impl class with @Overrride annotation.

public interface ProductService{

 List<Product> getProducts();

}

And then

@Service
public class ProductsServiceImpl implements  ProductService{

@Override
public List<Product> getProducts() {
    return productRepository.findAll();
}
 

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 JB Nizet
Solution 2 Mike S
Solution 3 lrathod
Solution 4 Lunayyko
Solution 5 TanvirChowdhury