2

私は2つの別々のデータベースを使用しているため、JTAを使用して分散トランザクションを処理する必要があります。したがって、両方のデータベースをコミットするか、両方をロールバックする必要があります。オープン 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 を使用して分散トランザクションを処理する必要があります。したがって、両方のデータベースをコミットするか、両方をロールバックする必要があります。junit を使用してコードを単体テストするには、open JPA と JTA を使用しますか?

コンテナの外部で統合テストを実行し、JTA を使用する場合は、次のことを行う必要があります。

  1. AtomikosBitronixなどのスタンドアロンの JTA トランザクション マネージャーをセットアップします(ドキュメントには Atomikos を選択します)。
  2. JTA 対応のデータソースをセットアップする
  3. 全体をまとめて包みます。

Spring を使用し、Hibernate と JOTM を使用して Spring、JPA、および JTA を確認することを強くお勧めします (ただし、Atomikos、Bitronix を使用するように調整します)。

資力

関連する質問

于 2010-10-17T09:38:29.070 に答える
0

EJB 3 を使用した Wicket アプリケーションがあります。本番環境は Glassfish 2 (Toplink - JPA 1) で動作します。単体テストは OpenEJB 3 で動作します。すばらしい Wicket 統合テストを使用するには、単体テストで OpenEJB が必要でした。

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

もう 1 つのオプションは、単体テストに OpenEjb を使用することです。

于 2010-12-01T00:21:44.867 に答える