Wicketを使う

今度の案件は、フレームワークApache Wicketを利用するようなので調査を開始。調査は以下のサイトを参考にした。
http://www.javelindev.jp/wicket/doc/tutorial01
http://hondou.homedns.org/pukiwiki/pukiwiki.php?Java#kc48aca8

どのバージョンを使うかも決まっていないが、サンプルとして提供されたプロジェクトが1.3.3だったので1.3系の最新版である1.3.5をダウンロードする。大枠は変わらないはずなので気にしない。

Eclipseで[SimpleWicket]という名称のTomcatプロジェクトを作成。今回は簡単に構築するために、EclipseTomcatプラグインを使用する。WEB-INF/libに何を入れておけばよいか分からないので、1.3.5のwicket-exampleに付属していたものをすべてをコピーした。springとかguiceとかあるけど気にしない。

Tomcatプロジェクトとして作成すると、ソースフォルダがWEB-INF/srcに作られるけど、なんだか気持ち悪いのでMaven風にsrc/main/javaとsrc/main/resourcesを作成した。出力先はtargetではなくWEB-INF/classesを指定。また、src/main/resources配下にjavaパッケージと同じ階層を切ってHTMLファイルを配置することにした。
Wicketでは、Pageクラスと同じディレクトリ構造にあるHTMLを探しに行くようになっているらしく、それの変更方法がよく分からなかったので、この方法はちょっとどうかと思うけど、まず動くものを作ること優先にした。

それではWEB-INF/web.xmlから。

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://java.sun.com/xml/ns/j2ee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"
         version="2.4">
  <display-name>Simple Wicket</display-name>
  <filter>
    <filter-name>SimpleWicketApplication</filter-name>
    <filter-class>org.apache.wicket.protocol.http.WicketFilter</filter-class>
    <init-param>
      <param-name>applicationClassName</param-name>
      <param-value>net.masa.wicket.simple.SimpleWicketApplication</param-value>
    </init-param>
  </filter>
  <filter-mapping>
    <filter-name>SimpleWicketApplication</filter-name>
    <url-pattern>/*</url-pattern>
  </filter-mapping>
</web-app>

次にsrc/main/javaにnet.masa.wicket.simpleパッケージを作成してApplicationクラスを作成する。

public class SimpleWicketApplication extends WebApplication {

 /** リクエスト・レスポンス及びHTMLのエンコードです。 */
 private static final String ENCODE = "UTF-8";
 /**
  * コンストラクタです。
  */
 public SimpleWicketApplication() {}

 /**
  * @see org.apache.wicket.protocol.http.WebApplication#init()
  */
 @Override
 protected void init() {
  super.init();
  getRequestCycleSettings().setResponseRequestEncoding(ENCODE);
  getMarkupSettings().setDefaultMarkupEncoding(ENCODE);
 }
  /**
  * @see org.apache.wicket.Application#getHomePage()
  */
 @Override
 public Class<LoginPage> getHomePage() {
  return LoginPage.class;
 }

}

次にApplicationクラスがgetHomePage()で呼び出すページクラスを作成する。 net.masa.wicket.simple.pageパッケージ配下に作成。

public class LoginPage extends WebPage {

 public LoginPage() {
  super();
  createLoginPage();
 }

 @SuppressWarnings("serial")
 private void createLoginPage() {

  add(new FeedbackPanel("feedback"));

  final Form appForm = new Form("appForm");
  add(appForm);

  final TextField loginId = new TextField("loginId", new Model());
  loginId.setRequired(Boolean.TRUE);
  appForm.add(loginId);

  final PasswordTextField password = new PasswordTextField("password",
    new Model());
  password.setRequired(Boolean.TRUE);
  appForm.add(password);

  appForm.add(new Button("doLogin") {
   public void onSubmit() {
    setResponsePage(new MenuPage());
   }
  });
 }
}

最後にログイン画面のHTML。 これはsrc/main/resources/net/masa/wicket/simple/page配下に作成した。

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
</head>
<body>
<h1>ログイン</h1>
<div wicket:id="feedback"></div>
<form method="POST" wicket:id="appForm">
<table border="0">
  <tr>
    <th>ログインID</th>
    <td><input type="text" wicket:id="loginId" size="10"/></td>
  </tr>
  <tr>
    <th>パスワード</th>
    <td><input type="password" wicket:id="password" size="10"/></td>
  </tr>
  <tr>
    <td colspan="2"><input type="submit" value="ログイン" wicket:id="doLogin"/></td>
  </tr>
</table>
</form>
</body>
</html>


あとは空のMenuPage(javaとHTML)を作成しておいて、動かしてみたらきちんとMenuPage.htmlに遷移された。個人で使うにはJavaを書く楽しみみたいなのが感じられて、これはこれで結構面白いかもしれない。

ただ、気になる点がいくつか。まずプロジェクトでの利用を前提とした場合、個人のスキルにだいぶ依存してしまうので、新人やあまりJavaに触れたことがない要員が多い場合なんかは使いづらいかもしれない。
unitテストのやりやすさみたいなのはどうなんだろう。ここには書いてないが、マスタの登録機能みたいなのを一通り作ってみたが、匿名クラスで色々書くことが多いので個々のテストケースなんかは書きづらいんじゃないだろうか。んー、でもそんなこともなさそうかなぁ。今回はテストケース無視で書いたからよく分からないな。個人的には匿名クラスはあんまり好きじゃないので、それが引っ掛かりの原因かもしれない。

次に、入力項目の入力チェックルールなどを全部Javaコードで書かなきゃいけないってのは、ダルく感じてしまう。SAStrutsの場合だと入力チェックルールなんかはほとんどの場合アノテーションで指定できたし、画面の表示制御などはJSPで簡単にできた。画面の制御に関しては、まだWicketの使い方が良く分かってないからなんだけど。フラグの値によって特定の箇所の表示/非表示の制御なんかはどうしたら良いか不明。

あとこれも書き方次第だと思うんだけど、Pageクラスが肥大化しやすいのはどうなんだろう。ボタンクリック時の処理なんかは、ボタンの定義に匿名クラスをくっ付けてズラズラと書かなきゃいけなくて、見通しが悪くなってしまう。きっと上手いやり方があるに違いないんだけど、今のところガリガリ書いていくしかないのかな。コードが長くなるとそれだけバグが混入してしまう確率が高まるから、短いコードをパパッと書いていけると良いんだけどな。取り敢えずもうちょっと色々な画面を作ってみて試してみるしかない。

最後に、これはどのフレームワークにも言えることだけど、一定の品質を確保しようとしたら、ある程度の前準備(コーディング規約とか開発ガイドみたいなの)はホントに必要だよなぁと改めて実感した。