-1

I am trying a small application and still very new to Spring mvc framework. I have a controller class and a bean config xml file. I am able to use the bean if I call getBean() method. However my plan is to use autowiring to inject the bean in my controller rather then using getBean(). But I get error. I am using maven to build my project. Here is my Controller class in a package under src/main/java

package com.eat.menu.controller;

import java.util.Date;

import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.support.GenericXmlApplicationContext;
import org.springframework.data.mongodb.core.MongoOperations;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

import com.eat.admin.config.Globals.DishCategory;
import com.eat.admin.config.Globals.MenuStatus;
import com.eat.menu.model.Dish;
import com.eat.menu.model.Menu;

@Controller
public class MenuController {


private static int counter = 0;
    private static final String VIEW_INDEX = "index";
    private final static org.slf4j.Logger logger =

LoggerFactory.getLogger(MenuController.class);

    @Autowired
    private MongoTemplate mongoTemplate;

    public MongoTemplate getMongoTemplate() {
        return mongoTemplate;
    }

    public void setMongoTemplate(MongoTemplate mongoTemplate) {
        this.mongoTemplate = mongoTemplate;
    }

    @RequestMapping(value = "/", method = RequestMethod.GET)
    public String welcome(ModelMap model) {

        model.addAttribute("message", "Welcome");
        model.addAttribute("counter", ++counter);
        logger.debug("[welcome] counter : {}", counter);

        // Spring uses InternalResourceViewResolver and return back index.jsp
        return VIEW_INDEX;

    }

    @RequestMapping(value = "/{name}", method = RequestMethod.GET)
    public String welcomeName(@PathVariable String name, ModelMap model) {

        model.addAttribute("message", "Welcome " + name);
        model.addAttribute("counter", ++counter);
        logger.debug("[welcomeName] counter : {}", counter);
        return VIEW_INDEX;

    }

    @RequestMapping(value = "/menu", method = RequestMethod.GET)
    public String createMenu(ModelMap model) {
        ApplicationContext ctx = new GenericXmlApplicationContext("BaseConfig.xml");
//Avoid using this
        MongoOperations mongoOperation = (MongoOperations) ctx.getBean("mongoTemplate");

        Dish dish1 = new Dish();
        Date now = new Date();
        dish1.setName("Butter Chicken");
        dish1.setCategory(DishCategory.ENTREE);
        dish1.setCreateDate(now);
        dish1.setUpdateDate(now);

        Dish dish2 = new Dish();
        dish2.setName("Korma Chicken");
        dish2.setCategory(DishCategory.ENTREE);
        dish2.setCreateDate(now);
        dish2.setUpdateDate(now);

        Dish [] dishes = new Dish[2];
        dishes[0] = dish1;
        dishes[1] = dish2;

        Menu menu = new Menu();
        menu.setCompanyId(1);
        menu.setCreateDate(now);
        menu.setUpdateDate(now);
        menu.setDishes(dishes);
        menu.setMenuStatus(MenuStatus.ACTIVE);

        mongoOperation.save(menu);

        Query searchMenuQuery = new Query(Criteria.where("companyId").is(1));

        // find the saved user again.
        Menu m = mongoOperation.findOne(searchMenuQuery, Menu.class);
        return VIEW_INDEX;
    }
}

Here is my baseConfig.xml under src/main/resources

<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mongo="http://www.springframework.org/schema/data/mongo"
xsi:schemaLocation="http://www.springframework.org/schema/context
      http://www.springframework.org/schema/context/spring-context.xsd
      http://www.springframework.org/schema/data/mongo
      http://www.springframework.org/schema/data/mongo/spring-mongo.xsd
      http://www.springframework.org/schema/beans
      http://www.springframework.org/schema/beans/spring-beans.xsd">

<context:annotation-config/>

<mongo:mongo host="127.0.0.1" port="27017" />
<mongo:db-factory dbname="eatMongoDB" />

<bean id="mongoTemplate" class="org.springframework.data.mongodb.core.MongoTemplate">
    <constructor-arg name="mongoDbFactory" ref="mongoDbFactory" />
</bean>

<bean id="menuController" class="com.eat.menu.controller.MenuController">
    <property name="mongoTemplate" value="mongoTemplate"/>
</bean>

Please let me know if I am doing anything wrong because I get the following error:

