レベルエンター山本大のブログ

面白いプログラミング教育を若い人たちに

BLOCKVROCKリファレンス目次はこちら

Wicketで理解する プレゼンテーション層フレームワーク革命

※ @ITさんでボツになった記事です。。。

Javaを使った国内の企業システム開発では、Webプレゼンテーション層のアーキテクチャとして最もよく使われているのは、いまだにStrutsだそうです。しかし、Sturtsはもはや時代に合わないフレームワークだと感じているエンジニアも多いのではないでしょうか。かといって、JSFStrutsの後継フレームワークが標準を勝ち取っていくことには「複雑さ」や「完成度の未熟さ」などの理由から疑問の声も聞かれます。とはいえフレームワークに利便性があることも事実なので、誰もJSPServletだけの時代に戻ることは望んではいません。そういったことから、筆者も新しい時代のWebプレゼンテーション層フレームワークを待ち望んでいました。
 今回紹介するWicketが、JavaEE開発のWebプレゼンテーション層に革命を巻き起こすことを期待しています。

1. WicketXMLレス・SwingライクなWebプログラミング

WicketJavaで作られたWebプレゼンテーション層(ユーザーインターフェイス)のためのフレームワークです。Wicketの代表的な特徴は以下の3つです。

No 特徴 備考
1. Javaオブジェクト指向の特性を活かしたプログラミングスタイル Swingに似たオブジェクト指向コンポーネントを利用
2. ピュアJavaとピュアHTMLを使ったシンプルな構造 JSPのような特殊な構文のファイルは不要
3. 実行のための設定はweb.xmlへの少しの簡単な記述のみ 特別な設定のためのXMLは不要

表 1:Wicketの代表的な特徴

この他にもたくさんの特徴や機能がありますが、それは後ほど説明することにして、実際にWicketのプログラミングを体験することにしましょう。まず簡単にWicketアーキテクチャの特徴から説明していきます。

1.1. Wicketの構造と概念

現在のWebプレゼンテーション層フレームワークの主流は、Servlet やSturtsなどのように、1回の「ページ遷移」に対して1つのクラスを用いるアーキテクチャです。それに対してWicketでは、1つのWebページに対して1つのJavaクラスを作成します。
ServletStrutsが、現在のようなアーキテクチャになった理由は、Httpというプロトコルのリクエスト・レスポンスをオブジェクトとしてモデル化したからです。しかし、リクエスト・レスポンスは1回の通信であるため、このアーキテクチャではイベントドリブンモデルのプログラミングスタイルになってしまいます。そのため、オブジェクト指向の実装や設計のメリットを活かせませんでした。それに対して、オブジェクト指向流のやり方でWebアプリケーションをモデル化したのがWicketアーキテクチャの特徴であるといえます。


図 1:ServletStrutsのオブジェクト設計とWicketのオブジェクト設計の違い

Wicketのように「1つの具体的なWebページ」に対応する「WebPageクラス」というモデルとすることは、オブジェクト指向では素直な考え方です。また、このWicketが提供するアーキテクチャを使うことで、開発者はリクエスト・レスポンスといった「HTTPのやり取り」を意識せずにプログラミングができます。
では、実際にWicketアーキテクチャを体験するためにサンプルアプリケーションを作成してみましょう。

2. Wicketのダウンロードと開発環境の設定

まずはWicketが提供するライブラリをダウンロードする必要があります。Wicketは、以下のサイトからダウンロードできます。

http://wicket.sourceforge.net/

原稿執筆時点ではWicketのバージョンは1.2.4ですので、「wicket-1.2.4.jar」をダウンロードしてください。


図 2:Wicketダウンロードサイト

「図 2:Wicketダウンロードサイト」の左側のナビゲーションからダウンロードのリンク (?)をクリックし、開いたページの表中のAPIダウンロードリンク(?)からWicketをダウンロードします。ダウンロードした「wicket-1.2.4.jar」は、作成するアプリケーションの「WEB-INF/lib」ディレクトリに配置してください。

