Wicketで始めるオブジェクト指向ウェブ開発

第4回 WicketでTwitterアプリケーションを作る(後編)

この記事を読むのに必要な時間:およそ 4.5 分

ログイン処理を実装する

AppSessionにlogin()メソッドを定義しましたので,ユーザがログインボタンを押した時の処理は,AppSessionのlogin()メソッドを呼び出すだけになりました。ここまでできれば簡単です。

リスト3 Twitterにログインする

Button submit = new Button("login") {
  private static final long serialVersionUID = 1L;
  @Override
  public void onSubmit() {
    AppSession session = AppSession.get();
    if(session.login(userName, password)) {
      setResponsePage(MyTimeline.class);
    } else {
      error(getString("unauthorized") + ": " + session.getLastUnauthorizedMessage());
    }
  }
};

先ほど登場した,<input type="submit">タグに適用するButtonコンポーネントの実装です。このButtonコンポーネントでは,onSubmit()メソッドをオーバーライドし,ボタンがクリックされるとログインを行います。

セッションオブジェクトの取得

ログインするにはAppSessionを取得しなければいけません。Wicketでは,Session.get()を呼び出すことでいつでもSessionオブジェクトを取り出すことができます。Session.get()を呼び出した時にセッションがまだ未作成であれば,先ほど定義した,WebApplicationのnewSession()メソッドが呼び出されます。つまり,Session.get()の戻り値はnewSession()メソッドの戻り値と同じです。通常であれば,次のように,AppSessionにキャストして使用します。

リスト4 Sessionオブジェクトの取得

AppSession session = (AppSession)Session.get();

しかし,使うたびにキャストを行うのも面倒です。今回のサンプルプログラムでは,AppSessionにget()というstaticメソッドを定義し,キャストした結果のオブジェクトを返すようにしました。これでいつでも「AppSession.get()」を呼ぶことで,AppSessionオブジェクトにアクセスすることができます。

ログイン処理を行う

セッションオブジェクトを準備できれば,あとはlogin()メソッドを呼ぶだけです。login()メソッドの引数はユーザ名とパスワードですが,それらはPropertyModelを介してページのフィールド「userName」「password」に格納されています。ユーザ名とパスワードの入力を制御するコンポーネントにはsetRequired(true)とセットされていましたので,もし未入力であれば入力検証段階ではじかれ,モデルに入力値は渡りません。onSubmit()が呼び出されたということは,ユーザ名とパスワードは必ず入力されていて,フィールドにその値が入っていることが保証されています。そのため,プログラムでは,いきなりフィールドを使用しているのです。

login()メソッドはログイン成功すればtrueを返しますし,失敗すればfalseを返します。よって,単純なif文で成功時,失敗時の処理を分岐できます。

