環境
クラウド ベースの 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 の事前コミットから除外する必要があります...