Google Web Toolkit覚書(GAEプラグイン)
流れ
Eclipseにて「Webアプリケーション・プロジェクト」を作成したら、基本的なファイルは作られる。
プロジェクトにて右クリック、実行、Webアプリケーションを選択すると、実行できる。
プロジェクト作成時に(プロジェクト名を"Sample"とする。)
war/Sample.html
が作成される。
tdタグなどにid属性をつけておく。(Javaよりそのid値を利用しアクセスする)
src/パッケージ/Sample.gwt.xml
が何者かによって呼び出される(はず)
entry-pointタグのclass属性クラスがロードされる。
そのクラスがEntryPointインターフェースを実装しており、onModuleLoadが呼び出される。
final TextBox nameField = new TextBox(); RootPanel.get("nameFieldContainer").add(nameField);
htmlのid値が"nameFieldContainer"となっているため、そのエレメント内部にTextBoxが追加される。
サーバとの通信
clientパッケージに、
GreetingServiceインターフェース
GreetingServiceAsyncインターフェース
が必要。(名前は*Service, *ServiceAsyncが妥当?)
命名規則や、シグネチャが間違っている場合は書いてる途中に、
「No asynchronous version of method メソッド名 exists in type GreetingServiceAsync」
とか言われるけど、インターフェースx2、実装クラスをちゃんと記述したらエラーは無くなる。
serverパッケージに
GreetingServiceImplクラス
が必要。(名前は*ServiceImplが妥当?)
client.GreetingServiceを実装する。(Asyncが無い方)
サーバー側は通常のJavaが利用できる。(好きに書いて良い)
クライント側はjava.lang以下+java.util以下のパッケージ以外は、googleパッケージや自作クラスのみ利用可能(?)
sharedパッケージ以下にはサーバ・クライアント両方で利用するクラスを定義する。
POJOなBeanやバリデータなどを定義するためのパッケージ?
→ただし、
・バリデータでも基本以外のクラスも利用できないので、簡単なチェックのみを記述し、実際のチェックはサーバサイドで行うべき(?)
・サーバ・クライアント間のデータを、POJOなBeanに詰めてやりとりする事は可能。ただし、それをそのまま永続化(DBに登録)はできない。(アノテーションを付けると、コンパイル時に怒られる→org.datanucleus.metadata.InvalidMetaDataException: Class com.noboru.shared.SampleModel has application-identity and no objectid-class specified yet has 0 primary key fields. Unable to use SingleFieldIdentity.)
どのパッケージをクライアント側とする(JavaScriptに変換する?)かは、Sample.gwt.xmlのsourceタグによる?
永続化(JDOの場合)
package com.sample.server; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Date; import javax.jdo.annotations.IdGeneratorStrategy; import javax.jdo.annotations.IdentityType; import javax.jdo.annotations.PersistenceCapable; import javax.jdo.annotations.Persistent; import javax.jdo.annotations.PrimaryKey; import com.sample.shared.TransModel; @PersistenceCapable(identityType = IdentityType.APPLICATION) public class StoreModel { @PrimaryKey @Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY) private Long id; @Persistent private Date date; public StoreModel() { } public StoreModel(Date date, Integer amount, String store, String note) { this.date = date; } public StoreKakeiboModel(TransModel model) { SimpleDateFormat sdf = new SimpleDateFormat(); sdf.applyPattern("yyyy/MM/dd"); try { this.date = sdf.parse(model.getDate()); } catch (ParseException e) { e.printStackTrace(); this.date = null; } } public Date getDate() { return date; } public void setDate(Date date) { this.date = date; } }
上記のように、いくつかのアノテーションが必要。
@PersistenceCapable
@PrimaryKey
@Persistent
が必要っぽい。
また、お約束クラス(?)が必要。(無くても毎回書けば動く)
package com.sample.server; import javax.jdo.JDOHelper; import javax.jdo.PersistenceManagerFactory; public class PMF { private static final PersistenceManagerFactory pmfInstance = JDOHelper .getPersistenceManagerFactory("transactions-optional"); private PMF() { } public static PersistenceManagerFactory get() { return pmfInstance; } }
transactions-optionalは、META-INFのjdoconfig.xmlによる?
いろいろ設定できるみたいだけど、不明。
デフォルトのままで動くので放置。
インサート(登録)は以下の通り
package com.sample.server; import javax.jdo.PersistenceManager; import com.google.gwt.user.server.rpc.RemoteServiceServlet; import com.sample.client.GreetingService; import com.sample.shared.KakeiboModel; public class GreetingServiceImpl extends RemoteServiceServlet implements GreetingService { public void insertNew(TransModel model) { StoreModel newModel = new StoreModel(model); PersistenceManager pm = PMF.get().getPersistenceManager(); try { pm.makePersistent(newModel); } finally { pm.close(); } } }
PersistenceManager#makePersistentの引数に永続化対象クラスを渡すだけ。
更新も同様にできる。(らしい)
SELECT(照会)は以下の通り。
@SuppressWarnings("unchecked") public List<TransModel> listAll() { List<TransModel> ret = new ArrayList<TransModel>(); PersistenceManager pm = PMF.get().getPersistenceManager(); Query query = pm.newQuery(StoreModel.class); query.setOrdering("date asc"); List<StoreModel> list = (List<StoreModel>) query .execute(); for (StoreModel storedData : list) { TransModel model = new TransModel(); model.setId(Long.toString(storedData.getId())); model.setDate(Converter.dateToString(storedData.getDate())); ret.add(model); } return ret; }
ただ、サーバ側→クライアント側では、TransModelのコンストラクタにStoreModelを渡したりはできない。(serverパッケージをインポートできないため。)
サーバ側に、ファクトリークラスを作ったりしたらよい?
まとめ
GWTをやる気が薄れてきたので、文字として残しておく。
後で参考になるといいな。