2

我使用 2 个单独的数据库,所以我必须使用 JTA 来处理分布式事务。所以要么两个数据库都必须提交,要么都回滚。我使用 open JPA 和 JTA.Now 使用 junit 对代码进行单元测试?当我尝试运行处理分布式事务的代码时出现以下错误。我在此站点上发布了类似的问题,有人要求我参考 http://knol.google.com/k/how-to-unit-test -enterprise-java-beans-ejb# 但我无法从那里理解任何事情。

<openjpa-1.2.1-SNAPSHOT-r422266:686069 fatal store error> org.apache.openjpa.persistence.RollbackException: Unable to obtain a TransactionManager using null. 
    at org.apache.openjpa.persistence.EntityManagerImpl.commit(EntityManagerImpl.java:523)
    at com.XYZ.cloud.admin.loadCatalog.LoadCatalogTest.populateOffering(LoadCatalogTest.java:253)
    at com.XYZ.cloud.admin.loadCatalog.LoadCatalogTest.CatalogUploadTest(LoadCatalogTest.java:160)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:37)
    at java.lang.reflect.Method.invoke(Method.java:599)
    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:70)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:44)
    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:45)
    at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:460)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:673)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:386)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:196)
Caused by: <openjpa-1.2.1-SNAPSHOT-r422266:686069 nonfatal general error> org.apache.openjpa.persistence.PersistenceException: Unable to obtain a TransactionManager using null. 
    at org.apache.openjpa.jdbc.sql.DBDictionary.narrow(DBDictionary.java:4231)
    at org.apache.openjpa.jdbc.sql.DBDictionary.newStoreException(DBDictionary.java:4196)
    at org.apache.openjpa.jdbc.sql.DB2Dictionary.newStoreException(DB2Dictionary.java:503)
    at org.apache.openjpa.jdbc.sql.SQLExceptions.getStore(SQLExceptions.java:102)
    at org.apache.openjpa.jdbc.sql.SQLExceptions.getStore(SQLExceptions.java:88)
    at org.apache.openjpa.jdbc.sql.SQLExceptions.getStore(SQLExceptions.java:64)
    at org.apache.openjpa.jdbc.kernel.AbstractJDBCSeq.next(AbstractJDBCSeq.java:65)
    at org.apache.openjpa.util.ImplHelper.generateValue(ImplHelper.java:160)
    at org.apache.openjpa.util.ImplHelper.generateFieldValue(ImplHelper.java:144)
    at org.apache.openjpa.jdbc.kernel.JDBCStoreManager.assignField(JDBCStoreManager.java:698)
    at org.apache.openjpa.util.ApplicationIds.assign(ApplicationIds.java:487)
    at org.apache.openjpa.util.ApplicationIds.assign(ApplicationIds.java:463)
    at org.apache.openjpa.jdbc.kernel.JDBCStoreManager.assignObjectId(JDBCStoreManager.java:682)
    at org.apache.openjpa.kernel.DelegatingStoreManager.assignObjectId(DelegatingStoreManager.java:134)
    at org.apache.openjpa.kernel.StateManagerImpl.assignObjectId(StateManagerImpl.java:519)
    at org.apache.openjpa.kernel.StateManagerImpl.preFlush(StateManagerImpl.java:2823)
    at org.apache.openjpa.kernel.PNewState.beforeFlush(PNewState.java:39)
    at org.apache.openjpa.kernel.StateManagerImpl.beforeFlush(StateManagerImpl.java:959)
    at org.apache.openjpa.kernel.BrokerImpl.flush(BrokerImpl.java:1948)
    at org.apache.openjpa.kernel.BrokerImpl.flushSafe(BrokerImpl.java:1908)
    at org.apache.openjpa.kernel.BrokerImpl.beforeCompletion(BrokerImpl.java:1826)
    at org.apache.openjpa.kernel.LocalManagedRuntime.commit(LocalManagedRuntime.java:81)
    at org.apache.openjpa.kernel.BrokerImpl.commit(BrokerImpl.java:1350)
    at org.apache.openjpa.kernel.DelegatingBroker.commit(DelegatingBroker.java:877)
    at org.apache.openjpa.persistence.EntityManagerImpl.commit(EntityManagerImpl.java:512)
    ... 26 more
