Language support

前回、GWT Designerで"NoClassDefFoundError"が発生する件だが、いろいろ試した結果、国際化リソース※をロードするためのインタフェースをロードするのに失敗していることが判った。

AddressInfoComposite
    static IAddressBookConstants constants = 
        (IAddressBookConstants)GWT.create(IAddressBookConstants.class);
    private Label fullNameLabel = new Label(constants.fullName());
    private TextBox fullNameTextBox = new TextBox();

このコード片で言うと、IAddressBookConstants.classがロードできないのである。

ならばと文字列を使ってクラスをロードする方法に変更しようと思ったのだが、GWT#createメソッドに文字列をシグネチャに持つオーバーロードは無いため、仕方が無いのでClassクラスのメソッドを使ってやはり文字列からクラスロードしようと思って以下のようにコーディングをしたのだが、

    static IAddressBookConstants constants = 
    static {
        constants = 
                (IAddressBookConstants)GWT.create(
                        Class.forName("net.kazzz.client.IAddressBookConstants"));
    }

今度は、こんなことを言われる。

GWT Designerのログより
java.lang.Error: Unresolved compilation problem: 
	The method forName(String) is undefined for the type Class
    :
    :

Class.forName(String)というメソッドが無い!? そんなバカな。と思った後で、このクラスはJavaであってJavaではないことに気がついた。
GWTのアプリケーションで/client配下に作成されるクラスはGWTによりコンパイルされてJavascriptとして実行されるため、Javaと互換性にはかなりの制限があるのだ。

Compatibility with the Java Language and Libraries - Coding Basics - Google Web Toolkit - Google Code

特にこの行に注目だ。

  • Reflection: For maximum efficiency, GWT compiles your Java source into a monolithic script, and does not support subsequent dynamic loading of classes. This and other optimizations preclude general support for reflection. However, it is possible to query an object for its class name using Object.getClass().getName().

JavaクラスがGWTによってどのようにエミュレートされるかの記述もある。
JRE Package java.lang - Emulation Reference - Google Web Toolkit - Google Code

Classクラスに至っては以下のメソッドしかサポートされていないようだ。
desiredAssertionStatus(), getEnumConstants(), getName(), getSuperclass(), isArray(), isEnum(), isInterface(), isPrimitive(), toString()

これでGWT.createメソッドを使う理由がようやく判った。

GWTの国際化に関しては別途ネタにする予定。