1

環境

クラウド ベースの Java プロジェクトの 1 つで、 2 つのオブジェクト間で JDO の双方向所有の 1 対多の関係を使用しています ( App Engine のドキュメントで説明されているように)。

@PersistenceCapable
public class IndexPage implements Page {

    @Persistent(mappedBy = "index")
    @Order(extensions =
      @Extension(
        vendorName = "datanucleus",
        key = "list-ordering",
        value = "title asc"))
    private List<MotherCategoryPage> motherCategoryPages;

    (...)
}

@PersistenceCapable
public class MotherCategoryPage implements Page {
    private String title;

    @Persistent
    private IndexPage index;

    (...)
}

次に、これらのオブジェクトは、次の非常に一般的な JDO コード スニペットを使用して、appengine のデータストアに格納されます。

public void persistPage(Page page) {
    PersistenceManager pm = PMF.get();
    Transaction tx = pm.currentTransaction();
    tx.begin();
    // persist a Page object
    pm.makePersistent(page);
    tx.commit();
    pm.close();
}

また、testNG を使用して (非常に単純な) 単体テストを実装しました。ここでは、IndexPage オブジェクトと MotherCategoryPage オブジェクトの両方をインスタンス化し、上記のメソッドを使用してそれらを永続化します。

問題

これが問題です。私のコードは本番環境で非常にうまく動作し(ページはローカルと App Engine のサーバーの両方で適切に永続化されます)、単体テストは Eclipse で完全に実行されます。しかし、 maven を介して実行すると、テストは失敗しました! (surefire プラグインを使用)

確実なレポートは次のとおりです。

"Unexpected error during precommit"
org.datanucleus.jdo.NucleusJDOHelper.getJDOExceptionForNucleusException(NucleusJDOHelper.java:419)
org.datanucleus.jdo.JDOTransaction.commit(JDOTransaction.java:132)
org.datanucleus.store.appengine.jdo.DatastoreJDOTransaction.commit(DatastoreJDOTransaction.java:59)
com.mycompany.PageManager.persistPage(PageManager.java:102)
com.mycompany.pages.PageTest.putPagesIntoDb(PageTest.java:167)
com.mycompany.pages.PageTest.pageTest(PageTest.java:90)
sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
java.lang.reflect.Method.invoke(Method.java:597)
org.testng.internal.MethodInvocationHelper.invokeMethod(MethodInvocationHelper.java:80)
org.testng.internal.Invoker.invokeMethod(Invoker.java:702)
org.testng.internal.Invoker.invokeTestMethod(Invoker.java:894)
org.testng.internal.Invoker.invokeTestMethods(Invoker.java:1219)
org.testng.internal.TestMethodWorker.invokeTestMethods(TestMethodWorker.java:127)
org.testng.internal.TestMethodWorker.run(TestMethodWorker.java:111)
org.testng.TestRunner.privateRun(TestRunner.java:768)
org.testng.TestRunner.run(TestRunner.java:617)
org.testng.SuiteRunner.runTest(SuiteRunner.java:334)
org.testng.SuiteRunner.runSequentially(SuiteRunner.java:329)
org.testng.SuiteRunner.privateRun(SuiteRunner.java:291)
org.testng.SuiteRunner.run(SuiteRunner.java:240)
org.testng.SuiteRunnerWorker.runSuite(SuiteRunnerWorker.java:53)
org.testng.SuiteRunnerWorker.run(SuiteRunnerWorker.java:87)
org.testng.TestNG.runSuitesSequentially(TestNG.java:1188)
org.testng.TestNG.runSuitesLocally(TestNG.java:1113)
org.testng.TestNG.run(TestNG.java:1025)
org.apache.maven.surefire.testng.TestNGExecutor.run(TestNGExecutor.java:177)
org.apache.maven.surefire.testng.TestNGXmlTestSuite.execute(TestNGXmlTestSuite.java:92)
org.apache.maven.surefire.testng.TestNGProvider.invoke(TestNGProvider.java:105)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.apache.maven.surefire.util.ReflectionUtils.invokeMethodWithArray(ReflectionUtils.java:189)
at org.apache.maven.surefire.booter.ProviderFactory$ProviderProxy.invoke(ProviderFactory.java:165)
at org.apache.maven.surefire.booter.ProviderFactory.invokeProvider(ProviderFactory.java:85)
at org.apache.maven.surefire.booter.ForkedBooter.runSuitesInProcess(ForkedBooter.java:103)
at org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:74)

NestedThrowablesStackTrace:
com.google.apphosting.api.ApiProxy$UnknownException: An error occurred for the API request datastore_v3.RunQuery().
at     com.google.appengine.tools.development.ApiProxyLocalImpl$AsyncApiCall.callInternal(ApiProxyLocalImpl.java:518)
at     com.google.appengine.tools.development.ApiProxyLocalImpl$AsyncApiCall.call(ApiProxyLocalImpl.java:452)
at     com.google.appengine.tools.development.ApiProxyLocalImpl$AsyncApiCall.call(ApiProxyLocalImpl.java:430)
at java.util.concurrent.Executors$PrivilegedCallable$1.run(Executors.java:463)
at java.security.AccessController.doPrivileged(Native Method)
at java.util.concurrent.Executors$PrivilegedCallable.call(Executors.java:460)
at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:303)
at java.util.concurrent.FutureTask.run(FutureTask.java:138)
at     java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
at java.lang.Thread.run(Thread.java:662)
Caused by: java.lang.NoClassDefFoundError: org/mortbay/xml/XmlParser
at     com.google.appengine.api.datastore.dev.LocalCompositeIndexManager.getCompositeIndicesNode(LocalCompositeIndexManager.java:446)
at     com.google.appengine.api.datastore.dev.LocalCompositeIndexManager.manageIndexFile(LocalCompositeIndexManager.java:247)
at     com.google.appengine.api.datastore.dev.LocalCompositeIndexManager.processQuery(LocalCompositeIndexManager.java:200)
at     com.google.appengine.api.datastore.dev.LocalDatastoreService$9.run(LocalDatastoreService.java:1068)
at java.security.AccessController.doPrivileged(Native Method)
at     com.google.appengine.api.datastore.dev.LocalDatastoreService.runQuery(LocalDatastoreService.java:1065)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at     com.google.appengine.tools.development.ApiProxyLocalImpl$AsyncApiCall.callInternal(ApiProxyLocalImpl.java:498)
... 10 more

つまり、変更がコミットされたときにエラーが発生し (上記のpersistPageメソッドの 6 行目)、原因は次のとおりです。

java.lang.NoClassDefFoundError: org/mortbay/xml/XmlParser

何が起こっているのですか?これは大きな問題ではありませんが、プロジェクトをリポジトリにプッシュできるようにするには、このテストを Maven の事前コミットから除外する必要があります...

4

1 に答える 1

0

そのため、Maven では、Mortbay の XMLParser (GAE インデックス作成プロセスで使用されるため、永続性自体とは関係ありませんが、AppEngine の内部構造とは関係ありません) に必要なすべての依存関係はありません。他の環境では、他の XML パーサーを使用します。これらの必要な deps があります。したがって、CLASSPATH 内の jar と Maven に含まれるものをデバッグして、違いを確認してください。

于 2013-01-25T18:35:31.897 に答える