データの共有とクラスフィールド
もし複数のマシンやブラウザが用意できるようなら、いくつかのブラウザからアクセスして投稿してみましょう。投稿したデータは全体で共有されており、誰がアクセスしても常に同じ内容のものが表示されます。
Webアプリケーションでは、データを保管するときにリクエストだけでなく、セッションやアプリケーションのスコープに値を保管することで、複数のページやアプリケーション全体で値を共有したりできます。例えば、掲示板のようなものを作るなら、アプリケーションに投稿データを保管することで、どの利用者も1つのデータを共有し使うことができます。
Wicketでもこうしたことは可能ですが、通常のWebアプリケーションとは考え方を変える必要があります。Wicketではアプリケーションの中にいくつものWebPageが用意されますが、これらは利用者がアクセスするごとにインスタンスが用意される形になっています。「すべての両者で共通するデータを保管する」とは「すべてのインスタンスで共有する値を用意する」ということです。つまり「クラスフィールド」として値を保管すればよいのです。ここではIndexPageクラスに、次のような形で投稿データを保管するためのフィールドを用意しています。
private static ArrayList<String> datalist = new ArrayList<String>();
このように、クラスフィールドとしてArrayListを用意しておき、ここに投稿されたデータを保管していきます。これで、このIndexPageクラスで常に1つだけのArrayListが保持されるようになります。
datalistは、IndexPageクラスのクラスフィールドなので、IndexPageのページでのみ利用可能です。同様に、アプリケーションクラスにクラスフィールドを用意しておけばすべてのページでデータを共有できるようになります。
private static String app_msg;
ここではWicSampleクラスにString値のクラスフィールドを用意しておきました。これでどのページからでも利用できます。では実際に、送信されたフォームの内容をこれらのクラスフィールドに保管している処理部分を見てみましょう。submitNowでは、まずそれぞれのコントロールの値をModelから取り出します。
String name = namemodel.getObject(); String cmnt = cmntmodel.getObject();
これで2つのクラスフィールドに保管する値が用意できました。まずはIndexPageクラスのフィールドに値を設定します。
datalist.add(0,cmnt + " (" + name + ")");
cmntmodel.setObject("");
list.modelChanged();
ArrayListの「add」を呼び出して投稿された値を元にテキストを追加し、cmntmodelを空の値に変更します。これで、コメントのテキストエリアが空に戻ります。その後にある「list.modelChanged」は、データの表示を行っているコンポーネントのmodelChangedを呼び出し、Modelが変更されたことを伝えています。これにより、表示が更新されるようになります。
続いて、アプリケーションのクラスフィールドに、最新の投稿情報を設定します。これは、アプリケーションのインスタンスを取得し、フィールドのSetterメソッドを呼び出します。
WicSample app = (WicSample)this.getApplication();
app.setApp_msg(cmnt + " (" + name + ")");
アプリケーションは、WebPageクラスの「getApplication」メソッドで呼び出すことができます。これはアプリケーションクラスで継承しているWebApplicationのスーパークラスであるApplicationというクラスのインスタンスとして返されるので、これをWicSampleにキャストします。そしてsetApp_msgを呼び出してapp_msgクラスフィールドの値を変更します。
このように、getApplicationでアプリケーションのインスタンスを取得することで、WebPageクラス内から自由にアプリケーションクラスのデータを操作できるようになります。
入力値のバリデーション
入力フォームでは、バリデーションのチェックを行っています。ここでは、名前のフィールドは3文字以上、またコメントは100文字以下で入力するように設定しています。また、どちらも必須項目となっています。ためしにどちらかを未入力の状態や指定の文字数範囲を超えるテキストにして送信してみましょう。エラーメッセージが表示され、もう一度送信しなくてはならなくなります。

バリデーションの設定は、整理すると2通りのやり方があります。1つは、コンポーネントに用意されているメソッドを呼び出して設定を行うもの、もう1つはバリデーションのクラスを組み込んで設定するものです。ここでのfield0とarea0のバリデーションの設定処理を見てみましょう。
field0.setRequired(true); field0.add(new StringValidator.MinimumLengthValidator(3)); area0.setRequired(true); area0.add(new StringValidator.MaximumLengthValidator(100));
1つ目の「setRequired」は、コンポーネントに用意されているメソッドで、必須項目とするかどうかを設定するものです。ここで引数にtrueを渡すことで、未入力ではフォーム送信時の処理が実行されないようになります。
またその後にあるaddでは、それぞれ「StringValidator.MinimumLengthValidator」「StringValidator.MaximumLengthValidator」といったクラスのインスタンスを組み込んでいます。これらは、バリデーションを行うためのクラスです。前者は、引数で指定した文字数以上でないと実行されないようにするもので、後者は引数で指定した文字数以内でないと実行されないようにします。
このように、バリデーションのクラスをaddで組み込むことで、そのバリデーションが実行されるようにできます。ここではテキストの文字数に関するバリデーションクラスを使いましたが、Wicketにはこの他にも多数のバリデーションクラスが用意されています。主なバリデーションクラスを以下に整理しておきましょう。
| バリデーションクラス | 説明 |
| CreditCardValidator | クレジットカード番号かどうかをチェックする |
| DateValidator | 日付の値かどうかをチェックする |
| EmailAddressValidator | メールアドレスかどうかをチェックする |
| NumberValidator.RangeValidator | 指定した範囲内の値かどうかをチェックする。引数に最小値、最大値を指定する |
| NumberValidator.MaximumValidator | 引数に指定した値以下かどうかをチェックする |
| NumberValidator.MinimumValidator | 引数に指定した値以上かどうかをチェックする |
| umberValidator.DoubleRangeValidator | RangeValidatorのDouble値版 |
| NumberValidator.DoubleMaximumValidator | MaximumValidatorのDouble値版 |
| NumberValidator.DoubleMinimumValidator | MinimumValidatorのDouble値版 |
| PatternValidator | 引数に指定した正規表現パターンに合致するかどうかをチェックする |
| StringValidator.LengthBetweenValidator | 指定した範囲内の文字数かどうかをチェックする。引数に最小文字数、最大文字数を指定する |
| StringValidator.MaximumLengthValidator | 引数に指定した文字数以下かどうかをチェックする |
| StringValidator.MinimumLengthValidator | 引数に指定した文字数以上かどうかをチェックする |
| UrlValidator | URLの値かどうかをチェックする |