この連載ではTomcat 5.5およびEclipse 3.2を使用します。次のセクションでは、EclipseTomcatを使ったWebアプリケーションの開発環境の設定を記載します。ただし、Wicketを使ったプログラミングは開発環境の設定には依存しません。サーブレットによるWebアプリケーションを作成したことがある読者は、このセクションを読み飛ばして「3. HelloWorldの作成」から読み進めてください。

2.1. 開発環境の設定

以下の解説では、下記の表(表 1)に従ってEclipseTomcatのインストールを行っていることとします。

準備の対象 インストールディレクト
Eclipseのworkspace C:\workspace
%TOMCAT_HOME% C:\Tomcat 5.5

表 2:開発環境インストールディレクトリ一覧

では、EclipseJavaプロジェクト「wicket」を作成します。Wicketプロジェクトの配下のディレクトリには「WEB-INF」、「WEB-INF/classes」、「WEB-INF/lib」、「WEB-INF/src」を作成し、Webアプリケーションのためのディレクトリ構成にしておきます。

wicket			
└─WEB-INF		
    ├─classes		
    ├─lib		
    └─src		


「WEB-INF/src」ディレクトリをソースフォルダに設定し、出力ディレクトリを「WEB-INF/classes」にセットしておけば、Eclipseによってコンパイルされたクラスファイルが「WEB-INF/classes」に出力されるようになります。また先ほどダウンロードした「wicket-1.2.4.jar」を「WEB-INF/lib」に配置し、Eclipseのビルドパスにも追加しておいてください。
ここまでできたら、次はこのEclipseプロジェクトのディレクトリをTomcatの「Webアプリケーションコンテキスト」として機能するように設定します。「%TOMCAT_HOME%\conf\Catalina\localhost」に以下(リスト 1)の「wicket.xml」ファイルを作成して配置してください。

<Context path="/wicket" reloadable="true" docBase="C:\workspace\wicket" />

