本文へジャンプ

「送信する」をクリックすることにより、お客様は developerWorks のご使用条件に同意したことになります。 ご使用条件を読む


お客様が developerWorks に初めてサインインすると、プロフィールが作成されます。プロフィールで選択した情報は公開されますが、いつでもその情報を編集できます。お客様の姓名(非表示設定にしていない限り)とディスプレイ・ネームは、投稿するコンテンツと一緒に表示されます。

送信されたすべての情報は安全です。

  • 閉じる [x]

developerWorks に初めてサインインするとプロフィールが作成されますので、その際にディスプレイ・ネームを選択する必要があります。ディスプレイ・ネームは、お客様が developerWorks に投稿するコンテンツと一緒に表示されます。

ディスプレイ・ネームは、3文字から31文字の範囲で指定し、かつ developerWorks コミュニティーでユニークである必要があります。また、プライバシー上の理由でお客様の電子メール・アドレスは使用しないでください。

「送信する」をクリックすることにより、お客様は developerWorks のご使用条件に同意したことになります。 ご使用条件を読む


送信されたすべての情報は安全です。

  • 閉じる [x]

レガシーなやり方を高度な GWT コントロールに導く

JavaScript ライブラリーを統合して Google Web Toolkit ウィジェットを機能強化する

Sergey Odobetskiy (s.odobetsky@gmail.com), Software development consultant , Freelance
Sergey Odobetskiy は Java と Web 技術を専門とするソフトウェア開発コンサルタントです。彼は最近、Rogers Communications でのいくつかのテレコム・プロジェクトに従事してきました。現在は Toronto にある ConceptWave Software Inc. で、テレコミュニケーションによる発注管理製品の業務に取り組んでいます。

概要: GWT (Google Web Toolkit) は、Java™ プログラミング言語で Ajax アプリケーションを開発するためのライブラリーやツールを提供しています。しかし残念なことに、GWTの標準 UI コントロール (ウィジェット) のギャラリーは、最近のエンタープライズ・アプリケーションで要求される高度な機能を提供していません。この記事は、この高度な機能を提供するための手法を説明します。比較的単純なコーディングによって一般的なJavaScript グリッド・コンポーネントと GWT アプリケーションとを統合することで、GWT コントロールに高度な機能を持たせる方法を学びましょう。

日付:  2007年 4月 24日
レベル:  上級 この記事の原文:  英語
アクティビティー: 3938 ビュー
お気軽にご意見・ご感想をお寄せください: 


オープン・ソースの Ajax フレームワークと商用ツールキットは、下位レベルの JavaScript と DOM (Document ObjectModel) 操作の複雑さと重荷を隠すことで、Ajax 開発をもっと取りかかりやすいものにしようとしています。多くの場合、そうしたフレームワークやツールキットは開発時間を削減するためには役立ちますが、それらを使って高度な機能を実現しようとすると、簡単には身につけられないような、高度なスキルとJavaScript の知識を要求されることが普通です。しかし Google は、Ajax アプリケーション開発をまったく新しいレベルに高める革新的な技術をもたらしました。GWTは API やツールを包括的に集めたものであり、GWT を利用すれば動的な Web アプリケーションを Java コードで作成することができます。GWTはこれを、コード生成によって実現しています。GWT コンパイラーは、さまざまなブラウザーと互換性を持つ JavaScript を、クライアント・サイドのJava コードから生成します。

しかし残念なことに、Google が提供する標準の UI コントロール (ウィジェット) の機能は限定されており、たいていの場合、最近のエンタープライズ・クラスのアプリケーションには不十分です。一連のカスタム・プロパティーを使って基本的なGWT コントロールを拡張することはできますが、その多くはかなりの開発努力が要求されます。幸いなことに、もっと容易な方法があります。この記事ではサンプル・アプリケーション(「ダウンロード」セクションを参照) を利用して、一般的な ActiveWidgets JavaScript グリッド・コンポーネントを GWT アプリケーションと統合し、比較的単純なコーディングで高度な機能を実現するための方法を説明します。


