Google Web Toolkitで遊んでみました その2
その1からの続きです。今日は実際にGWTを使ったアプリケーションの開発に挑戦してみました。ただ、いきなりAJAX的にサーバとクライアントの間で非同期に通信をおこなうアプリケーションを作るのは大変なので、とりあえずGWTのクラスライブラリに慣れるために単純なコードを書いてみました。
まず適当なディレクトリを作り、そこから以下のようにapplicationCreatorを実行します。引数は適当なパッケージ名+メインのクラス名です。
applicationCreator com.google.code.myproject.client.MyApplication
するとHello World的な単純なアプリケーションのコードが生成されます。MyApplication-shellを実行すると以下のようなホステッドモードの画面になります。
これをひな型として、不要な部分を削り、必要なコードを加えていくことでオリジナルのアプリケーションを作成します。
具体的にはsrc/com/google/code/myproject/client/MyApplication.java
を編集して、ホステッドモードでRefreshボタンを押すだけでOKです。JavaScriptプログラミングと同じノリですね。GWTのウィジェットが実際にHTML内にどのように配置されるかはwww/com.google.code.myproject.MyApplication/MyApplication.html
というHTMLファイルを編集して決めます。
今回作成したプログラムは以下の通りです。Googleの高度な次世代テクノロジーにより、正確かつ客観的に中年であるか判定します。
package com.google.code.myproject.client;
// GWTクラスライブラリのAPIドキュメントは以下のURLを参照。
// http://code.google.com/webtoolkit/documentation/gwt.html
import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.user.client.ui.ListBox;
import com.google.gwt.user.client.ui.ChangeListener;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.RootPanel;
import com.google.gwt.user.client.ui.Panel;
import com.google.gwt.user.client.ui.Widget;
// 使用可能なJavaクラスの一覧は以下のURLを参照。
// http://code.google.com/webtoolkit/documentation/jre.html
import java.util.Date;
/**
* MyApplicationをEntryPointインタフェースのonModuleLoad()メソッドを実装したクラスとして定義。
*/
public class MyApplication implements EntryPoint {
private ListBox yearBox;
private ListBox monthBox;
private ListBox dateBox;
private final Label label = new Label();
// 年月日を選択するリストボックスが変更されたときに呼ばれるリスナー。中年判定をおこない、
// 結果文字列をlabelにセットする。
private class BirthdayChangeListener implements ChangeListener {
public void onChange(Widget sender) {
try {
int year = Integer.parseInt(yearBox.getValue(yearBox.getSelectedIndex()));
int month = Integer.parseInt(monthBox.getValue(monthBox.getSelectedIndex()));
int date = Integer.parseInt(dateBox.getValue(dateBox.getSelectedIndex()));
// 35歳の誕生日(0時0分)
Date birthday35th = new Date(year - 1900 + 35, month - 1, date);
// 50歳の誕生日(0時0分)
Date birthday50th = new Date(year - 1900 + 50, month - 1, date);
// 今日の日付(現時刻)
Date today = new Date();
// 日付の前後関係を使って判定する。現在の年齢を計算するより簡単。
if (today.after(birthday35th) && today.before(birthday50th)) {
label.setText("You are middle aged.");
} else {
label.setText("You are not middle aged.");
}
} catch (Exception e) {
// 例外処理: 数字をリストボックスで選択するだけなので通常はエラーは起こらない。
// 2月31日のようにカレンダー上に存在しない日を入力しても例外は発生しないらしい。
label.setText("Exception: " + e);
}
}
}
// 一定範囲の数字を選択するためのListBoxを作って返す。ListBoxには
// 上で定義した BirthdayChangeListener をリスナーとして登録。
private ListBox createRangeMenu(int start, int end) {
ListBox listBox = new ListBox();
for (int i = start; i <= end; ++i)
listBox.addItem(String.valueOf(i), String.valueOf(i));
listBox.addChangeListener(new BirthdayChangeListener());
return listBox;
}
/**
* EntryPointインタフェースの実装。モジュールがロードされたときに呼ばれるので、
* ここでインスタンスの初期化をおこなう。
*/
public void onModuleLoad() {
yearBox = createRangeMenu(1900, 2000);
monthBox = createRangeMenu(1, 12);
dateBox = createRangeMenu(1, 31);
// ここでは簡単のため、MyApplication.html に最初から用意されている slot1, slot2 という
// 要素に年月日のListBoxと判定結果labelをそれぞれ配置する。
Panel slot1 = RootPanel.get("slot1");
slot1.add(yearBox);
slot1.add(monthBox);
slot1.add(dateBox);
RootPanel.get("slot2").add(label);
}
}
冗談はともかく、このような小さなアプリケーションでもGWTの有効性は実感できました。GWTのウィジェットやイベントはAWTやSwingと似ていますし、慣れているJava用のエディタやデバッガが使えるのは、新しいことをおぼえるのが億劫になりつつあるお年頃の人間にとっては助かります。コンパイル時のエラーでいくつかのバグを未然に防ぐことができましたし、実行時のバグもExceptionが(制限つきながら)使えるおかげで簡単にわかりました。
ただし、どんなJavaプログラムでもJavaScriptに変換できるわけではありません。この例ではjava.util.Dateを使いましたが、Java標準クラスライブラリはjava.langとjava.utilの一部しか使えません。スレッドが使えないといったやむを得ない制約もあります。GWTを使ったからといってJavaScriptでできないことができるようにはなりません。JavaScriptでできる範囲のことを、Javaのスタイルできれいに書くためのフレームワークがGWTなのだと思います。
GWTを使っているとJavaがクライアント側の開発に使われる言語だと考えられていた時代、つまりJavaといえばJavaアプレットだった時代を思い出します。いつの間にかJavaはサーバ側の開発にばかり用いられるようになってしまいましたが、思わぬ形でクライアント側に帰ってきたなあという印象です。GWTがブラウザ毎の違いを考慮したコードを出力してくれるので、"Write once, run anywhere"的でもあります。
Googleで実際にGWTを使っている例としてはGoogle Image Labelerがあります。HTMLソースを見てみれば、gwt.jsを読み込んでいることがわかります。ちなみにこれは先日、当ブログで紹介されていたアレのGoogleによる実装です。
GWTはGoogleの提供する様々なAPIへの対応もおこなっていく予定となっており、現時点ではGoogle Gears APIを正式にサポートしています。GWTとGearsを組み合わせると、通常のデスクトップアプリケーションに近い操作性を持ったウェブアプリケーションの開発も容易になるでしょう。
最近は様々なウェブアプリケーション開発フレームワークが登場していますが、Javaプログラマの皆さんにはGWTもぜひ選択肢の一つに入れていただければと思います。