SEVERE: Exception sending context initialized event to listener instance of class org.springframework.web.context.ContextLoaderListener
org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'menuController': Unsatisfied dependency expressed through field 'mongoTemplate': No qualifying bean of type [org.springframework.data.mongodb.core.MongoTemplate] found for dependency [org.springframework.data.mongodb.core.MongoTemplate]: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [org.springframework.data.mongodb.core.MongoTemplate] found for dependency [org.springframework.data.mongodb.core.MongoTemplate]: 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:569)
    at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:88)
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:349)
    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:776)
    at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:861)
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:541)
    at org.springframework.web.context.ContextLoader.configureAndRefreshWebApplicationContext(ContextLoader.java:444)
    at org.springframework.web.context.ContextLoader.initWebApplicationContext(ContextLoader.java:326)
    at org.springframework.web.context.ContextLoaderListener.contextInitialized(ContextLoaderListener.java:107)
    at org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java:4715)
    at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5177)
    at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:152)
    at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1403)
    at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1393)
    at java.util.concurrent.FutureTask.run(Unknown Source)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
    at java.lang.Thread.run(Unknown Source)
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [org.springframework.data.mongodb.core.MongoTemplate] found for dependency [org.springframework.data.mongodb.core.MongoTemplate]: 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.raiseNoMatchingBeanFound(DefaultListableBeanFactory.java:1406)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1057)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1019)
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:566)
    ... 24 more

I am adding 3 config files for clarity and let me know if anything may be required: The first one is pom file:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> 4.0.0 com.eat EatApp war 1.0-SNAPSHOT EatApp Maven Webapp http://maven.apache.org

<properties>
    <jdk.version>1.8</jdk.version>
    <spring.version>4.3.2.RELEASE</spring.version>
    <jstl.version>1.2</jstl.version>
    <junit.version>4.12</junit.version>
    <logback.version>1.1.7</logback.version>
    <jcl-over-slf4j.version>1.7.21</jcl-over-slf4j.version>
</properties>

 <dependencies>
    <dependency>
        <groupId>javax.servlet</groupId>
        <artifactId>javax.servlet-api</artifactId>
        <version>3.1.0</version>
        <scope>provided</scope>
    </dependency>

    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>${junit.version}</version>
        <scope>test</scope>
    </dependency>

    <dependency>
        <groupId>org.slf4j</groupId>
        <artifactId>jcl-over-slf4j</artifactId>
        <version>${jcl-over-slf4j.version}</version>
    </dependency>

    <dependency>
        <groupId>ch.qos.logback</groupId>
        <artifactId>logback-classic</artifactId>
        <version>${logback.version}</version>
    </dependency>

    <!-- Spring Framework -->
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-core</artifactId>
        <version>${spring.version}</version>
        <exclusions>
            <exclusion>
                <groupId>commons-logging</groupId>
                <artifactId>commons-logging</artifactId>
            </exclusion>
        </exclusions>
    </dependency>

    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-web</artifactId>
        <version>${spring.version}</version>
    </dependency>

    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-webmvc</artifactId>
        <version>${spring.version}</version>
    </dependency>

    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context</artifactId>
        <version>${spring.version}</version>
    </dependency>

    <!-- Mongo dependencies -->
    <dependency>
        <groupId>org.mongodb</groupId>
        <artifactId>mongo-java-driver</artifactId>
        <version>3.3.0</version>
    </dependency>

    <dependency>
        <groupId>org.springframework.data</groupId>
        <artifactId>spring-data-mongodb</artifactId>
        <version>1.9.2.RELEASE</version>
    </dependency>

    <!-- jstl -->
    <dependency>
        <groupId>jstl</groupId>
        <artifactId>jstl</artifactId>
        <version>${jstl.version}</version>
    </dependency>

    <dependency>
        <groupId>cglib</groupId>
        <artifactId>cglib</artifactId>
        <version>3.2.4</version>
    </dependency>

 </dependencies>

 <build>
    <finalName>EatApp</finalName>

    <plugins>
        <!-- Eclipse project -->
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-eclipse-plugin</artifactId>
        <version>2.10</version>
        <configuration>
                <!-- Always download and attach dependencies source code -->
            <downloadSources>true</downloadSources>
            <downloadJavadocs>false</downloadJavadocs>
            <!-- Avoid type mvn eclipse:eclipse -Dwtpversion=2.0 -->
            <wtpversion>2.0</wtpversion>
        </configuration>
      </plugin>

      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-compiler-plugin</artifactId>
        <version>3.5.1</version>
        <configuration>
            <source>${jdk.version}</source>
            <target>${jdk.version}</target>
        </configuration>
      </plugin>
      <!--  
      <plugin>
        <groupId>org.apache.tomcat.maven</groupId>
        <artifactId>tomcat7-maven-plugin</artifactId>
        <version>2.2</version>
        <configuration>
            <path>/EatApp</path>
        </configuration>
      </plugin>
      -->

    </plugins>
 </build>

The web.xml:

    <!--  <!DOCTYPE web-app PUBLIC
 "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
 "http://java.sun.com/dtd/web-app_2_3.dtd" >
 -->