動的な Web UI コントロール

JavaScript による Web UI コントロールは、HTML をブラウザー内部で動的に生成することでサーバーへの往復時間をなくすように設計されています。サーバーは静的なHTML を送信する代わりに、動的コンポーネントのためのデータ構造と JavaScript コードをページ内容に追加します。ブラウザーは、ページをロードする際にそのスクリプトを実行してアクティブなコンポーネントを作成し、それらを構成し、そして各コンポーネントが生成するHTML ストリングをページ上の適切な場所に挿入します。この時点以降は、JavaScript コンポーネントのコードはページ上の HTML フラグメントに結びつけられます。このコンポーネントはユーザーとの対話動作を処理し、データの変化に応じてHTML を更新し、またそのコンポーネントの内容や動作、視覚スタイルを操作するための API を提供します。

Java コードで開発され JavaScript にコンパイルされる GWT コントロールも、それとまったく同じように動作します。そのため GWTコントロールは、商用のコントロールや JavaScript ライブラリーと完全な互換性があります。JavaScript ライブラリーは成熟しており、さまざまなブラウザーで動作する高度な機能(インテリジェントなスクロールや列のサイズ変更、ソート、動的ロード、大規模データ・セットに対するページングなど) を完璧に備えて提供しています。GWTの持つオープンなアーキテクチャーを利用すれば、商用のコントロールや JavaScript のレガシー・ライブラリーを新しいアプリケーションと統合することができ、既に作成されているおなじみのものを再度作成する無駄をせずにエンタープライズ・レベルの課題に集中することができます。



自動リソース・インジェクション

この記事のサンプル GWT アプリケーション (「ダウンロード」を参照) は、GWT の便利な機能、自動リソース・インジェクション (automatic resource injection) を使っています。プロジェクト・モジュールには外部のJavaScript ファイルと CSS (Cascading Style Sheets) ファイルへの参照が含まれているため、このモジュール自体がロードされると、そうしたファイルも自動的にロードされます。リスト1 は、これを実現するための方法で、サンプル・アプリケーションのモジュールを定義する XML ファイルの中の宣言を示しています。


リスト 1. GWT のモジュール定義
                
<module>
  <inherits name='com.google.gwt.user.User'/>
  <entry-point class='com.mycompany.project.client.GridDemo'/>
  
  <source path="client"/>

  <stylesheet src="runtime/styles/xp/aw.css"/>
  <script src="runtime/lib/aw.js"> 
    <![CDATA[ 
     if ($wnd.AW.Grid.Control.create) 
       return true; 
     else 
       return false; 
   ]]> 
  </script>
</module>

JavaScript ファイルとスタイルシートをインジェクションによる方法は、外部ファイルを自動的に GWT モジュールと関連付けるための便利な方法です。インジェクトされたすべてのリソースを、GWTWeb サーバーのルートを定義する com\mycompany\project\public ディレクトリーに置く必要があります。

AW.Grid.Control.create はスクリプト ready 関数であり、グリッド・コントロール・スクリプトが初期化されることがわかっている場合に true を返します。ready 関数の目的は、そのスクリプトが完全にロードされたことを明確に判断することです。それによって GWT コードはそのスクリプトを使用でき、また参照される識別子が用意できていることを確認できます。リスト1 の例では、AW.Grid.Control.create 関数が存在していることで、スクリプトが用意できていることがわかります。この関数は GWT コントロールのライブラリーの一部であり、また外部リソースとして、この関数には$wnd という接頭辞を付ける必要があります。



JavaScript Native Interface が救いに

JavaScript グリッド・コントロールの統合そのものは、GWT の JSNI (JavaScript Native Interface)の実装を基にしています。JSNI は、Java ソース・コードに JavaScript コードを含められる強力な機能です。リスト 2 は、JavaScriptグリッド・コントロールが JSNI によってインスタンス化され、初期化される様子を示しています。