Caused by: java.sql.SQLException: Unable to obtain a TransactionManager using null. 
    at org.apache.openjpa.jdbc.kernel.TableJDBCSeq.allocateSequence(TableJDBCSeq.java:419)
    at org.apache.openjpa.jdbc.kernel.TableJDBCSeq.nextInternal(TableJDBCSeq.java:290)
    at org.apache.openjpa.jdbc.kernel.AbstractJDBCSeq.next(AbstractJDBCSeq.java:60)
    ... 44 more
Caused by: javax.transaction.NotSupportedException: Unable to obtain a TransactionManager using null. 
    at org.apache.openjpa.ee.AutomaticManagedRuntime.doNonTransactionalWork(AutomaticManagedRuntime.java:306)
    at org.apache.openjpa.jdbc.kernel.TableJDBCSeq.allocateSequence(TableJDBCSeq.java:415)
    ... 46 more
Caused by: <openjpa-1.2.1-SNAPSHOT-r422266:686069 fatal user error> org.apache.openjpa.util.InvalidStateException: Could not perform automatic lookup of EJB container's javax.transaction.TransactionManager implementation. Please ensure that you are running the application from within an EJB 1.1 compliant EJB container, and then set the org.apache.openjpa.ManagedRuntime property to  
    at org.apache.openjpa.ee.AutomaticManagedRuntime.getTransactionManager(AutomaticManagedRuntime.java:250)
    at org.apache.openjpa.ee.AutomaticManagedRuntime.doNonTransactionalWork(AutomaticManagedRuntime.java:304)
    ... 47 more
Caused by: javax.naming.ConfigurationException: Name space accessor for the java: name space has not been set. Possible cause is that the user is specifying a java: URL name in a JNDI Context method call but is not running in a J2EE client or server environment.
    at com.XYZ.ws.naming.java.javaURLContextFactory.isNameSpaceAccessable(javaURLContextFactory.java:93)
    at com.XYZ.ws.naming.urlbase.UrlContextFactory.getObjectInstance(UrlContextFactory.java:82)
    at javax.naming.spi.NamingManager.getURLContext(NamingManager.java:655)
    at javax.naming.InitialContext.getURLOrDefaultInitCtx(InitialContext.java:434)
    at javax.naming.InitialContext.lookup(InitialContext.java:450)
    at org.apache.openjpa.ee.RegistryManagedRuntime.getTransactionManager(RegistryManagedRuntime.java:61)
    at org.apache.openjpa.ee.AutomaticManagedRuntime.getTransactionManager(AutomaticManagedRuntime.java:154)
    ... 48 more
4

3 回答 3

2

我使用 2 个独立的数据库,所以我必须使用 JTA 来处理分布式事务。因此,要么两个数据库都必须提交,要么都回滚。我使用 open JPA 和 JTA.Now 来使用 junit 对代码进行单元测试?

如果要在容器外运行集成测试并使用 JTA,则必须

  1. 设置一个独立的 JTA 事务管理器,如AtomikosBitronix等(我会选择 Atomikos 作为其文档)
  2. 设置支持 JTA 的数据源
  3. 把整个东西包起来。

我强烈建议使用 Spring,并查看Spring、JPA 和 JTA with Hibernate 和 JOTM(但将其调整为使用 Atomikos、Bitronix)。

资源

相关问题

于 2010-10-17T09:38:29.070 回答
0

我有一个带有 EJB 3 的 Wicket 应用程序。生产适用于 Glassfish 2 (Toplink - JPA 1)。单元测试适用于 OpenEJB 3。我需要在单元测试中使用 OpenEJB 才能使用出色的 Wicket 集成测试。

我假设你有一个 Maven 项目。如果没有,请手动获取依赖项。

pom.xml:

<dependency>
    <!-- It's provided by Glassfish but while testing OpenEJB needs it explicitly -->
    <groupId>toplink.essentials</groupId>
    <artifactId>toplink-essentials</artifactId>
    <version>2.0-58g</version>