<web-app xmlns="http://java.sun.com/xml/ns/javaee"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
          http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
    version="2.5">

  <display-name>EatApp Web Application</display-name>

  <servlet>
       <servlet-name>mvc-dispatcher</servlet-name>
       <servlet-class>
            org.springframework.web.servlet.DispatcherServlet
       </servlet-class>
       <!--  
       <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>
                /WEB-INF/BaseConfig.xml
            </param-value>
        </init-param>
        -->
        <load-on-startup>1</load-on-startup>
    </servlet>

    <servlet-mapping>
        <servlet-name>mvc-dispatcher</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>

    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>/WEB-INF/mvc-dispatcher-servlet.xml</param-value>
    </context-param>

    <listener>
        <listener-class>
            org.springframework.web.context.ContextLoaderListener
        </listener-class>
    </listener>
</web-app>

And the servlet file: mvc-dispatch-servlet:

<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
    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">

<context:component-scan base-package="com.eat.menu.controller" />

<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
    <property name="prefix">
        <value>/WEB-INF/pages/</value>
    </property>
    <property name="suffix">
        <value>.jsp</value>
    </property>
</bean>

sirajnadwar
  • 237
  • 2
  • 6
  • 13
  • Why would you use @Autowired and setter injection? – SMA Oct 09 '16 at 08:16
  • Even if I do not use it it still gives me the above error – sirajnadwar Oct 09 '16 at 18:35
  • Remove getter/setter for `MongoTemplate`, remove `` from ``. If it still doesn't work it's something you didn't include or it's not code the you're actually running (like "baseConfig" vs "BaseConfig" discrepancy). Do you have any other XML config files? Are you sure your MVC app also uses BaseConfig.xml? – kryger Oct 09 '16 at 18:59
  • I did still the same. I have added pom file, web.xml and the servlet file. Please let me know if there is anything missing in the configuration. Thanks – sirajnadwar Oct 09 '16 at 19:43

2 Answers2

0

It seems you have set only the config file /WEB-INF/mvc-dispatcher-servlet.xml in the contextConfigLocation parameter. Add the content of your baseConfig.xml to that one and try again. If that solves the problem then, later, you can manage to use multiple config files.

mgsCatDev
  • 136
  • 1
  • 1
  • 10
-1

If you want to use annotation ,component-scan must defined in your configuration,you may tell spring which package need this auto-scan.

<context:component-scan base-package="com.xxx.xxx"/>

Exception says : excepted at least 1 bean which qualifies as... it means spring can't find it. If you want to inject the bean into your controller,@Resource is much better than @Autowired. Because

@Autowired
Inject by type. if you want to inject by name, you must add @Qualifier() annotation. And if you use @Autowired,you must make sure the dependency bean is exist. If null is permitted, add @Autowired(required=false). I found that your Exception says

No qualifying bean of type [org.springframework.data.mongodb.core.MongoTemplate] found for dependency [org.springframework.data.mongodb.core.MongoTemplate]: 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.raiseNoMatchingBeanFound(DefaultListableBeanFactory.java:1406)

Check your MongoTemplate bean, maybe it doesn't even exist or maybe your spring container can't find it.

@Autowired()
@Qualifier("mongoTemplate")
private MongoTemplate mongoTemplate; // Autowired. Inject by type. if you want to inject by name, you must add @Qualifier() annotation.

@Resource
Inject by name. if you want to inject by name

@Resource(name="mongoTemplate")
private MongoTemplate mongoTemplate; // Resource. Inject by name.

And most important thing is that @Resource is belong to the J2EE, @Autowired is belong to Spring. Both of them will solve the problem, but if you figure out how,you will be better. Wish this would help you.

  • Autowiring by name pretty much defeats the purpose of using IoC and makes refactoring extremely hard due to how brittle the app gets. This advice also wouldn't fix the problem so it's more of a comment than an answer. – kryger Oct 09 '16 at 18:43
  • Nope none of it seems towork. It doesn't recognize the mongoTemplate bean. It seems it may be related to configuration but I am not sure how because I have defined my beans in baseConfig.xml and I have put this file in java/main/resources. My understanding is that anything under resources is read by Springmvc. If that is not the case then please let me know how I may include my baseConfig.xml file such that the beans declared in it are available. – sirajnadwar Oct 09 '16 at 18:55
  • @sirajnadwar bean id `mongoTemplate` is defined in your configuration. I think `@Autowired@Qualifier("mongoTemplate")private MongoTemplate mongoTemplate;` is enough. Or `@Resource(name="mongoTemplate")private MongoTemplate mongoTemplate;` – stackoverflow Oct 10 '16 at 01:27