代码之家  ›  专栏  ›  技术社区  ›  James Hamilton

java.lang.IllegalStateException:无法使用Arquillian检索unitName HorizonPU的EntityManagerFactory

  •  1
  • James Hamilton  · 技术社区  · 10 年前

    我希望有人能帮我解决一个非常令人沮丧的问题。

    我想用Arquillian测试我正在开发的一个Web应用程序,我很难让JPA测试运行。我对Arquillian很陌生,我必须承认,我发现它很难使用。

    我的测试用例如下:

      @RunWith(Arquillian.class)
    public class BudgetFacadeTest
    {
        @Deployment
        public static WebArchive deploy(){
            WebArchive archive =  ShrinkWrap.create(WebArchive.class, "testarchive.war")
                    .addClasses(Budget.class, BudgetLine.class, BudgetSection.class, BudgetFacade.class)
                    .addAsManifestResource("META-INF/persistence.xml", "persistence.xml")
                    .addAsManifestResource(EmptyAsset.INSTANCE, "beans.xml");
            System.out.println(archive.toString(true));
            return archive;
        }
    
        @EJB
        BudgetFacade instance; 
    
    
            @Test
        public void testArquillianWorking(){
            instance.count();
        }
        }
    

    这很简单。持久性单元位于单独的测试文件夹中,如下所示:

    <?xml version="1.0" encoding="UTF-8"?>
    <persistence version="2.1" xmlns="http://xmlns.jcp.org/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence http://xmlns.jcp.org/xml/ns/persistence/persistence_2_1.xsd">
        <persistence-unit name="HorizonPU" transaction-type="JTA">
            <jta-data-source>jdbc/horizonBase</jta-data-source>
            <exclude-unlisted-classes>false</exclude-unlisted-classes>
            <properties>
                <property name="javax.persistence.schema-generation.database.action" value="drop-and-create"/>
                <property name="eclipselink.logging.level.sql" value="FINE"/>
                <property name="eclipselink.logging.parameters" value="true"/>
            </properties>
        </persistence-unit>
    </persistence>
    

    收缩存档结构如下:

    testarchive.war:
    /WEB-INF/
    /WEB-INF/classes/
    /WEB-INF/classes/com/
    /WEB-INF/classes/com/macraeanddick/
    /WEB-INF/classes/com/macraeanddick/marketinghorizon/
    /WEB-INF/classes/com/macraeanddick/marketinghorizon/company/
    /WEB-INF/classes/com/macraeanddick/marketinghorizon/company/Budget.class
    /WEB-INF/classes/com/macraeanddick/marketinghorizon/company/BudgetSection.class
    /WEB-INF/classes/com/macraeanddick/marketinghorizon/company/BudgetLine.class
    /WEB-INF/classes/com/macraeanddick/facades/
    /WEB-INF/classes/com/macraeanddick/facades/BudgetFacade.class
    /META-INF/
    /META-INF/beans.xml
    /META-INF/persistence.xml
    

    我认为这一切都很正常,POM如下:

        <dependency>
            <groupId>org.jboss.arquillian.junit</groupId>
            <artifactId>arquillian-junit-container</artifactId>
            <scope>test</scope>
        </dependency>        
        <dependency>
            <groupId>org.glassfish.main.extras</groupId>
            <artifactId>glassfish-embedded-all</artifactId>
            <version>4.1</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.jboss.arquillian.container</groupId>
            <artifactId>arquillian-glassfish-embedded-3.1</artifactId>
            <version>1.0.0.CR4</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.jboss.shrinkwrap</groupId>
            <artifactId>shrinkwrap-impl-base</artifactId>
            <scope>test</scope>
            <type>jar</type>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.10</version>
            <scope>test</scope>
        </dependency>        
    </dependencies>
    
    <!--Arquillian Dependency BOMs -->
    <dependencyManagement>
        <dependencies>        
            <dependency>
                <groupId>org.jboss.arquillian</groupId>
                <artifactId>arquillian-bom</artifactId>
                <version>1.1.5.Final</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>
    
    <build>
        <testResources>
            <testResource>
                <directory>src/test/resources</directory>
            </testResource>
            <testResource>
                <directory>src/test/resources-glassfish-embedded</directory>
            </testResource>
        </testResources>
    

    但如果我运行测试,我会得到以下结果:

    Caused by: java.lang.IllegalStateException: Unable to retrieve EntityManagerFactory for unitName HorizonPU
        at com.sun.enterprise.container.common.impl.EntityManagerWrapper.init(EntityManagerWrapper.java:138)
        at com.sun.enterprise.container.common.impl.EntityManagerWrapper._getDelegate(EntityManagerWrapper.java:171)
        at com.sun.enterprise.container.common.impl.EntityManagerWrapper.getCriteriaBuilder(EntityManagerWrapper.java:834)
        at com.macraeanddick.facades.AbstractFacade.count(AbstractFacade.java:57)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:483)
        at org.glassfish.ejb.security.application.EJBSecurityManager.runMethod(EJBSecurityManager.java:1081)
        at org.glassfish.ejb.security.application.EJBSecurityManager.invoke(EJBSecurityManager.java:1153)
        at com.sun.ejb.containers.BaseContainer.invokeBeanMethod(BaseContainer.java:4786)
        at com.sun.ejb.EjbInvocation.invokeBeanMethod(EjbInvocation.java:656)
        at com.sun.ejb.containers.interceptors.AroundInvokeChainImpl.invokeNext(InterceptorManager.java:822)
        at com.sun.ejb.EjbInvocation.proceed(EjbInvocation.java:608)
        at org.jboss.weld.ejb.AbstractEJBRequestScopeActivationInterceptor.aroundInvoke(AbstractEJBRequestScopeActivationInterceptor.java:46)
        at org.jboss.weld.ejb.SessionBeanInterceptor.aroundInvoke(SessionBeanInterceptor.java:52)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:483)
        at com.sun.ejb.containers.interceptors.AroundInvokeInterceptor.intercept(InterceptorManager.java:883)
        at com.sun.ejb.containers.interceptors.AroundInvokeChainImpl.invokeNext(InterceptorManager.java:822)
        at com.sun.ejb.EjbInvocation.proceed(EjbInvocation.java:608)
        at com.sun.ejb.containers.interceptors.SystemInterceptorProxy.doCall(SystemInterceptorProxy.java:163)
        at com.sun.ejb.containers.interceptors.SystemInterceptorProxy.aroundInvoke(SystemInterceptorProxy.java:140)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:483)
        at com.sun.ejb.containers.interceptors.AroundInvokeInterceptor.intercept(InterceptorManager.java:883)
        at com.sun.ejb.containers.interceptors.AroundInvokeChainImpl.invokeNext(InterceptorManager.java:822)
        at com.sun.ejb.containers.interceptors.InterceptorManager.intercept(InterceptorManager.java:369)
        at com.sun.ejb.containers.BaseContainer.__intercept(BaseContainer.java:4758)
        at com.sun.ejb.containers.BaseContainer.intercept(BaseContainer.java:4746)
        at com.sun.ejb.containers.EJBLocalObjectInvocationHandler.invoke(EJBLocalObjectInvocationHandler.java:212)
        ... 108 more
    

    我完全不知道我做错了什么,已经为此浪费了一天。任何建议都将不胜感激!

    1 回复  |  直到 10 年前
        1
  •  4
  •   James Hamilton    10 年前

    我终于找到了这件事的真相。如果您正在部署web应用程序,那么persistence.xml文件需要位于web-INF/classes/META-INF/中,换句话说,META-INF不应该位于归档的顶层。通常,Arquillian的文档并不十分清楚如何实现这一点,但我的问题的解决方案是将测试中的部署方法更改为:

    WebArchive archive = ShrinkWrap.create(WebArchive.class, "testarchive.war")
            .addClasses(Budget.class, BudgetLine.class, BudgetSection.class, BudgetFacade.class)
            .addAsResource("META-INF/persistence.xml")
            .addAsWebInfResource(EmptyAsset.INSTANCE, "beans.xml");
    

    注意,persistence.xml现在添加了 .addAsResource ,beans.xml添加为 .addAsWebInfResource .