</dependency>

<dependency>
    <!-- not sure about this one but probably it's needed -->
    <groupId>org.glassfish</groupId>
    <artifactId>javax.servlet</artifactId>
    <version>3.0</version>
    <scope>test</scope>
</dependency>

<dependency>
    <groupId>org.apache.openejb</groupId>
    <artifactId>openejb-core</artifactId>
    <version>3.0.2</version>
    <scope>test</scope>
</dependency>

<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>5.1.13</version>
    <scope>test</scope>
</dependency>

确保你把它放在后面<dependencies>

AbstactOpenEjbTest 类:

public abstract class AbstractOpenEjbTest {

    private static final String JTA_DATA_SOURCE = "jdbc/SeobserwatorDS";

    protected static InitialContext context;

    @BeforeClass
    public static void createInitialContext() throws Exception {
        setSystemProperties();

        final Properties properties = new Properties();

        properties.setProperty(JTA_DATA_SOURCE, "new://Resource?type=DataSource");
        properties.setProperty(JTA_DATA_SOURCE + ".JdbcDriver", "com.mysql.jdbc.Driver");
        properties.setProperty(JTA_DATA_SOURCE + ".JdbcUrl", "jdbc:mysql://localhost:3306/inne_test");
        properties.setProperty(JTA_DATA_SOURCE + ".UserName", "xxx");
        properties.setProperty(JTA_DATA_SOURCE + ".Password", "yyy");

        context = new InitialContext(properties);
    }

    @BeforeClass
    public static void setSystemProperties() {
        System.setProperty("java.naming.factory.initial", "org.apache.openejb.client.LocalInitialContextFactory");
        System.setProperty("toplink.target-server", "net.nowaker.nhr.seobserwator.web.OpenEjbTransactionController");
        System.setProperty("toplink.ddl-generation", "drop-and-create-tables");
        System.setProperty("toplink.logging.level", "WARNING");
        System.setProperty("toplink.ddl-generation.output-mode", "both");
    }

    @SuppressWarnings("unchecked")
    public AbstractOpenEjbTest() {
        // Execute manually all ServletContextListeners as we are outside the container
    }

    @AfterClass
    public static void removeTables() throws Exception {
        // some clean-up, e.g. delete all data
    }
}

一些奇怪的课程,我不记得它的用途但需要:

import javax.transaction.TransactionManager;
import oracle.toplink.essentials.transaction.JTATransactionController;

/**
 * Transaction controller for OpenEJB standalone/embedded and Toplink
 *
 * @see http://qbeukes.blogspot.com/2008/08/toplink-as-your-openejb-persistence.html
 */
public class OpenEjbTransactionController extends JTATransactionController {

    public static final String JNDI_TRANSACTION_MANAGER_NAME = "java:comp/TransactionManager";

    public OpenEjbTransactionController() {
        super();
    }

    @Override
    protected TransactionManager acquireTransactionManager() throws Exception {
        return (TransactionManager) jndiLookup(JNDI_TRANSACTION_MANAGER_NAME);
    }
}

示例测试:

public class OpenEjbTest extends AbstractOpenEjbTest {

    @Test
    public void shouldAddUserWithStatelessBean() throws Exception {
        // when
        final AuthServiceLocal authService = EjbUtils.lookupBean(AuthServiceLocal.class);
        final CrudServiceLocal crudService = EjbUtils.lookupBean(CrudServiceLocal.class);

        // then
        assertFalse(authService.userExists("nonExistent"));
        final User unmanagedUser = new User(null, "a", "b", "c", "d", 12345678, new Date());
        final User managedUser = crudService.update(unmanagedUser);
        assertNotNull(managedUser.getId());
        assertNotNull(crudService.find(User.class, managedUser.getId()));
    }
}

请让我知道这对你有没有用。

于 2010-12-01T00:40:34.083 回答
0

另一种选择是使用 OpenEjb 进行单元测试。

于 2010-12-01T00:21:44.867 回答