GWTの基本
最初にGWTを見たときにはASP.NET/WebFormsのGoogle版なのだろう思ったのだが(だからこそスルーした)、実際に少し触ってみるとどうもそうではないようだ。
GWTで書くJavaクラスは実行時にレンダリングされるWebページと透過なものではなく、HTMLのDOM要素にGWTのウィジェットクラスのインスタンスをバインドする、という仕組みでクライアント側のGUI処理が実現されている。
典型的なGWTのGUI初期処理
final TextBox nameField = new TextBox(); RootPanel.get("nameFieldContainer").add(nameField);
RootPanelはGWTウィジェットのルートコンテナであり、getメソッドはHTML上のid要素と関連付けられたインスタンスを取得する。(デフォルトはbody要素)その後のaddメソッドで生成したウィジェットクラス(ここではTextBoxクラス)からHTML要素を生成して、関連付けされたHTMLの要素中に追加するのである。
上記コード実行後のHTML要素
<td id="nameFieldContainer"> <input type="text" class="gwt-TextBox"> <= 挿入されたintput要素 </td>
このように、なんらかのHTML要素とGWTのコンテナを結びつけた上でウィジェットクラスをコードでを配置していくのがGWTの基本的なスタイルだ。(UIBinderという.NETのコードビハインドのような仕組みもあるらしいが、今は言及しない)
HTML上のid要素に依存しているのはどういうことか、実際に試してみよう。上記コードで参照しているid要素"nameFieldContainer"はウィザードで自動的に生成された"TestEcho.html"上にあるが、これをコメントアウトしてアプリケーションを実行してみる。
TestEcho.html(抜粋)
<h1>Web Application Starter Project</h1> <table align="center"> <tr> <td colspan="2" style="font-weight:bold;">Please enter your name:</td> </tr> <tr> <!-- <td id="nameFieldContainer"></td> --> <td id="sendButtonContainer"></td> </tr> <tr> <td colspan="2" style="color:red;" id="errorLabelContainer"></td> </tr> </table>
実行結果
11:52:29.015 [ERROR] [testecho] Unable to load module entry point class net.kazzz.gwt.test.client.TestEcho (see associated exception for details) java.lang.NullPointerException: null at net.kazzz.gwt.test.client.TestEcho.onModuleLoad(TestEcho.java:52) 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.gwt.dev.shell.ModuleSpace.onLoad(ModuleSpace.java:396) at com.google.gwt.dev.shell.OophmSessionHandler.loadModule(OophmSessionHandler.java:183) at com.google.gwt.dev.shell.BrowserChannelServer.processConnection(BrowserChannelServer.java:510) at com.google.gwt.dev.shell.BrowserChannelServer.run(BrowserChannelServer.java:352) at java.lang.Thread.run(Thread.java:662)
とコード中で参照しているid要素をコメントアウトするとこのように例外が発生してしまう。