在JUnit测试时,EntityManager没有被注入EJB模块,由WebSphere embeddable容器实例化

时间:2014-09-03 18:39:53

标签: jpa junit ejb websphere java-ee-6

使用可嵌入容器时,我的EntityManager保持为null。在常规Web应用程序中调用时,相同的代码效果很好。

测试代码:

package com.learning.business.car;

import static org.junit.Assert.assertEquals;
import java.util.List;
import javax.ejb.embeddable.EJBContainer;
import javax.naming.NamingException;
import org.junit.Test;

public class CarRepoTest {

    @Test
    public void testGetCarsByEjb() throws NamingException {

        EJBContainer ec = EJBContainer.createEJBContainer();

        CarRepo carRepo = (CarRepo) ec
                .getContext()
                .lookup("java:global/classes/CarRepo");

        List<Car> cars = carRepo.getAll();

        assertEquals(0, cars.size());

        ec.close();
    }
}

在调试上述代码时,ec.toString()向我显示:

svContainerActive = true
svNamingInitialized = true
ivContext = com.ibm.ws.naming.java.javaURLContextRoot@fe720e63[super=com.ibm.ws.naming.java.javaURLContextImpl@fe720e63[super=com.ibm.ws.naming.urlbase.UrlContextImpl(java:)@fe720e63[_schemeId=java, _primaryLeafName=null, _strCtxID=ROOT CONTEXT, _ns=com.ibm.ws.naming.ipbase.NameSpace@d2d1a4d7[_nameSpaceName=java:comp(null, null, null), _nameSpaceID=2, _nameSpaceType=1, _contextsTable=java.util.HashMap@c8fb6403[size=2], _bindingsTable=java.util.HashMap@9cd644e1[size=2]]], _javaNameSpaceScope=COMPONENT SCOPE, _jns=javaNameSpaceImpl:{_appName=null,_moduleName=null,_componentName=null,_bootstrapAddress=rir:,_clientMode=ISOLATED,_componentNameSpaceLocation=LOCAL,_otherModuleNames=[],_applicationsRootProviderURL=corbaname:rir:/NameServiceApplicationsRoot#,_applicationRootProviderURL=null,_moduleRootProviderURL=null,_componentRootProviderURL=null,_ns=com.ibm.ws.naming.ipbase.NameSpace@d2d1a4d7[_nameSpaceName=java:comp(null, null, null), _nameSpaceID=2, _nameSpaceType=1, _contextsTable=java.util.HashMap@c8fb6403[size=2], _bindingsTable=java.util.HashMap@9cd644e1[size=2]]}], _caching=false, _rootCache=com.ibm.ws.naming.java.JavaNameSpaceCache@d10b63f9]
ivIsClosed = false
ivModules = [com.ibm.websphere.ejbcontainer.EmbeddableContainer$EmbeddableModule@9202003a[name=classes, file=C:\WorkSpaceRTC\javaee6\target\classes, metadata=com.ibm.ejs.csi.SharedEJBModuleMetaDataImpl@acb40850[embeddable#classes]]]
ivProperties = {enableProtocolSecurity=false}
ivServiceTokens = [sun.misc.Launcher$AppClassLoader@f3ba9f23:interface com.ibm.ws.runtime.service.MetaDataFactoryMgr, sun.misc.Launcher$AppClassLoader@f3ba9f23:interface com.ibm.wsspi.injectionengine.InjectionEngine]

EJB模块:

package com.learning.business.car;

import java.util.List;
import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.TypedQuery;

@Stateless
public class CarRepo {

    @PersistenceContext
    protected EntityManager em;

    public List<Car> getAll() {

        // "em" keeps null and the below line throws a NullPointerException
        TypedQuery<Car> query = em.createQuery("SELECT c FROM Car c", Car.class);

        return query.getResultList();
    }
}

的persistence.xml:

<?xml version="1.0" encoding="UTF-8" ?>
<persistence xmlns="http://java.sun.com/xml/ns/persistence"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/persistence
 http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd"
    version="2.0">

    <persistence-unit name="javaee6" transaction-type="JTA">
        <class>com.learning.business.car.Car</class>

        <properties>
            <property name="javax.persistence.jdbc.driver" value="org.h2.Driver" />
            <property name="javax.persistence.jdbc.url" value="jdbc:h2:mem:test;DB_CLOSE_DELAY=-1" />
            <property name="openjpa.jdbc.SynchronizeMappings" value="buildSchema(ForeignKeys=true)"/>
        </properties>
    </persistence-unit>
</persistence>

例外:

CNTR0020E: EJB threw an unexpected (non-declared) exception during invocation of method "getAll" on bean "BeanId(embeddable#classes#CarRepo, null)". Exception data: java.lang.NullPointerException
    at com.learning.business.car.CarRepo.getAll(CarRepo.java:18)
    at com.learning.business.car.EJSLocalNSLCarRepo_a1ab5865.getAll(EJSLocalNSLCarRepo_a1ab5865.java)
    at com.learning.business.car.CarRepoTest.testGetCarsByEjb(CarRepoTest.java:23)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:60)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:37)
    at java.lang.reflect.Method.invoke(Method.java:611)
    at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:44)
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15)
    at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:41)
    at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:20)
    at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:28)
    at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:31)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:73)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:46)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:180)
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:41)
    at org.junit.runners.ParentRunner$1.evaluate(ParentRunner.java:173)
    at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:28)
    at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:31)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:220)
    at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:46)
    at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)

另一方面,下面的代码在WebSphere应用程序中的xhtml页面使用时起作用:

package com.learning.app.car;

import javax.ejb.EJB;
import javax.faces.bean.ManagedBean;
import com.learning.business.car.CarRepo;

@ManagedBean
public class CarBean {

    @EJB
    public CarRepo carRepo;

    public Integer getCarsCount() {

        // in a WebSphere application it works as expected (EntityManager is correctly injected in CarRepo)
        return carRepo.getAll().size();
    }
}

1 个答案:

答案 0 :(得分:2)

建议在使用可嵌入容器时包含JPA瘦客户端。请查看以下链接以获取详细信息,可能会对您有所帮助Running an embeddable container

  

在嵌入式EJB中使用JPA开发应用程序时   容器,类路径必须包含JPA瘦客户端,   com.ibm.ws.jpa.thinclient_n.0.jar,其中n是WebSphere®   Application Server发布;例如,8.5版本8.5。 JPA   瘦客户端位于\ runtimes所在的根目录中   安装映像位于。