Spring MVC Test安装程序在加载ApplicationContext.xml

时间:2016-10-04 10:51:08

标签: java xml hibernate spring-mvc spring-mvc-test

目前我正在尝试为我工作的学校项目设置Spring MVC Controller测试。通常我在像Laravel这样的php和框架中编程,所以这对我来说很新。问题是我无法弄清楚如何解决在加载ApplicationContext时不断弹出的问题。任何帮助表示赞赏。

更新

我现在告诉我,测试用例不能在我的应用服务器中使用jndi ref。所以这个引用在测试用例上会失败,它在启动应用程序时运行良好。现在我创建了一个名为servlet-test.xml (listed below)的第二个文件,该文件在端口3306上使用对数据库的引用。我只在测试时使用此文件而不是在启动应用程序时。但是当我使用这种方法时,我得到Following error: Error creating bean with name 'productController': Injection of autowired dependencies failed。欢迎任何帮助,因为我正努力为我的学校项目设置MVC控制器测试。我一直在工作的其他学生也遇到了同样的问题,所以我也可以帮助他们。

我怀疑问题如下,但我不确定如何解决这个问题。

Error creating bean with name 'myDataSource' defined in URL 
[file:web/WEB-INF/servlet.xml]: Invocation of init method failed; 
nested exception is javax.naming.NamingException: Lookup failed for
'java:app/fotoproducent' ...

错误堆栈跟踪

java.lang.IllegalStateException: Failed to load ApplicationContext

Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'entityManagerFactory' defined in URL [file:web/WEB-INF/servlet.xml]: Cannot resolve reference to bean 'myDataSource' while setting bean property 'dataSource'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'myDataSource' defined in URL [file:web/WEB-INF/servlet.xml]: Invocation of init method failed; nested exception is javax.naming.NamingException: Lookup failed for 'java:app/fotoproducent' in SerialContext[myEnv={java.naming.factory.initial=com.sun.enterprise.naming.impl.SerialInitContextFactory, java.naming.factory.url.pkgs=com.sun.enterprise.naming, java.naming.factory.state=com.sun.corba.ee.impl.presentation.rmi.JNDIStateFactoryImpl} [Root exception is javax.naming.NamingException: Invocation exception: Got null ComponentInvocation ]
at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveReference(BeanDefinitionValueResolver.java:328)
at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveValueIfNecessary(BeanDefinitionValueResolver.java:107)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyPropertyValues(AbstractAutowireCapableBeanFactory.java:1456)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1197)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:537)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:475)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:304)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:228)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:300)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:195)
at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:973)
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:750)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:482)
at org.springframework.test.context.support.AbstractGenericContextLoader.loadContext(AbstractGenericContextLoader.java:121)
at org.springframework.test.context.support.AbstractGenericContextLoader.loadContext(AbstractGenericContextLoader.java:60)
at org.springframework.test.context.support.AbstractDelegatingSmartContextLoader.delegateLoading(AbstractDelegatingSmartContextLoader.java:100)
at org.springframework.test.context.support.AbstractDelegatingSmartContextLoader.loadContext(AbstractDelegatingSmartContextLoader.java:250)
at org.springframework.test.context.CacheAwareContextLoaderDelegate.loadContextInternal(CacheAwareContextLoaderDelegate.java:64)
at org.springframework.test.context.CacheAwareContextLoaderDelegate.loadContext(CacheAwareContextLoaderDelegate.java:91)

控制器测试我试图运行:

ProductController测试

package controller.tests.config;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.web.servlet.ResultMatcher;
import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import org.springframework.test.web.servlet.result.MockMvcResultMatchers;
import org.springframework.test.web.servlet.setup.DefaultMockMvcBuilder;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration({"file:web/WEB-INF/servlet-test.xml", "file:web/WEB-INF/dispatcher-servlet.xml"})

public class ProductControllerTest {

    @Autowired
    private WebApplicationContext wac;
    private MockMvc mockMvc;

    @Before
    public void setup() {
        DefaultMockMvcBuilder builder = MockMvcBuilders.webAppContextSetup(this.wac);
        this.mockMvc = builder.build();
    }

    @Test
    public void testProductAction() throws Exception {
       ResultMatcher ok = MockMvcResultMatchers.status().isOk();
       ResultMatcher msg = MockMvcResultMatchers.model()
                       .attribute("msg", "Spring quick start!!");

       MockHttpServletRequestBuilder builder = MockMvcRequestBuilders.get("/product");
       this.mockMvc.perform(builder)
               .andExpect(ok)
               .andExpect(msg);
    }

}

servlet.xml / applicationContext.xml文件

<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:tx="http://www.springframework.org/schema/tx"
   xmlns:mvc="http://www.springframework.org/schema/mvc"
   xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd">

