0

我正在将 Spring Java Web 项目的基于 XML 的配置转换为 JavaConfig。

我正在使用 JPA。所以我用必要的配置创建了一个额外的 JavaConfig 类。但是由于某种原因,JPA 配置失败了。

这是我的 [web.xml][1]

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" 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">

     <context-param>
      <param-name>contextClass</param-name>
      <param-value>
          org.springframework.web.context.support.AnnotationConfigWebApplicationContext
      </param-value>
  </context-param>

  <!-- Configuration locations must consist of one or more comma- or space-delimited
       fully-qualified @Configuration classes. Fully-qualified packages may also be
       specified for component-scanning -->
<!--  <context-param>
      <param-name>contextConfigLocation</param-name>
      <param-value>com.my.contoso.spring.contosoJPA</param-value>
  </context-param>-->

  <!-- Bootstrap the root application context as usual using ContextLoaderListener -->
  <listener>
      <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
  </listener>

  <!-- Declare a Spring MVC DispatcherServlet as usual -->
  <servlet>
      <servlet-name>restservices</servlet-name>
      <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
      <!-- Configure DispatcherServlet to use AnnotationConfigWebApplicationContext
           instead of the default XmlWebApplicationContext -->
      <init-param>
          <param-name>contextClass</param-name>
          <param-value>
              org.springframework.web.context.support.AnnotationConfigWebApplicationContext
          </param-value>
      </init-param>
      <!-- Again, config locations must consist of one or more comma- or space-delimited
           and fully-qualified @Configuration classes -->
      <init-param>
          <param-name>contextConfigLocation</param-name>
          <param-value>com.my.contoso.spring.contosoConfig</param-value>
      </init-param>
  </servlet>

    <!--
        This Servlet mapping means that this Servlet will handle all incoming requests
     -->

    <servlet-mapping>
        <servlet-name>restservices</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>


    <!-- for CORS -->
    <filter>
        <filter-name>CORS</filter-name>
        <filter-class>com.thetransactioncompany.cors.CORSFilter</filter-class>

        <init-param>
            <param-name>cors.supportedMethods</param-name>
            <param-value>GET, HEAD, POST, PUT, DELETE, OPTIONS</param-value>
        </init-param>

        <init-param>
            <param-name>cors.supportedHeaders</param-name>
            <param-value>Content-Type, X-Requested-With, Origin, Accept</param-value>
        </init-param>

    </filter>

    <filter-mapping>
        <filter-name>CORS</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
    <!-- End for CORS -->

    <context-param>
        <param-name>log4jConfigLocation</param-name>
        <param-value>classpath:log4j.properties</param-value>
    </context-param>

    <listener>
        <listener-class>org.springframework.web.util.Log4jConfigListener</listener-class>
    </listener>
<filter>
        <filter-name>OpenEntityManagerFilter</filter-name>
        <filter-class>org.springframework.orm.jpa.support.OpenEntityManagerInViewFilter</filter-class>
        <init-param>
        <param-name>entityManagerFactoryBeanName</param-name>
         <param-value>entityManagerFactory</param-value>
         </init-param> 
</filter>
    <filter-mapping>
        <filter-name>OpenEntityManagerFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
<!--    <resource-ref>
        <description>DB Connection</description>
        <res-ref-name>jdbc/contosoDS</res-ref-name>
        <res-type>javax.sql.DataSource</res-type>
        <res-auth>Container</res-auth>
    </resource-ref>-->
</web-app>

这是我的主要 [JavaConfig 类][2]

@Configuration
@EnableWebMvc
//@ImportResource("contoso-jpa.xml") //Import any existing xml context files
@Import(contosoJPA.class)
//@EnableTransactionManagement //substitute for  <tx:annotation-driven/>
@ComponentScan({"com.my.contoso.webservices.rest", "com.my.contoso.services,com.my.contoso.dao"})
public class contosoConfig {

}

这是带有 [JPA config][3] 的 JavaConfig 类

@Configuration
@EnableTransactionManagement
@EnableJpaRepositories //(basePackages = { "com.my.contoso.domain" })
public class contosoJPA {


         @Bean
        public DataSource dataSource() {
    //        return new EmbeddedDatabaseBuilder().setType(H2).build();

            DriverManagerDataSource ds = new DriverManagerDataSource();


        try {
            ds.setDriverClassName("com.mysql.jdbc.Driver");
            ds.setUsername("root");
            ds.setPassword("");
            ds.setUrl("jdbc:mysql://localhost:3306/contosodb");

        } catch (Exception e) {
    //        logger.error(e.getMessage());
            System.out.println(e);
        }
        return ds;
        }