成功したときには,Twitterタイムライン表示ページへと遷移します(そのページはまだ作っていませんが,MyTimelineというクラスです⁠⁠。

Wicketでのページ遷移は,これもまたプログラムから行います。プログラム中でsetResponsePage()メソッドを呼び出すことで,次にブラウザへ表示すべきページを設定できます。Wicketではページはクラスですから,setReponsePage()メソッドにクラスを渡せば,そのページが表示されます。ページ遷移のための定義ファイルなどはありません。

また,setResponsePage()には,次のようにクラスだけではなくオブジェクトを渡すこともできます。

リスト5 自分で生成したページに遷移する

setResponsePage(new MyPage(arg1, arg2));

MyPageはあなたが用意したページクラスだと考えてください。あなたが用意したのですから,コンストラクタも自由に作成できます。コンストラクタ引数を介して,自由にデータを受け取ることができます。Wicketでは,必要な情報はリクエストパラメータではなく,コンストラクタ引数を介して渡すこともできるのです。

今回は,次のページへ渡す情報が一切ありません。Twitterから情報を取得するためのTwitterオブジェクトは,login()メソッドが成功すればAppSessionオブジェクト内に保存されるため,次ページでも自由にアクセス可能だからです。

エラーメッセージを表示する

ログインが成功すればsetReponsePage()で次のページに遷移すればよいですが,失敗した場合には,遷移せずに今のページに失敗したことを表示したいところです。

Wicketでは,バリデータによるエラーメッセージは自動的にFeedbackPanelに表示されます。バリデータと同じように,独自のメッセージをFeedbackPanelに表示できれば便利です。

そのためのメソッドが,サンプルプログラムで使っているerror()です。ページを含むすべてのComponentクラスには,debug(), info(), warn(), error(), fatal()というメッセージ出力用メソッドが用意されています。これらのメソッドに指定したメッセージは,FeedbackPanelに表示されます。

プロパティファイルから文字列を取り出す

サンプルプログラムでは,AppSessionに保存されている,最後にログイン失敗した時のエラーメッセージをerror()メソッドに渡しています。しかしその頭に,getString()メソッドの結果値を連結しています。getString()とは何でしょうか。

Wicketは,アプリケーションの国際化を簡単に行えるように,プロパティファイルからの文字列取得を簡単に行えるように作られています。getString()は,引数をキーとしてプロパティファイルを検索して,見つかった文字列を返してくれます。サンプルプログラムでは「unauthorized」というキーでプロパティファイルに登録されているメッセージを取得しています。

では,メッセージはどのプロパティファイルに定義すればいいのでしょうか。これも簡単です。HTMLファイルと同じなのです。Wicketは,ページと同名の.propertiesファイルを用意すれば,それを「ページ用のプロパティファイル」として扱います。getString()メソッドは,ページ用のプロパティファイルからメッセージを探すのです※2⁠。さらに,プロパティファイル検索時には,ユーザのロケール(国/言語情報)も参考にします。デフォルトでは,Wicketはブラウザが送ってくるロケール情報をもとに自動的にユーザのロケールを決めます。日本のユーザであれば,おそらく「ja_JP」というロケールになります。Wicketは「ページ名_ja_JP.properties」⁠ページ名_ja.properties」⁠ページ名.properties」の順にプロパティファイルを探し,最初に見つかったものを使用するのです。

Loginクラスのプロパティファイルは「Login.properties」となります。サンプルプログラムでは,Login.propertiesファイルに次のようにメッセージを設定しました。

リスト6 プロパティファイルのメッセージ定義

unauthorized = ログインに失敗しました。

サンプルプログラムでは,ログインに失敗した理由情報(Twitter4jから取り出したもの)の頭に「ログインに失敗しました。」という文字列を付与して,FeedbackPanelに表示するのです。

この例のように,画面に日本語を表示する際には,プロパティファイルに文字列を定義するのが良いプラクティスです。そうしておくことで,いざというときに国際化するのが簡単です。WicketではgetString()によって簡単にプロパティファイルから文字列を取得できます。

※2
さらに,ページにスーパークラスが存在する場合は,スーパークラス用のプロパティファイルも検索対象となります。

Wicketがプログラマを支える

ここまででログインを行うLoginページの実装は完了です。

Loginクラスは40行程度の短いプログラムですが,この中にWicketが提供する機能がつまっています。Formとコンポーネントで入力を受け付ける方法,コンポーネントに設定されたPropertyModelを介して,入力値がページのフィールドに結びつけられるところ,コンポーネントに適用するバリデータによって,モデル更新前に必ず検証が行われるところ,FeedbackPanelへのエラーメッセージ自動表示,Session.get()による独自セッションオブジェクトの取得,setResponsePage()メソッドによるページ遷移,getString()によるプロパティファイル自動検索,error()メソッドによるFeedbackPanelへのメッセージ表示など,いろいろな機能を使用しました。Wicketが提供する機能を使うことで,プログラムはシンプルに,本当に行いたいことだけを記述しています。

Wicketは豊富な機能を単純なメソッド呼び出しで使えるよう,デザインされています。Wicketが土台となり,プログラムのための環境を作り上げているのです。

次回は,Twitterのタイムライン(発言の一覧リスト)を表示することで,Wicketがどうやってリスト状のHTMLを生成するのか,を紹介したいと思います。

著者プロフィール

矢野勉(やのつとむ)

フリーランスのプログラマ。Wicket-ja主催。

ウェブ・アプリケーションの開発を中心にさまざまな案件に関わってきました。現在はWicketによる開発を支援しています。

URLhttp://d.hatena.ne.jp/t_yano/

著書