リスト 2. グリッド・コントロールの初期化 (一部)
                
native JavaScriptObject init(JavaScriptObject myColumns,JavaScriptObject myData)/*-{
  try{
    $wnd.mygrid = new $wnd.AW.UI.Grid;
    $wnd.mygrid.setSize(750, 350);

    // provide cells and headers text
    $wnd.mygrid.setCellText(myData);
    $wnd.mygrid.setHeaderText(myColumns);

    // set number of rows/columns
    $wnd.mygrid.setRowCount(myData.length);
    $wnd.mygrid.setColumnCount(myColumns.length);
    ...
    $doc.getElementById('mygrid').innerHTML = $wnd.mygrid;

    return $wnd.mygrid;
  }
  catch(e){
    $wnd.alert(e.description);
  }

  return null;

}-*/;

JSNI は、インライン・アセンブリー・コードの Web 版と考えることができます。JSNI を使うことで、

  • Java メソッドを直接 JavaScript で実装することができます。
  • 既存の JavaScript の前後をタイプセーフな Java メソッド・シグニチャーでラップすることができます。
  • JavaScript から Java コードを呼ぶことができ、その逆も可能です。
  • Java/JavaScript の境界にまたがって例外をスローすることができます。
  • JavaScript から Java フィールドを読み書きすることができます。
  • ホスト・モードを使うことで、Java ソースと JavaScript の両方をデバッグすることができます (Java ソースは Java デバッガーで、JavaScriptはスクリプト・デバッガーでデバッグします)。

GWT の開発用ドキュメンテーションでは、JSNI を慎重に使うように警告されています。その理由は、ブラウザー間の移植性が保証されておらず、コンパイルされるコードの最適化が限定的であるためです。商用コントロールの場合には、複数のブラウザー・タイプとデプロイメント・プラットフォームをサポートするというベンダーの確約に委ねることができます。

JSNI からブラウザーのウィンドウと文書オブジェクトにアクセスする際には、それぞれを $wnd$doc として参照する必要があります。コンパイルされたスクリプトはネストされたフレームで実行され、$wnd$doc は自動的に初期化されてホスト・ページのウィンドウと文書を正しく参照します。

サンプル・コードは JSNI を使った便利な方法を示しています。ここでは 1 次元と 2 次元の Java ストリング配列を JavaScript配列に変換し、そしてグリッドにデータを追加しています (リスト 3)。


リスト 3. Java から JavaScript への配列変換
                
public static JavaScriptObject arrayConvert(String[] array) { 
    JavaScriptObject result = newJSArray(array.length); 
    for (int i = 0; i<array.length; i++) { 
      arraySet(result, i, array[i]); 
    } 
    return result; 
} 

private static native JavaScriptObject newJSArray(int length) /*-{ 
    return new Array(length);  
}-*/; 

public static native int arrayLength(JavaScriptObject array) /*-{ 
    return array.length; 
}-*/; 

public static native String arrayGetObject(JavaScriptObject array, int index) /*-{ 
    return array[index]; 
}-*/; 

public static native void arraySet(JavaScriptObject array,int index,String value) /*-{ 
    array[index] = value; 
}-*/;



イベントを処理する

JavaScript で定義されたイベント・ハンドラーは、Java コードで実装されるメソッドと関連付けられます。リスト 4 は、グリッド・コントロールのonRowClicked イベントが onRowSelect という Java 関数を呼び出す様子を示しています。


リスト 4. JavaScript から Java 関数を呼び出す
                
public void onRowSelect(String index){
  GWT.log("Row #" + index + "selected", null);
}

