インターネットアプリケーションの新しいフレームワーク「Guise」はじめに今日のインターネットは、Ajaxや他のテクノロジのおかげで、デスクトップアプリケーション並の多機能アプリケーションを実行できるプラットフォームになりつつあります。それにともない開発者の間では、下層のクライアント/サーバ通信の部分を透過的に処理し、複雑なソフトウェアの開発を支援するエレガントなアーキテクチャ基盤を備えた、総合的なオブジェクト指向フレームワークを求める声が高まっています。 本稿で紹介するGuiseは、透過的なAjaxサポートを備えた完全なオブジェクト指向のインターネットアプリケーションフレームワークです。Guiseが提供する洗練されたアーキテクチャでは、SwingやMFCなどのフレームワークに似た、単純で直接的なJavaプログラミングが可能です。 新しいインターネットアプリケーションまず1980年代に、SmalltalkやC++などのオブジェクト指向のプログラミング言語が登場しました。これらは、その当時に出現し始めた最初のGUIをサポートしていました。 1990年代になると、多くのツールベンダが複雑なオブジェクト指向のフレームワークを作成しました。開発者はより簡単にGUIアプリケーションを作成できるようになり、下層の非オブジェクト指向のGUI用APIを使用しないで済むようになりました。BorlandのTurbo C++には、テキストモードだけでGUI風のインターフェイスを作成できる複雑なオブジェクトセットが含まれていました。Borlandはその後、Windows用の完全なオブジェクト指向フレームワークであるObject Windows Library(OWL)をリリースしましたが、MicrosoftのMicrosoft Foundation Classes(MFC)という類似の競合フレームワークの普及に伴い、OWLは最終的に消えてしまいました。 Javaがインターネット関連の言語として人気を集めるようになると、SunはSwingという複合的なオブジェクト指向GUIフレームワークをリリースしました。その一方で、Microsoftは、Windows Formsというまた別のフレームワークをリリースしました。これは.NETプラットフォーム上で主にMicrosoftの新しいC#言語で使用されるフレームワークであり、その設計は、BorlandのDelphiおよびその洗練されたVisual Component Library(VCL)フレームワークの設計者の手によります。 21世紀が幕を開けると、新しいプラットフォームの選択肢として、主にHTML(HyperText Markup Language)によって実現されるインターネットが加わりました。インターネットの概念は画期的でしたが、急速に普及した理由はHTMLの簡単さ、つまり誰でも単純なテキストエディタでWebページを作成してリンクできるという点にありました。しかしHTMLの簡単さと、各ブラウザの標準実装レベルのばらつき、さらにブラウザ間の相互運用性の低さがあいまって、当時の複雑なWeb機能はどれも、10年前に一般的だった標準GUIからはほど遠い状況でした。言うまでもなく、当時存在していた多数のGUIフレームワークは、静的なテキストページに対しては現実的に意味がありませんでした。 Web上で動的な対話を実現しようという試みは、まずテンプレートを通じて行われ、次にスクリプトを通じて行われました。SunのJavaServer Pages(JSP)およびMicrosoftのActive Server Pages(ASP)では、HTMLページ内にシンボルを挿入し、そのページをサーバがコンテンツに変換していました。Sunは、「サーブレット」という概念を導入しました。これはWeb上に配置される小さなプログラムで、何もない状態からHTMLページ全体を生成する働きをします。JSP処理エンジンそのものが、JSPテンプレートを解析および操作する目的で設計されたサーブレットでした。しかし、このような試みも(サーブレットといくつかのJSPをMVCモデルで動作させるパターンを含む)、依然として、過去の多機能なGUIフレームワークより劣っていました。 しかし、Javaを使ったHTMLプログラミングは進化を続けました。まずStrutsオープンソースフレームワーク、さらに続いてSunのJavaServer Faces(JSF)が、よりコンポーネントベースのユーザーインターフェイスアーキテクチャの作成を試みました。ですが、これらのコンポーネントも本質的には、サーブレットとJSPのテンプレート/スクリプトフレームワークの延長にすぎませんでした。 コンポーネント間のリアルタイムのやり取りには、複雑な設定と、JSFの「バッキングBean」のような特別な インターネットアプリケーションでは、デスクトップアプリケーションとして実装するよりも大規模で複雑な機能を実現でき、分散処理やマルチユーザーにも対応できます。総合的なオブジェクト指向のインターネットアプリケーションフレームワークが必要であることは、もはや明白です。本稿で紹介するGuiseフレームワークこそ、このニーズを満たすものです。 Guiseフレームワークの概要Guiseは、Ajaxによる透過的なWebレンダリングをサポートするインターネットアプリケーションフレームワークです。「Guise」という名前は「Graphical User Interface, Simple and Elegant」の頭辞語だとされていますが、もともとの開発の動機であった「JavaServer Facesに代わるもの」という意味も込められていると思います。GuiseはAjaxツールキットを大きく超えるものであり、信頼性、安全性、および機能性に優れたインターネットアプリケーションを実現するという目的のために一から構築された完全なフレームワークです。 Guiseの作成に当たっては、SwingとJSFに加えて、他のGUIフレームワークのホストが大いに参考にされました。その結果、GuiseはプレーンなJavaで動作する強力なフレームワークとなっています。Guiseは次のような特徴により、インターネットアプリケーションを開発するためのユニークで強力な基盤と考えられています。
Guiseは、単なるツールキットやライブラリではなく、真のフレームワークであり、アプリケーション構造全体を導くコンテキストを提供します。
Guiseは、本当の意味でのインターネットアプリケーション、つまり単なる連続するWebページではなく、デスクトップアプリケーションと同様の方法でユーザーとやり取りするインターネットアプリケーションを作成します。
Guiseで作成されたアプリケーションは、デスクトッププログラムと同様に動作する多機能なユーザーインターフェイスを備えていますが、その機能をプログラマが明示的に実装する必要はありません。Guiseアプリケーションを作成する開発者は、HTMLやJavaScriptを1行たりとも記述する必要はありません。Guiseは、IE 6、IE7、Firefox 1.x、Firefox 2.x、Safari 1.3.xなど、一般的な多くのブラウザをサポートしています。
Guiseアプリケーションは、標準の単純なJava構造を使用します。特別なマーシャリングクラスや「バッキングBean」を作成する必要はありません。通常どおりにGuiseクラス(または独自のカスタムクラス)のインスタンスを作成し、標準のイベントリスナを登録してイベントを待機します。
Guiseフレームワークは、その構造を一から見直し、Java Swing、OWL、MFCなどのフレームワークの長所を取り入れ、さらに改善することで、洗練された一貫性のあるオブジェクト指向のプラットフォームを実現しています。Guiseクラスは、ジェネリックや「タイプセーフなenum」など、最新のJava言語機能を使用します。Guiseは、実際のレンダリング言語(ブラウザのXHTMLなど)を抽象化したものであり、アプリケーションのコードをほとんど(あるいはまったく)変更することなく、別のレンダリングプラットフォーム(Java Swingなど)を後から追加できます。
Guiseは、標準準拠であることを目指しています。生成されたマークアップはXHTML準拠です。構成ファイルは、XML形式でシリアル化されるRDFを使用します。Guiseは国際化に完全に対応しており、ローカライズされたアプリケーションコンテンツを簡単に提供できる機能が用意されています。
Guiseの働きを見てみるには、米カリフォルニアのBlueCross社のBeneFits Insurance for Small Businessというサイトを参照するのが最も簡単です。このサイトは、完全にGuiseで動作しています。カリフォルニアの郵便番号94111などを使って「Quick Quote」(即時見積もり)の機能を試し、フライオーバー、迅速な検証、ポップアップカレンダー、さらに保険料をリアルタイムで更新するスライダの機能を確認してみてください。トップページのいくつかのFlashコンポーネントにも、Flash埋め込み用の既存のGuiseコンポーネントが使われています。 Guiseはhttp://www.guiseframework.com/で入手できます。一般的なGuiseライセンスはまだ公表されておらず、ライセンスはケースバイケースで決定されますが、Guiseのすべての機能を備えた開発バージョンは無料で提供されます。Guise Webプラットフォームは標準のJ2EEサーブレットに基づいており、Java 5.0以降が必要です。 重要
JDK 1.5.0_11の時点では、Sun Javaコンパイラのバグが原因でGuiseと連携できません。最新のEclipse 3.2.xコンパイラを使用してアプリケーションをコンパイルする必要があります。
Guiseで「Hello World!」チュートリアルのお約束に従い、画面に「Hello World!」というテキストを表示するGuiseアプリケーションを作成してみます。 package com.example; import com.guiseframework.component.*; import com.guiseframework.component.layout.RegionLayout; public class HelloWorldPanel extends LayoutPanel { public HelloWorldPanel() { super(new RegionLayout()); setLabel("Guiseu2122 Demonstration: Hello World"); final Heading helloWorldHeading = new Heading(0); helloWorldHeading.setLabel("Hello World!"); add(helloWorldHeading); } } 技術的には、ここで新しいGuiseアプリケーション型を作成する必要はありません。既定のGuiseアプリケーション型を使用し、カスタマイズされたパネルを提供して、Guiseアプリケーションフレームに配置します。このアプリケーションのメインパネルの主要なセクションを見ていきましょう。
標準のGuiseパネルクラス
LayoutPanelを拡張して、パネルを作成します。
パネルを作成します。このときに子コンポーネントのレイアウト方法を指定します。この例では、RegionLayoutクラスを使用することで、パネルをいくつかの領域に分割するよう指定しています。
各コンポーネントにはラベルを指定できます。ラベルの用途は状況に応じて異なります。ここでは、このメインパネルのラベルはブラウザ内のページのタイトルとして使用されます。
新しいコンポーネントHeadingを作成します。ここではトップレベルヘッダ(レベル0)の使用を指定しています。このコンポーネントは、ブラウザの中で
<h1> XHTML要素としてレンダリングされます。
ヘッダのラベルを設定します。ヘッダコンポーネントのラベルには、ブラウザに表示するタイトルではなく、ヘッダコンテンツとして表示するテキストを指定します。
パネルにヘッダを追加します。特に指定しない限り、RegionLayoutはパネルの中心にヘッダを配置します。
「Hello World」というタイトルを含むパネルを表示するJavaソースコードはこれですべてですが、このアプリケーションをブラウザで実際に試すには、もちろん、いくつかの操作を行う必要があります。まずGuiseのインストール方法を確認してから、このHello Worldアプリケーションの構成方法を見ていくことにしましょう。 GuiseのインストールGuiseをインストールする前に、以下の環境が用意されていることを確認します。
重要:JDK 1.5.0_11の時点では、Sun Javaコンパイラのバグが原因でGuiseと連携できません。最新のEclipse 3.2.xコンパイラを使用してアプリケーションをコンパイルする必要があります。
また、この説明では、WebアプリケーションをホストするJavaサーブレットコンテナが「/server/webapp/」に格納され、Webアプリケーション定義ファイルが「/server/webapp/WEB-INF/web.xml」に格納されることを前提としています。Guiseアプリケーションを「/webapp/example/」にマップすることも前提です。
アプリケーション記述ドキュメントの設定Guiseをインストールしたら、Hello Worldアプリケーションの設定に戻ります。「Hello World」ページをユーザーにどのようにして閲覧させるかをGuiseに指示するには、Guiseアプリケーション記述ドキュメントを作成する必要があります。このドキュメントでは、最低限、アプリケーションの「ナビゲーションパス」とコンポーネントのマッピングを指定します。 Guiseアプリケーション記述ドキュメントでは、XML形式でシリアル化されるRDFオントロジの一種であるPLOOPを使用します。Guiseアプリケーション記述ドキュメントについては後で詳しく説明することにして、まず今回のサンプルアプリケーションに必要なアプリケーション記述ドキュメントを紹介しておきます。このコードは「/server/webapp/WEB-INF/example-application.rdf」ファイル内に記述されます(web.xmlと同じ場所です)。 <rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:property="http://ploop.org/namespaces/property#" xmlns:guise="java:com.guiseframework." > <guise:DefaultGuiseApplication> <property:destinations rdf:parseType="Collection"> <guise:ComponentDestination> <property:path>helloworld</property:path> <property:componentClass> com.example.HelloWorldPanel </property:componentClass> </guise:ComponentDestination> </property:destinations> </guise:DefaultGuiseApplication> </rdf:RDF> アプリケーション記述ドキュメントの中心部分では、 web.xmlの構成 最後に、サーブレット「/server/webapp/WEB-INF/web.xml」ファイルで、Guiseを構成し、アプリケーション記述ドキュメントを参照する必要があります。最初に、先頭の <listener> <description> The class that manages Guise sessions in an HTTP servlet environment. </description> <listener-class> com.guiseframework.platform.web.HTTPGuiseSessionManager </listener-class> </listener> 次に、 <servlet> <description>Example Application</description> <servlet-name>exampleApplication</servlet-name> <servlet-class> com.guiseframework.platform.web.GuiseHTTPServlet </servlet-class> <init-param> <param-name>application</param-name> <param-value>example-application.rdf</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>exampleApplication</servlet-name> <url-pattern>/example/*</url-pattern> </servlet-mapping> J2EEコンテナを起動すると、要求を受け取るGuiseアプリケーションが「http://localhost/webapp/example/」に作成されます。これで、「http://localhost/webapp/example/helloworld」のHello Worldサンプルにアクセスできるようになります。 「Hello User!」サンプル静的なコンテンツについて理解できたところで、次は、イベントに応答し、Webページのコンテンツを更新することがいかに簡単であるかを見ていきましょう。Guiseは背後でAjaxを自動的に使用しているため、サーバとの通信はバックグラウンドで発生し、ページの再ロードを引き起こすことなく、Webページへの変更が動的に行われます。では、Hello Worldパネルを少し変更して、Hello Userパネルを作成してみましょう。 package com.example; import com.guiseframework.component.*; import com.guiseframework.component.layout.*; import com.guiseframework.event.*; import com.guiseframework.validator.RegularExpressionStringValidator; public class HelloUserPanel extends LayoutPanel { public HelloUserPanel() { super(new FlowLayout(Flow.PAGE)); setLabel("Guiseu2122 Demonstration: Hello User"); final Label greetingLabel = new Label(); greetingLabel.setVisible(false); add(greetingLabel); final TextControl<String> userInput = new TextControl<String>(String.class); userInput.setLabel("What’s your name?"); userInput.setInfo("Enter a name that does not start with whitespace."); userInput.setValidator(new RegularExpressionStringValidator ("S+.*", true)); add(userInput); final Button greetButton = new Button(); greetButton.setLabel("Greet"); greetButton.addActionListener(new ActionListener() { public void actionPerformed(final ActionEvent actionEvent) { if(HelloUserPanel.this.validate()) { final String user = userInput.getValue(); greetingLabel.setLabel("Hello, "+user+"!"); greetingLabel.setVisible(true); } } }); add(greetButton); } } ご存知のように、ボタンの押下などのイベントを検出するには、関連するコントロールにイベントリスナをインストールする必要があります。イベントリストに加えて、このパネルには、Hello Worldサンプルと異なる点がいくつかあります。
このパネルを領域に基づいてレイアウトする代わりに、FlowLayoutを使用して、追加されたすべてのコンポーネントをページに沿って垂直に配置します。垂直に配置するにはFlow.PAGEを指定します(ほとんどのロケールでは、行の進行方向は水平で、ページの進行方向は垂直です)。
ユーザー名がわからないので、最初はグリーティングラベルを非表示にします。
TextControlは、テキスト入力を受け取るコンポーネントです。他のValueControlと同様、ユーザーが入力する値が格納されます。テキストコントロールは、ジェネリックを使用して、格納する値のデータ型を指定します(このケースでは
String)。これは、ユーザーがテキストを入力しても、コントロールに格納される実際の値は、例えばBooleanの可能性もあり(trueとfalseのテキストで表現されます)、テキストとは限らないためです。
多くのコンポーネントでは、コンポーネントラベルのように、状況に応じて異なる用途に使われる独立した情報を指定できます。多くの場合、コンポーネントの情報は、マウスポインタをコンポーネントの上に置いたときに表示されるツールヒントに表示されます。
アプリケーションでは、通常、ユーザーが入力する値を制限する必要があります。Guiseのすべての値コントロールでは、コーディングで値をチェックするのではなく、Validatorによる宣言的な制限を行います。Validatorは正しい値が入力されたことを自動的に確認し、値が不正な場合はエラーを表示します。この特殊なバリデータは、文字列を正規表現
S+.*(空白以外の文字と、それに続くゼロ個以上の文字)で制限します。
ボタンなどのアクションコントロールはActionEventを生成します。このイベントを検出するには、コントロールにActionListenerを追加します。この例では、ボタンが押されるとActionListener.actionPerformed(com.guiseframework.event.ActionEvent)メソッドが呼び出され、必要に応じて応答アクションが実行されます。
すべてのコンポーネントは、自身を検証する機能を備えています。ネストされたコンポーネントを持つコンポーネントは、子を検証することもできます。パネル全体を検証すると、すべてのコントロールが自身を検証します。TextControlは、自身にValidatorが追加されている場合はそれを使用します(通常は、値が変更されたときにバリデータが既に起動されています)。このメソッドがtrueを返す場合は、すべてのコンポーネントは正しい値を格納しています。
すべてのValueControlの値はgetValue()メソッドを通じて取得できます。コントロールはJavaジェネリックの使用を通じて正しいデータ型を既に返しているので、ここで返される値をキャストする必要はありません。この値はラベル内のユーザー名を更新するために使用され、ラベルがまだ表示されていない場合は、これを表示します。
Guiseの優れた機能駆け足の説明でしたが、Guiseの使用について、感じはつかめたことでしょう。今後の記事では、高級なアーキテクチャの概念から強力な対話機能に至るまで、Guiseフレームワークのさまざまな要因を、じっくりと、包括的に扱う予定です。さらに興味を持っていただくために、以降では、高度でありながら簡単に使用できるGuiseの機能をいくつか紹介します。 正規表現のマップ先 Guiseのマップ先は正規表現で指定できます。例えば、パネルを WebTrends準拠の自動ログ Guiseアプリケーションディスクリプションに ユーザーの変更GuiseSession.setPrincipal(java.security.Principal)の呼び出しを通じて現在の「プリンシパル」を変更することによって、ユーザーログインおよびログアウトを実行できます。 ロケールの変更別の言語への変更は簡単です。GuiseSession.setLocale(java.util.Locale)を呼び出すだけで現在のセッションのコントロールが再設定され、必要に応じて新しいテキストや他のリソースが読み込まれます。 コンテナはコレクション Guiseの個々のContainerはJavaの コントロールのプロトタイプGuiseには特別な「プロトタイプ」が用意されており、属性と機能を共有する各種のコンポーネントを、簡単かつ統一された方法で作成できます。例えば、1つの「ファイルの保存」プロトタイプを作成すると、プロトタイプの正しい(国際化された)ラベルとアイコンを自動的に継承するボタンとメニュー項目を簡単に作成できます。これらは、選択されるとプロトタイプのアクションを実行し、プロトタイプが適切だと判断すると、無効または有効になります。 高度なセマンティクスGuiseでは、単に機能を記述するだけでなく、情報セマンティクスを定義できます。GuiseComponent.setInfo(java.lang.String)を使用して情報をコンポーネントに割り当てると、既定でツールヒントが表示されます。GuiseComponent.setDescription(java.lang.String)を使用して説明を設定すると、GuiseComponent.setFlyoverEnabled(boolean)でフライオーバもオンになっている場合は、フライオーバ表示になります。 ブックマーク ブックマークを簡単に設定できます。ユーザーがページに初めてアクセスしたときにコンポーネントに特別な処理を行わせるには、NavigationListenerインターフェイスを実装します。 まとめGuiseは新しいインターネットアプリケーションフレームワークですが、急速に成長しており、複雑な現実のアプリケーションで評価を得ています。Guiseは標準のJavaを通じてアクセスできる強力で洗練されたオブジェクト指向のユーザーインターフェイスパラダイムであり、Guiseを使用する開発者は、Ajaxなどの下位レベルの基本テクノロジを意識せずに済みます。 GuiseはXHTMLやJavaScriptを記述することなくインターネットアプリケーションを作成できる総合的な標準ベースのフレームワークであり、新しいインターネットアプリケーションのSwingおよびMFCとなることが期待されています。 著者紹介Garret Wilson(Garret Wilson)
|