<!-- module/package declarations -->
<context:component-scan base-package="Application" />
<context:component-scan base-package="Authentication" />
<context:component-scan base-package="Photo" /> 
<context:component-scan base-package="Product" />
<context:component-scan base-package="Organisation" />
<context:component-scan base-package="Login" />
<context:component-scan base-package="UI" />
<context:component-scan base-package="I18n" />
<context:component-scan base-package="Internationalization" />

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

<bean id="myDataSource" class="org.springframework.jndi.JndiObjectFactoryBean" scope="singleton"> 
    <property name="jndiName" value="java:app/fotoproducent" /> 
    <property name="resourceRef" value="true" /> 
</bean>

<tx:annotation-driven transaction-manager="transactionManager" />
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
    <property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>

<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
    <property name="dataSource" ref="myDataSource" />
    <property name="persistenceXmlLocation" value="classpath:META-INF/persistence.xml" />        
    <property name="packagesToScan" value="*" />
    <property name="jpaVendorAdapter">
        <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
            <property name="showSql" value="true" />
            <property name="databasePlatform" value="org.hibernate.dialect.MySQLDialect" />
        </bean>
    </property>
</bean>

<bean id="multipartResolver"  class="org.springframework.web.multipart.commons.CommonsMultipartResolver"/>

<mvc:resources mapping="/static/**" location="/static/"/>
<mvc:resources mapping="/resources/**" location="/resources/" />
<mvc:default-servlet-handler/>
<mvc:annotation-driven />

</beans>

分派器-servlet.xml中

<?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:p="http://www.springframework.org/schema/p"
   xmlns:aop="http://www.springframework.org/schema/aop"
   xmlns:tx="http://www.springframework.org/schema/tx"
   xsi:schemaLocation="http://www.springframework.org/schema/beans     http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
   http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd
   http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd">

<bean class="org.springframework.web.servlet.mvc.support.ControllerClassNameHandlerMap ping"/>

<bean id="urlMapping" class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
    <property name="mappings">
        <props>
            <prop key="index.html">indexController</prop>
            <prop key="test.html">testController</prop>
        </props>
    </property>
</bean>

<bean id="viewResolver"
      class="org.springframework.web.servlet.view.InternalResourceViewResolver"
      p:prefix="/WEB-INF/views/"
      p:suffix=".jsp" />

<!--
The index controller.
-->
<bean name="indexController"
      class="org.springframework.web.servlet.mvc.ParameterizableViewController"
      p:viewName="index" />

<!--
The test controller.
-->
<bean name="testController"
      class="org.springframework.web.servlet.mvc.ParameterizableViewController"
      p:viewName="test" />


</beans>

更新1:&#34;数据源配置&#34;

这显示了数据源的配置方式。

的glassfish-resources.xml中

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE resources PUBLIC "-//GlassFish.org//DTD GlassFish Application Server 3.1 Resource Definitions//EN" "http://glassfish.org/dtds/glassfish-resources_1_5.dtd">
<resources>
<jdbc-connection-pool allow-non-component-callers="false" associate-with-thread="false" connection-creation-retry-attempts="0" connection-creation-retry-interval-in-seconds="10" connection-leak-reclaim="false" connection-leak-timeout-in-seconds="0" connection-validation-method="auto-commit" datasource-classname="com.mysql.jdbc.jdbc2.optional.MysqlDataSource" fail-all-connections="false" idle-timeout-in-seconds="300" is-connection-validation-required="false" is-isolation-level-guaranteed="true" lazy-connection-association="false" lazy-connection-enlistment="false" match-connections="false" max-connection-usage-count="0" max-pool-size="32" max-wait-time-in-millis="60000" name="mysql_fotoproducent_rootPool" non-transactional-connections="false" pool-resize-quantity="2" res-type="javax.sql.DataSource" statement-timeout-in-seconds="-1" steady-pool-size="8" validate-atmost-once-period-in-seconds="0" wrap-jdbc-objects="false">
    <property name="serverName" value="localhost"/>
    <property name="portNumber" value="3306"/>
    <property name="databaseName" value="fotoproducent"/>
    <property name="User" value="root"/>
    <property name="Password" value="password"/>
    <property name="URL" value="jdbc:mysql://localhost:3306/fotoproducent?zeroDateTimeBehavior=convertToNull"/>
    <property name="driverClass" value="com.mysql.jdbc.Driver"/>
</jdbc-connection-pool>
<jdbc-resource enabled="true" jndi-name="app/fotoproducent" object-type="user" pool-name="mysql_fotoproducent_rootPool"/>
</resources>

更新2:其他Bean配置文件(servlet-test.xml)

这导致bean未加载。以下错误:使用名称&#39; productController创建bean时出错&#39;:注入自动连接的依赖项失败

 <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:tx="http://www.springframework.org/schema/tx"
   xmlns:mvc="http://www.springframework.org/schema/mvc"
   xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd">

<context:annotation-config/>
<mvc:annotation-driven />

