При загрузке ApplicationContext происходит сбой установки теста Spring MVC.XML

в настоящее время я пытаюсь настроить тестирование контроллера Spring MVC для школьного проекта, над которым я работаю рядом с моей работой. Обычно я программирую на php и фреймворках, таких как Laravel, поэтому это довольно ново для меня. Проблема в том, что я не могу понять, как решить проблему, которая продолжает появляться при загрузке ApplicationContext. Любая помощь приветствуется.

обновление:

теперь мне говорят, что тестовые случаи не используют ссылку jndi на моем сервере приложений. Так эта ссылка не будет работать на тестовом примере, она отлично работает при запуске приложения. Теперь я сделал второй файл под названием 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.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);
    }

}

сервлет.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>

диспетчер-сервлета.в 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:"Конфигурация Источника Данных"

это показывает, как настроен источник данных.

glassfish-ресурсы.в 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>

Update 2: дополнительный конфигурационный файл Bean (servlet-test.в XML)

это приводит к тому, что бобы не загружаются. Следующая ошибка: Ошибка при создании фасоли с имя productcontroller в': инъекции подгружен зависимости не

 <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 ответов


согласно вашей трассировке стека, когда контекст приложения инициализирует его, все еще пытаются загрузить неправильные файлы конфигурации (сервлет.xml), но должен загрузить servlet-test.XML. Попробуйте изменить расположение конфигурации с помощью пути из корневой папки (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: "classpath:servlet-test.XML." Также вы можете проверить этот поток на stackoverflow: Spring @ContextConfiguration как правильно расположить xml для расширенного обсуждения подобных проблем.


вы получаете сообщение об ошибке, в котором говорится, что контейнер Spring IOC не может создать и создать экземпляр entityManagerFactory бобовые. Почему?

это еще одна вещь, которую упоминает ваше исключение ошибки. Это не удается сделать, потому что он не может создать экземпляр myDataSource бобовые. Почему?

согласно вашему сообщению об ошибке:

 Lookup failed for 'java:app/fotoproducent'

это означает, что когда контейнер весны IOC попытался создать 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 docs выше.

теперь не забудьте заменить значения для имени класса драйвера, url, имени пользователя и пароля.

вот пример из Spring docs, как определить источник данных для использования Hibernate ORM: http://docs.spring.io/spring/docs/current/spring-framework-reference/htmlsingle/#orm-hibernate