GWTの基本

最初にGWTを見たときにはASP.NET/WebFormsのGoogle版なのだろう思ったのだが(だからこそスルーした)、実際に少し触ってみるとどうもそうではないようだ。
GWTで書くJavaクラスは実行時にレンダリングされるWebページと透過なものではなく、HTMLのDOM要素にGWTウィジェットクラスのインスタンスをバインドする、という仕組みでクライアント側のGUI処理が実現されている。

典型的なGWTGUI初期処理
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要素をコメントアウトするとこのように例外が発生してしまう。