リスト 1:コンテキストファイル(wicket.xml

以上で開発環境の設定は完了です。Tomcatを起動すれば「http://localhost:8080/wicket」のURLでサンプルアプリケーションにアクセスできるようになりました。上記の設定の他、WTPTomcatプラグインを利用してWebアプリケーションプロジェクトを利用することもできます。

3. HelloWorldの作成

では、「Hello World」というメッセージを表示するサンプルアプリケーションを作成しましょう。このHello Worldアプリケーションで作成する必要があるファイルを以下の表(表 2)にまとめました。

ファイル名 説明
web.xml J2EEWebアプリケーション標準の設定ファイル。サーブレットとしてHelloWorldApplicationを起動するためにservlet要素とservlet-mapping要素の記述のみを追加する。
HelloWorldApplication.java このアプリケーションの設定および起動のためのクラス。
HelloWorld.java ページを表すクラス。ラベルコンポーネントをひとつ持つ。
HelloWorld.html ページのレイアウトを決めるHTMLマークアップ

表 3:HelloWorldサンプルで作成するファイル

今回のサンプルの構造は以下の図(図 3)のようになります。


図 3:Wicketの基本構造


では、「HelloWorld」と表示するためのHTMLページを作成します。以下(リスト 2)のようにHelloWorld.htmlファイルを作成してください。

<html>
<body>
  <span wicket:id="message">この部分の文字はWicketによって置き換えられます。</span>
</body>
</html>

リスト 2:HelloWorld.html

spanタグの属性であるwicket:id属性に注目してください。wicket:id属性の機能は後ほど説明しますが、この属性はブラウザで表示した際には無視されます。そのため、このHTMLファイルは一般的なHTMLエディターで作成・編集することができます。
では、次に以下のJavaクラスファイル(リスト 3)を作成します。このファイルはHelloWorld.htmlページの振る舞いや配置するコンポーネントを定義するクラスです。

package net.kronos_jp.wicket.helloworld;

import wicket.markup.html.WebPage;
import wicket.markup.html.basic.Label;

public class HelloWorld extends WebPage
{
public HelloWorld()
    {
        this.add(new Label("message", "Hello World!"));
    }
}

リスト 3:HelloWorld.java

Wicketでは、1つのWebページに対して1つのJavaクラスを作成します。このWebページを表すクラスは「wicket.markup.html.WebPage」クラスを継承して作成します。
コンストラクタ内では「message」と言う名前のLabelコンポーネントを作成しています。このLabelコンポーネントには”Hello World!”という文字列を設定して作成しています。そして、生成したLabelコンポーネントインスタンスをadd()メソッドで、このページオブジェクトに追加しています。
次に作成するのはアプリケーション全体を表すHelloWorldApplicationクラスです。

package net.kronos_jp.wicket.helloworld;
import wicket.protocol.http.WebApplication;

public class HelloWorldApplication extends WebApplication
{
    public HelloWorldApplication()
    {
    }
    public Class getHomePage() 
    {
        return HelloWorld.class;
    }
}

リスト 4:HelloWorldApplication.java

このクラスは「wicket.protocol.http.WebApplication」クラスを継承して作成します。getHomePage()メソッドでは、アプリケーションを起動した際に初期表示されるページであるWebPageサブクラスを返却するように設定します。このサンプルではHelloWorld.classを設定します。以上のファイルを作成したら、すべてのファイルを同じディレクトリに保存してください。
Eclipseで保存する場合は以下のようになります。


図 4:アプリケーションのフォルダ構成(Eclipse

HTMLファイルも、クラスファイルと同じ場所に配置します。つまり、WEB-INF/classes以下のパッケージ階層に合わせたディレクトリに配置します。(※ ここでは説明しませんが、別のディレクトリに置いたHTMLを利用する方法もあります。)
 次にweb.xmlファイルで、HelloWorldApplicationクラスをサーブレットから呼び出すように設定します。

<?xml version="1.0" encoding="SHIFT_JIS"?>
<web-app version="2.4">
    <servlet>
        <servlet-name>helloworld</servlet-name>
        <servlet-class>wicket.protocol.http.WicketServlet</servlet-class>
        <init-param>
            <param-name>applicationClassName</param-name>
            <param-value>
            net.kronos_jp.wicket.helloworld.HelloWorldApplication
            </param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>

    <servlet-mapping>
        <servlet-name>helloworld</servlet-name>
        <url-pattern>/hello/*</url-pattern>
    </servlet-mapping>
</web-app>

リスト 5:web.xml


このweb.xmlファイルには、WicketServletというサーブレットを登録します。このサーブレットの初期化パラメータに、パラメータ名「applicationClassName」として「HelloWorldApplicationクラスの完全修飾名」を記述します。
また、このサーブレットのURLマッピングは「/hello/*」となっています。この理由はCSSやJS、画像ファイルなどの静的コンテンツを「Wicketアプリケーションとして動作する対象」から除外するためです。
ここまでできたら完成です。Tomcatを再起動し、以下のURLをブラウザのアドレスに入力して、アプリケーションを動作させてみてください。

http://localhost:8080/wicket/hello

リスト 6:HelloWorldアプリケーション実行パス

以下のような画面が表示されたら成功です。


図 5:HelloWorldアプリケーションの実行イメージ

3.1. HTMLマークアップJavaコードのみのアーキテクチャ

上記のHelloWorldサンプルアプリケーションでみてきたように、Wicketでは画面の作成には主にHTMLマークアップJavaコードのみを使います。それぞれの役割をまとめると以下のようになります。

コンポーネントJavaからHTMLに配置するときに、HTMLマークアップではコンポーネントを識別するためのwicket:idを用います。HTML要素の属性としてwicket:id属性を設定しておくと、レンダリング(描画・出力)時に、Wicketwicket:id属性の部分をJavaコードで定義したコンポーネントに置き換えて出力します。
 

図 6:HelloWorldクラスの動き

4. Wicketアーキテクチャのメリット

Wicketアーキテクチャでは、特殊なルールのXMLJSPを必要としないため、以下のようなメリットがあります。

  • 開発者は直感的にプログラミング・デバッグができる。
  • EclipseなどのIDEが持つ強力なリファクタリング機能を効果的に利用することができる。
  • WTPTomcat Pluginが持つデバッグ・ステップ実行機能を効果的に利用することができる。
  • 開発者にとってわかりやすいエラーメッセージが表示されるので容易にデバッグができる。
  • 容易に問題点の切り分けができる。
  • ピュアHTMLなので、容易にWebページデザイナーとの共同作業ができる。
  • 一般的なHTMLデザインツールを使って画面デザインの開発ができる。

Wicketを使ったプログラミングでは過去のフレームワークを使ったプログラミングと比較して、Javaのコード量は増加するかもしれませんが、上記のようなメリットによってコード量の増加分と比較してもメリットがあるほど開発効率が向上します。

4.1. Wicketのその他の特徴や機能

今回紹介した以外にも、表(表 3)に表すような「特徴」や「機能」があります。また、これらの機能を試してみたり実装の参考にしたりするための、わかりやすいサンプルコードが数多く提供されています。(サンプル:http://wicket.sourceforge.net/Examples.html


機能 説明
透過的でスケーラブルなクラスタリングのサポート すべてのWicketのアプリケーションは、追加の作業なしでそのままクラスタリング環境でも動作します。
透過的な「戻る」ボタンのサポート Wicketは設定可能な「ページ状態のパージョン管理」をサポートしています。ユーザーがフォーム情報をサブミットしたり、リンクによってページを遷移したりした後で、ブラウザの戻るボタンを押すと、Wicketはページオブジェクトの状態を、ページが初めに表示された時の状態に戻せるようにしています。これによって、Webアプリケーションの戻るボタンを簡単に作ることができます。
再利用可能なコンポーネント Wicketでは再利用可能なコンポーネントを、非常に簡単に作ることができます。たとえば、既存のコンポーネントJavaの「extend」キーワードによって拡張することができます。それだけでなく、再利用可能なユニットとして、複数のコンポーネントを関連づけた「パネルコンポーネント」を作ることもできます。
タイプセーフなセッション Wicketでは、HttpSessionの属性を手動で管理する必要がありません。ページとコンポーネントオブジェクトは、透過的にセッションに保存されます。また、タイプセーフなプロパティーをもった、セッションのカスタムサブクラスを作ることもできます。セッションに保存されたすべてのオブジェクトは、自動的にクラスタリングレプリケーションに参加させることができます。
動的イメージ Wicketでは、画像イメージを使ったり共有したり生成したりするのがとても簡単です。動的なイメージは、ペイントメソッドを使って簡単に作ることができます。
ページ遷移が可能なリストビュー Wicketのリストビューは、とてもパワフルです。リストビューの行にはどんな種類のコンポーネントでもネストすることができます。他のリストビューでさえネストできます。数の多いリストのためのページング可能なリストビューは、ナビゲーションリンクをサポートしています。
Ajax対応のコンポーネント Wicketは、Ajaxに対応したコンポーネントが提供しています。開発者はこれらのコンポーネントを使って、JavaScriptを記述せずに、Ajaxによる非同期通信や、ツリービュー、リストビューを利用することができます。

表 4:Wicket Features(http://wicket.sourceforge.net/Features.html

5. まとめ

Wicketは、今までのWebアプリケーションの構築方法を根底から変えるWebプレゼンテーションフレームワークです。Wicketは、オブジェクト指向のメリットを活かせるアーキテクチャであり、ピュアJavaとピュアHTMLのみを使ったシンプルな構造です。特殊なルールのXMLJSPを必要としないため、開発者は直感的なプログラミング・デバッグを行うことができます。また、Webページデザイナーとの共同作業やHTMLデザインツールの利用が容易です。
今回は、HelloWorldアプリケーションを作成することでWicketのプログラミングスタイルに簡単に触れてみました。次回は、実際の開発でよく使う「画面の基本的な要素」をWicketで作成するサンプルを紹介します。(・・・できれば、、、)