Google App Engine JDO3に対応する方法


古いGoogle App Engineのプロジェクトを新しいプロジェクトに対応するため、
[Google Plugin for Eclipse から Cloud Tools for Eclipse](https://qiita.com/kazuki1600/items/360f649d158cd81191c2) 
を参考に動くようにはなったが、データベース関係が動かない。

これはJDOを新しいものに対応しないといけないから。基本的には、BigTable関係のコードもそのまま動くが、ビルドした後に一手間を加えないといけなくなった。
その理由は、Cloud Toolsがクラスの自動拡張に対応しなくなったこと。そのため、JDOUserException が発生し、
クラス名 does not seem to have been enhanced.
といったエラーが出る。

クラスの拡張を行うために、コマンドで行う方法もあるようだが、build.xmlを配置すれば、Eclipseだけで出来た。いろいろ苦戦したが最終的には動くようになった。その方法をまとめる。

参考：
[App Engine での JDO 3.0 の使用](
https://cloud.google.com/appengine/docs/standard/java/datastore/jdo/overview-dn2?hl=ja)

###１．build.xmlをプロジェクトルート直下に置く

build.xmlはAnt用の設定ファイル。これを以下のように新規に作成。
(appengine-java-sdkのディレクトリを指定)にはダウンロードしたappengine-java-sdkのディレクトリを指定する。

```
<project name="JDO Examples" default="datanucleusenhance">
  <property name="appengine.sdk" location="(appengine-java-sdkのディレクトリを指定)" />

  <import file="${appengine.sdk}/config/user/ant-macros.xml" />

  <path id="project.classpath">
    <pathelement path="war/WEB-INF/classes" />
    <fileset dir="war/WEB-INF/lib">
      <include name="**/*.jar" />
    </fileset>
    <fileset dir="${appengine.sdk}/lib">
      <include name="shared/**/*.jar" />
    </fileset>
  </path>

  <target name="copyjars"
      description="Copies the App Engine JARs to the WAR.">
    <mkdir dir="war/WEB-INF/lib" />
    <copy
        todir="war/WEB-INF/lib"
        flatten="true">
      <fileset dir="${appengine.sdk}/lib/user">
      	<include name="**/appengine-api-1.0-sdk*.jar" />
      </fileset>

      <fileset dir="${appengine.sdk}/lib/opt/user">
         <include name="appengine-api-labs/v1/*.jar" />
         <include name="jsr107/v1/*.jar" />
         <include name="datanucleus/v2/*.jar" />
      </fileset>

    </copy>
  </target>

  <target name="compile" depends="copyjars"
      description="Compiles Java source and copies other source files to the WAR.">
    <mkdir dir="war/WEB-INF/classes" />
    <copy todir="war/WEB-INF/classes">
      <fileset dir="src">
        <exclude name="**/*.java" />
      </fileset>
    </copy>
    <javac
        srcdir="src"
        destdir="war/WEB-INF/classes"
        classpathref="project.classpath"
        debug="on" />
  </target>

  <target name="datanucleusenhance" depends="compile"
      description="Performs JDO enhancement on compiled data classes.">
    <enhance_war war="war" >
    	<args>
    		<arg value="-enhancerVersion" />
    		<arg value="v2" />
    	</args>
    </enhance_war>
  </target>

  <target name="runserver" depends="datanucleusenhance"
      description="Starts the development server.">
    <dev_appserver war="war" />
  </target>

  <target name="update" depends="datanucleusenhance"
      description="Uploads the application to App Engine.">
    <appcfg action="update" war="war" />
  </target>

  <target name="update_indexes" depends="datanucleusenhance"
      description="Uploads just the datastore index configuration to App Engine.">
    <appcfg action="update_indexes" war="war" />
  </target>

  <target name="rollback" depends="datanucleusenhance"
      description="Rolls back an interrupted application update.">
    <appcfg action="rollback" war="war" />
  </target>

  <target name="request_logs"
      description="Downloads log data from App Engine for the application.">
    <appcfg action="request_logs" war="war">
      <options>
        <arg value="--num_days=5"/>
      </options>
      <args>
        <arg value="logs.txt"/>
      </args>
    </appcfg>
  </target>

</project>
```

###２．jdoconfig.xmlを修正

具体的には 
xsi:schemaLocation 
の行と
value="org.datanucleus.api.jdo.JDOPersistenceManagerFactory"
の行

```
<?xml version="1.0" encoding="utf-8"?>
<jdoconfig xmlns="http://java.sun.com/xml/ns/jdo/jdoconfig"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/jdo/jdoconfig http://java.sun.com/xml/ns/jdo/jdoconfig_3_0.xsd">

   <persistence-manager-factory name="transactions-optional">
       <property name="javax.jdo.PersistenceManagerFactoryClass"
            value="org.datanucleus.api.jdo.JDOPersistenceManagerFactory"/>
       <property name="javax.jdo.option.ConnectionURL" value="appengine"/>
       <property name="javax.jdo.option.NontransactionalRead" value="true"/>
       <property name="javax.jdo.option.NontransactionalWrite" value="true"/>
       <property name="javax.jdo.option.RetainValues" value="true"/>
       <property name="datanucleus.appengine.autoCreateDatastoreTxns" value="true"/>
   </persistence-manager-factory>
</jdoconfig>
```

###３．WEB-INF/libのライブラリを更新
datanuleusの古いものを削除し新しいものを入れる。
appengine-java-sdkの
lib/opt/user/datanucleus/v2

###４．アップ前にbuild.xmlを右クリックし、[実行]-[Ant...]を行う。

ここでのエラーは３で古いものが残っているためなことが多い。

###５．アップロード