        @Bean
        public LocalContainerEntityManagerFactoryBean entityManagerFactory(DataSource dataSource, JpaVendorAdapter jpaVendorAdapter) {
            LocalContainerEntityManagerFactoryBean lef = new LocalContainerEntityManagerFactoryBean();
            lef.setDataSource(dataSource);
            lef.setJpaVendorAdapter(jpaVendorAdapter);
            lef.setPackagesToScan("com.my.contoso.domain");
            lef.setPersistenceUnitName("contosoPU");
            return lef;
        }

        @Bean
        public JpaVendorAdapter jpaVendorAdapter() {
            HibernateJpaVendorAdapter hibernateJpaVendorAdapter = new HibernateJpaVendorAdapter();
            hibernateJpaVendorAdapter.setShowSql(false);
            hibernateJpaVendorAdapter.setGenerateDdl(true);
            hibernateJpaVendorAdapter.setDatabase(Database.MYSQL);
    //        hibernateJpaVendorAdapter.setDatabase(Database.H2);
            return hibernateJpaVendorAdapter;
        }

        @Bean
        public PlatformTransactionManager transactionManager() {
            return new JpaTransactionManager();
        }   

}

全栈跟踪:

org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'entityManagerFactory' is defined
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBeanDefinition(DefaultListableBeanFactory.java:570)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getMergedLocalBeanDefinition(AbstractBeanFactory.java:1108)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:278)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:198)
    at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1121)
    at org.springframework.orm.jpa.support.OpenEntityManagerInViewFilter.lookupEntityManagerFactory(OpenEntityManagerInViewFilter.java:222)
    at org.springframework.orm.jpa.support.OpenEntityManagerInViewFilter.lookupEntityManagerFactory(OpenEntityManagerInViewFilter.java:205)
    at org.springframework.orm.jpa.support.OpenEntityManagerInViewFilter.doFilterInternal(OpenEntityManagerInViewFilter.java:152)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:243)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
    at com.thetransactioncompany.cors.CORSFilter.doFilter(CORSFilter.java:179)
    at com.thetransactioncompany.cors.CORSFilter.doFilter(CORSFilter.java:241)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:243)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:222)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:123)
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:502)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:171)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:100)
    at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:953)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:408)
    at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1041)
    at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:603)
    at org.apache.tomcat.util.net.AprEndpoint$SocketProcessor.doRun(AprEndpoint.java:2430)
    at org.apache.tomcat.util.net.AprEndpoint$SocketProcessor.run(AprEndpoint.java:2419)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
    at java.lang.Thread.run(Thread.java:744)
    org.springframework.beans.factory.support.DefaultListableBeanFactory.getBeanDefinition(DefaultListableBeanFactory.java:570)

'entityManagerFactory' 在 [web.xml][1] 中声明。该错误表明不存在具有此类名称的 bean。但我确实将它包含在 [JPA config][3] 文件中。所以我猜测 JPA javaConfig 文件中的 bean 没有被拾取。想知道配置失败的地方。

4

2 回答 2

0

你为什么注释掉

<!-- Configuration locations must consist of one or more comma- or space-delimited
       fully-qualified @Configuration classes. Fully-qualified packages may also be
       specified for component-scanning -->
<!-- <context-param>
     <param-name>contextConfigLocation</param-name>
     <param-value>com.uhsarp.billrive.spring.BillriveJPA</param-value>
 </context-param>-->

?

在我看来,应该加载根上下文并通过ContextLoaderListener. 这context-param需要可用,以便根上下文具有加载 bean 定义的源。

于 2014-02-03T04:23:40.187 回答
0

我会尝试手动删除参数并调用 bean 方法:

@Bean
    public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
        LocalContainerEntityManagerFactoryBean lef = new LocalContainerEntityManagerFactoryBean();
        lef.setDataSource(dataSource());
        lef.setJpaVendorAdapter(jpaVendorAdapter());
        lef.setPackagesToScan("com.my.contoso.domain");
        lef.setPersistenceUnitName("contosoPU");
        return lef;
    }

如果spring从这个配置类中获取任何方法,然后尝试调试/输出。

也许将 web.xml 配置与 java config 混合不是最好的主意?你考虑过迁移它吗?:)

于 2014-02-03T10:05:50.227 回答