<!-- module/package declarations -->
<context:component-scan base-package="Application" />
<context:component-scan base-package="Authentication" />
<context:component-scan base-package="Photo" /> 
<context:component-scan base-package="Product" />
<context:component-scan base-package="Organisation" />
<context:component-scan base-package="Login" />
<context:component-scan base-package="UI" />
<context:component-scan base-package="I18n" />
<context:component-scan base-package="Internationalization" />


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

<bean id="myDataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
    <property name="driverClassName" value="com.mysql.jdbc.Driver" />
    <property name="url" value="jdbc:mysql://localhost:3306/fotoproducent?zeroDateTimeBehavior=convertToNull" />
    <property name="username" value="root" />
    <property name="password" value="password" />
</bean>

<tx:annotation-driven transaction-manager="transactionManager" />
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
    <property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>

<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
    <property name="dataSource" ref="myDataSource" />
    <property name="persistenceXmlLocation" value="classpath:META-INF/persistence.xml" />        
    <property name="packagesToScan" value="*" />
    <property name="jpaVendorAdapter">
        <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
            <property name="showSql" value="true" />
            <property name="databasePlatform" value="org.hibernate.dialect.MySQLDialect" />
        </bean>
    </property>
</bean>

<bean id="multipartResolver"  class="org.springframework.web.multipart.commons.CommonsMultipartResolver"/>

<mvc:resources mapping="/static/**" location="/static/"/>
<mvc:resources mapping="/resources/**" location="/resources/" />


</beans>

更新3:问题解决的附加代码

产品控制器

package Product.Controller;

import Product.Sevice.ProductService;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

@Controller
@RequestMapping("/product")
public class ProductController {

    @Autowired
    protected ProductService service;

    @RequestMapping(value = "", method = RequestMethod.GET)
    public String productAction(ModelMap model)
    {
        model.put("productList", this.service.findAll());

        return "product/overview";
    }
}

产品服务

package Product.Sevice;

import Product.Entity.Product;
import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;
import javax.transaction.Transactional;
import org.springframework.stereotype.Service;

@Service
public class ProductService {

    @PersistenceContext
    private EntityManager em;

    @Transactional
    public void insert(Product product)
    {
        // insert into database
        // persist function is for NEW entities in database
        this.em.persist(product);
    }

    @Transactional
    public Product get(Integer id)
    {
        // this gets the entity from the database and returns it
        return this.em.find(Product.class, (long) id);
    }


    @Transactional
    public Product update(Product product)
    {
        // this updates the ExampleEntity in within the database
        return this.em.merge(product);
    }

    @Transactional
    public void remove(Integer id)
    {
        Product product = this.em.find(Product.class, (long) id);
        product.delete();

        // this updates the product in within the database
        this.update(product);
    }

    @Transactional
    public List<Product> findAll()
    {
        Query q = this.em.createNamedQuery("product.namedquery", Product.class);
        return q.getResultList();
    }
}

2 个答案:

答案 0 :(得分:1)

根据应用程序上下文初始化时的堆栈跟踪,它仍然尝试加载错误的配置文件(servlet.xml),但是应该加载servlet-test.xml。请尝试使用root(src)文件夹中的路径更改配置位置,例如:

@ContextConfiguration({"file:src/main/web/WEB-INF/servlet-test.xml", "file:src/main/web/WEB-INF/dispatcher-servlet.xml"})

P.S此外,您可以尝试将测试配置(servlet-test.xml)移动到src / test / resources并从类路径加载它:“classpath:servlet-test.xml”。您还可以在stackoverflow上查看此线程:Spring @ContextConfiguration how to put the right location for the xml以扩展对类似问题的讨论。

答案 1 :(得分:0)

您收到一条错误消息,指出Spring IOC容器无法创建并实例化entityManagerFactory bean。为什么?

您的错误异常提到的另一件事。它没有这样做,因为它无法实例化myDataSource bean。为什么呢?

根据您的错误消息:

 Lookup failed for 'java:app/fotoproducent'

这意味着当IOC Spring容器尝试创建myDataSource bean时,它无法执行此操作,因为它无法将jndiName设置为值java:app/fotoproducent

而不是使用它:

<bean id="myDataSource" class="org.springframework.jndi.JndiObjectFactoryBean" scope="singleton"> 
    <property name="jndiName" value="java:app/fotoproducent" /> 
    <property name="resourceRef" value="true" /> 
</bean>

将其替换为:

<bean id="myDataSource" class="org.apache.commons.dbcp2.BasicDataSource" destroy-method="close">
    <property name="driverClassName" value="your_driver_class_name" />
    <property name="url" value="url_to_your_db" />
    <property name="username" value="user_name_to_db" />
    <property name="password" value="password_to_db" />
</bean>

我的建议是创建一个像上面的Spring文档中提到的标准数据源。

现在不要忘记替换驱动程序类名,网址,用户名和密码的值。

以下是Spring文档中有关如何定义使用Hibernate ORM的数据源的示例:http://docs.spring.io/spring/docs/current/spring-framework-reference/htmlsingle/#orm-hibernate