きっかけ:Java8へのマイグレーション
去年辺りから、GAEはjava7をサポートしなくなるので、java8対応してくださいね、というお知らせがGoogleから来ていました。
マイグレーションのページ
https://cloud.google.com/appengine/docs/standard/java/migrating-to-java8
を見ると、appengine-web.xmlにちょっと書き足せばいいだけっぽいので楽勝だなとか思って即対応はせず、先日まで放置していたのですが、いざやってみたら大変でかなり焦りました。
slim3を使用している場合はCloud tools for Eclipseの環境に移行してちょっと直せば終わりみたいな感じで、簡単なようなのですが、私が担当したプロジェクトはslim3は使っておらず、GWT+JDOを使用しており、移行の最中さまざまなエラーが出て、さらに日本語の情報が少なく、かなり苦労しました。
以下、私が都度調べながら実際に行った作業を記します。他にいい方法、あるいは記述自体に間違いがある可能性が充分あるので、(万一参考にするなら)ご注意ください!!
作業開始
元々の開発環境はEclipse Juno (4.2) + Google Plugin for Eclipseです。
これで、フロントエンドはGWT、データベースはJDOを使ったプロジェクトを作っていました。
■appengine-web.xmlに追記
まず、マイグレーションのページに従ってappengine-web.xmlに<runtime>java8</runtime>を追加しました。
で、ビルドすると、xmlのパースエラーが発生しました。
使用しているAppEngineのSDKが1.9.12と(相当)古いせいで、xsdに<runtime>タグが定義されていないせいのようです。
SDKのdocs\appengine-web.xsdを見るとわかりました。
■SDKを新しく
なので現時点で最新のSDK(1.9.63)をダウンロード、これを使用するようにしました。xsdに<runtime>タグがあり、パースエラーにはならず、ビルドとデプロイができました。管理ページのインスタンス情報を見るとjava8となっており、よし完了!と思った
のですが・・・
サイトにアクセスし、Datastoreへアクセスする処理を実行すると、サーバーエラーが発生します。ログを見ると「Persistent class ○○ does not seem to have been enhanced.」と出力されていました。
プロジェクトをクリーンしたりすると解消する、という情報などなどあるものの、何をやっても解消しませんでした。
(これは結局未解決)
■Cloud Tools for Eclipseに移行
そもそも今の環境(Eclipse Juno (4.2) + Google Plugin for Eclipse)は古く、Cloud tools for Eclipseへの移行が推奨されています。
https://cloud.google.com/eclipse/docs/migrating-gpe?hl=ja
古い環境で悩みながらやるよりも、いっそ環境を新しくすれば解決するのでは?という根拠のない予想のもと、上記ページを参照し、新環境を作成しました。
いきなり問題のプロジェクトを新環境に移行するのも怖いので、GWT+JDOを使用するテストプロジェクトを新規作成します。
ビルドしたところエラーなく完了し、Cloud tools for Eclipseによるデプロイも成功しました。これでどうかな、とテストしてみると…
■GWTのモジュールがアップロードされてない?
トップページにアクセスすると、GWTモジュールを使用している部分が真っ白です。ブラウザの開発ツールを使用し詳細を見てみると、xxxx.nocache.jsが404になっています。
nocache.jsはGWTが出力するファイルで、これがどうもアップロードされていないようです。
Cloud tools for Eclipseによるデプロイは、ログが出るものの、基本的にプラグインにおまかせになるので、原因が良くわかりません。ログにも特に変なことは書かれていません。
さらに・・・
■Persistent class ○○ does not seem to have been enhanced.がまた出た
JDOを使用してDatastoreの処理を行う部分を実行すると、サーバーエラー。ログを見ると、旧環境の本物のプロジェクトで出ていたPersistent class ○○ does not seem to have been enhanced.が、このテストプロジェクトでも出ていました。
旧環境で出ていた原因は結局わかりませんでしたが、新環境でこのエラーになる理由はわかりました。
https://cloud.google.com/eclipse/docs/migrating-gpe?hl=ja
の中程に↓という記述があります。
【DataNucleus(JPA & JDO)
Cloud Tools for Eclipse はエンティティ クラスを自動拡張しません。
この機能には Maven を使用することができます。】
そんな…Maven?
■Maven
Mavenとは、で検索するといっぱい情報ありますので詳しくはそちらに譲りますが、要はpom.xmlというファイルにプロジェクト情報、参照ライブラリ、ビルド手順などを記述するタイプのビルドツールです。
pom.xmlをどうやって書けばいいのでしょう。
①App Engine Standard Projectのpom.xmを手に入れる
Cloud tools for Eclipseでプロジェクトを作る際、Create as Maven projectというチェックボックスがあります。デフォルトはOFFですが、ONにして作成すると、プロジェクトのルートディレクトリにpom.xmlが作成されます。
pom.xmlを見るとApp Engineに関する記述がありますが、当然ながらGWTに関する記述はありません。
そこで、、、
②GWTのpom.xmlを手に入れる
GWT Eclipse Plugin (V3)でプロジェクトを作成する際の画面も、よく見るとGenerate a Maven Projectというチェックボックスがあります。(デフォルトはOFF)
ONにして作成すると、GWTに関する記述が含まれたpom.xmlが作成されます。
③datanucleusに関するpom.xmlを手に入れる
そもそもMavenでのデプロイにチャレンジしたのは
【DataNucleus(JPA & JDO)
Cloud Tools for Eclipse はエンティティ クラスを自動拡張しません。
この機能には Maven を使用することができます。】
これが原因です。pom.xmlに、JDOを使用する&エンテティクラスを拡張してくれるよう記述しないといけません。
http://www.datanucleus.org/products/accessplatform_4_1/jdo/maven.html
このあたりを参考にします。
■①+②+③ = pom.xml完成!
Mavenが初めてなので綱渡りな感じだったのですが、なんとか完成しました。概ね①+②+③のpom.xmlを作成した感じです。ビルドするとエラーが出たりしましたが、エラーメッセージで検索して都度微調整しました。(長くなるので割愛)
■Datastoreのインデックスが作られない
サイトにアクセスすると、GWTもDatastoreも使用できます。やった!
しかし、一部処理でエラーが出ます。ログを見ると、そのクエリにはこういうインデックスが必要だよ。という良く見る内容が出ていました。datastore-indexes.xmlは既にそのように書いていて、mvn packageで出来るwarファイルにも含まれているのになぜ?
https://cloud.google.com/appengine/docs/standard/java/config/indexref?authuser=3&hl=ja
datastore-indexes.xmlはApp Engine SDK for Javaに基づくツールで使われる、とのこと。Mavenでビルド、デプロイの際には使われないようです。(ファイル自体が含まれるのは含まれるようですが)
これに関する解決方法は2つあります。
・datastore-indexes.xmlを適用するために、適当なバージョンを指定してCloud tools for Eclipseによるデプロイだけ行う。
・gcloudツールでindex.yamlを使用してインデックスを作成する。
https://cloud.google.com/datastore/docs/tools/?hl=ja#the_development_workflow_using_gcloud