native JavaScriptObject init(JavaScriptObject myColumns, JavaScriptObject myData)/*-{
  var widget = this;
  
  try{
      ... 
      // set click action handler
      $wnd.mygrid.onRowClicked = function(event, index){

widget.@com.mycompany.project.client.GwtGrid::onRowSelect(Ljava/lang/String;)(index);
      };

      ...
 }
 catch(e){
  $wnd.alert(e.description);
 }
}-*/;

JavaScript で Java メソッドを参照するためには、次のような表記を使う必要があります。instance-expr.@class-name::method-name(param-signature)(arguments)

  • instance-expr. は、インスタンス・メソッドを呼び出す際には必要であり、静的メソッドを呼び出す際には存在してはなりません。
  • class-name は、メソッドが宣言されているクラス (あるいはそのサブクラス) の完全修飾名です。
  • param-signature は、ここで指定される内部 Java メソッド・シグニチャーですが、その後にメソッド戻り型のシグニチャーはありません (オーバーロードを選択するためには必要ないためです)。
  • arguments は、呼び出されたメソッドに渡される実際の引数リストです。


JavaScript コントロール API を使う

リスト 2を見るとわかるように、この実装の Java クラスの init メソッドは、グリッド・インスタンスを表す JavaScriptObject を返します。このオブジェクトはクラス属性として保存することができ、また、後でこれをコードの中で参照して JavaScript コントロールAPI メソッドを呼び出すことができます。リスト 5 は、Delete ボタンのクリック・イベントが Java コードで処理される様子を示しています。


リスト 5. JavaScript メソッドを呼び出す
                
protected JavaScriptObject grid = null;

...

public void onLoad(){
  if(grid == null){
    grid = init(...);
  }
}

public void onDeleteButtonClick(){
  delete(grid, getCurrentRow(grid));
}


public native void delete(JavaScriptObject obj, int index) /*-{

 try{
    obj.deleteRow(index);
 }
 catch(e){
    $wnd.alert(e.description);
 }

}-*/;   

public native int getCurrentRow(JavaScriptObject obj) /*-{
 
  try{
    return obj.getCurrentRow();
  }
  catch(e){
    $wnd.alert(e.description);
  }

  return -1;

}-*/;

リスト 5 で、Java イベント・ハンドラーは JavaScript コントロール API メソッドを呼び出します。これは、このコントロール・インスタンスとの対話機能を示しています。同様のJava ラッパーをすべての JavaScript コントロール API メソッドに対して定義し、それらを GWT の世界で利用できるようにすることができます。



ランタイムの構成

このデモ・アプリケーションを利用するためには、システムに GWT SDK をインストールする必要があります。サンプル・コードを実行するためには、ダウンロードしたアーカイブ(ソースと、コンパイルされたスクリプトが入っています) を、GWT SDK ディストリビューションのディレクトリーの samples フォルダーの中に単純に解凍します。GWTのサンプルを実行できれば、次のコマンドを使ってサンプル・アプリケーションを起動することができます (Windows プラットフォームの場合)。

                your_local_path\gwt-windows-1.3.3\samples\GridDemo\GridDemo-shell.cmd

このサンプル GWT アプリケーションは、商用の JavaScript グリッド・コンポーネントを統合した様子を示しています。このコンポーネントはActiveWidgets 社によって開発されたもので、同社の Web サイトから評価用にダウンロードが提供されています (「参考文献」を参照)。


図 1. サンプル GWT アプリケーションでの高度なグリッド・コントロール
図 1. サンプル GWT アプリケーションでの高度なグリッド・コントロール

このデモ・アプリケーションのアーカイブには、必要なライブラリーがすべて含まれています (GWT を除きます)。私はこのアプリーションを、主なGWT リリースすべて (バージョン 1.3 を含みます) を使ってテストしました。



まとめ

この記事では、レガシーな JavaScript グリッド・コントロールを GWT アプリケーションと統合する方法の一例を紹介しました。同じ方法を、市場で入手できる他の高度なコントロールにも適用することができます。また、商用のJavaScript コントロールに代わるものとして、Yahoo! User Interface Library を調べてみてください (「参考文献」を参照)。このライブラリーはオープン・ソースの JavaScript ユーティリティーとコントロールを集めたもので、DOM スクリプトや DHML、そしてAjax などの手法を使った対話性に富んだ Web アプリケーションを構築する際に活用することができます。



ダウンロード

内容ファイル名サイズダウンロード形式
Sample GWT applicationj-gwtcontrols.zip503KBHTTP

ダウンロード形式について


参考文献

学ぶために

製品や技術を入手するために

  • Google Web ToolkitSDKをダウンロードしてください。

  • ActiveWidgetsから ActiveWidgets JavaScript コンポーネント・ライブラリーの評価版をダウンロードしてください。

  • Yahoo! User Interface Libraryはオープン・ソースの JavaScript ユーティリティーとコントロールです。

議論するために

著者について

Sergey Odobetskiy は Java と Web 技術を専門とするソフトウェア開発コンサルタントです。彼は最近、Rogers Communications でのいくつかのテレコム・プロジェクトに従事してきました。現在は Toronto にある ConceptWave Software Inc. で、テレコミュニケーションによる発注管理製品の業務に取り組んでいます。

不正使用の報告のヘルプ

不正使用の報告

ありがとうございます。 このエントリーは、モデレーターの注目フラグが設定されました。


不正使用の報告のヘルプ

不正使用の報告

不正使用の報告の送信に失敗しました。


developerWorks: サイン・イン


IBM ID が必要ですか?
IBM IDをお忘れですか?


パスワードをお忘れですか?
パスワードの変更

「送信する」をクリックすることにより、お客様は developerWorks のご使用条件に同意したことになります。 利用条件

 


お客様が developerWorks に初めてサインインすると、プロフィールが作成されます。 プロフィールで選択した情報は公開されますが、いつでもその情報を編集できます。 お客様の姓名(非表示設定にしていない限り)とディスプレイ・ネームは、投稿するコンテンツと一緒に表示されます。

表示名をお選びください

developerWorks に初めてサインインするとプロフィールが作成されますので、その際にディスプレイ・ネームを選択する必要があります。ディスプレイ・ネームは、お客様が developerWorks に投稿するコンテンツと一緒に表示されます。

ディスプレイ・ネームは、3文字から31文字の範囲で指定し、かつ developerWorks コミュニティーでユニークである必要があります。また、プライバシー上の理由でお客様の電子メール・アドレスは使用しないでください。

(半角英数字で3文字以上31文字以下にする必要があります)


「送信する」をクリックすることにより、お客様は developerWorks のご使用条件に同意したことになります。 利用条件

 


この記事を評価する

コメント

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=60
Zone=Java technology
ArticleID=250271
ArticleTitle=レガシーなやり方を高度な GWT コントロールに導く
publish-date=04242007
author1-email=s.odobetsky@gmail.com
author1-email-cc=

タグ

Help
このタグで、My developerWorks のすべてのタイプのコンテンツを見つけるために検索フィールドを使用します。

スライダーバーを使用することで、より多く(少なく)タグを表示します。

人気のタグは、この特定のコンテンツ・ゾーン(例えば、Java テクノロジー、Linux や WebSphere など)に対するトップのタグを表示します。

マイ・タグは、この特定のコンテンツ・ゾーン(例えば、Java テクノロジー、Linux や WebSphere など)に対するお客様ご自身のタグを表示します。

このタグで、My developerWorks のすべてのタイプのコンテンツを見つけるために検索フィールドを使用します。人気のタグは、この特定のコンテンツ・ゾーン(例えば、Java テクノロジー、Linux や WebSphere など)に対するトップのタグを表示します。マイ・タグは、この特定のコンテンツ・ゾーン(例えば、Java テクノロジー、Linux や WebSphere など)に対するお客様ご自身のタグを表示します。