読者です 読者をやめる 読者になる 読者になる

Wicket 1.3 から 1.4 へマイグレートしてみた

数年前から Wicket 1.3 (1.3.7) で開発していたプロジェクトを Wicket 1.4 (1.4.7) へマイグレートした体験談です。
長文の上、ほぼ公式Wikiのマイグレート手順通りなのですが、何かの参考になりましたら。

作業をした当時は1.4.7が最新版だったので。この記事も1.4.7として書いていますが、1.4.8 以降に大きな変更が無いかぎり、同手順でいけるはずです。また、作業はEclipse Galileoで行いました。

Wicket 1.4.7 をダウンロードして、Wicket 1.3.7 のライブラリと入れ替える。

  1. Wicketの公式サイトからWicket-1.4.7をダウンロードして、展開する。
  2. apache-wicket-1.4.7/lib ディレクトリの中から、必要なjarファイルををプロジェクトのlibディレクトリへコピーする*1
  3. プロジェクトのlibディレクトリから、1.3.7のjarを削除する*2
  4. Eclipseメニューバーの Project » Properties » Java Build Files » libraries を選択して、1.3.7のライブラリをRemoveし、1.4.7のライブラリをaddする。
  5. プロジェクトをビルドする。

ライブラリを入れ替えると、Error数とwarning数が大変なことに……。

ソースコードを修正する

星屑のように広がったErrorとWarningをなんとかすべく、公式Wikiのマイグレート手順に従ってマイグレートを始めます。

始める前は Component.get(set)DefaultModel() ぐらいじゃん?とか思っていたけどそんなことはなかったぜ!

Component.get(set)DefaultModel()

Modelのget(set)の仕方が変わっているので、修正します。

	hoge.getModel(); → hoge.getDefaultModel();
	hoge.setModel(IModel); → hoge.setDefaultModel(IModel);

Eclipseの変換予測とか、ファイルの一括修正スクリプトを使えば機械的にやれると思います。

匿名クラス化したDataProviderなどのオーバーライドメソッド
	@Override
	public IModel model(Object object) {
		IModel model = modelMap.get(object);
			(中略)
		return model;
	}

上記の様な、匿名クラス化したDataProviderのオーバーライドメソッドでは、引数の型を正確に指定してやらないとエラーが消えませんでした。

	@Override
	public IModel<Hoge> model(Hoge hoge) {
		IModel<ActivityModelBean> model = modelMap.get(hoge);
			(中略)
		return model;
	}

こんな感じで解決しました。

FileUploadFieldコンポーネントの引数を修正する

1.4から、FileUploadFieldコンポーネントにModelが必要になっています。

例えば1.3では

FormObject formObject = new FormObject();
Form form = new Form("form"new CompoundPropertyModel(formObject));
FileUploadField fileField = new FileUploadField("fileField");
TextField nameField = new TextField("nameField");
form.add(fileField);
form.add(nameField);

という風に書いてあれば、fileFieldはモデルを必要としないため、formObjectのフィールド変数を探索することはありませんでした。

しかし、Wicket1.4からはFileUploadFieldにModelが必要になったため、このまま実行すると描画時にfileFieldがformObjectのフィールド変数(file)を探索してしまい、例えばformObject.fileが存在しないとエラーになってしまいます。

このような例であれば、

FileUploadField fileField = new FileUploadField("fuf"new Model<FileUpload>());

とすることで、fileFieldのモデルオブジェクトはformObject.fileではなくなり、適切に動作します。

私の環境では、ここまで来ればエラーが消えました。

引き続き5000個のWarningが無くなるようにマイグレートを進めます。

独自のCSSJavaScriptの指定

Headタグのスタイルシートのパス指定方法が変わっていたので、変更します。

this.add(HeaderContributor.forCss("hoge.css");

から

this.add(CSSPackageResource.getHeaderContribution("hoge.css"));

こんな感じ。JavaScriptなどの設定も同様です。

Validators

バリデータクラスが大きく変わってしまったので、修正します。
スタイルシートの設定方法が変わっていたので、変更します。

hgoe.add(NumberValidator.range(01000));

から

hoge.add(new RangeValidator<Long>(new Long(0)、 new Long(100)));

こんな感じ。

特に、この例の様な、Long値の入力するテキストフィールドなどの場合に、今まではint型で良かった引数をLong型の引数として与えてやらなくてはいけないところでちょっとハマりました。

Generics

5000個のWarningのうち、ほとんど全てがGenericsの指定についてでした。
ここも、CompoundPropertyModelの有無や、直接setしているModelの有無によってGenericsの型を使い分けたりで、以外と注意しなきゃいけない部分がありました。

例えば、

Link<Void> link = new Link<Void>("link") {
	@Override
	public void onClick() {
		(中略)
	}
};

Link<String> link = new Link<String>("link"new Model<String>()) {
	@Override
	public void onClick() {
		(中略)
	}
};

の違いとか、CompoundPropertyModelが親コンポーネントにsetされている時は、wicket:idを元にバインドされるオブジェクトのフィールド変数の有無と型に気を配ったりとか。もし大人数で一斉にマイグレートする場合は、あらかじめ確認方法の徹底やLink、 FormなどのGenericsの設定ルールを決めておくと良いと思います。

あと、getDefaultModelなどのキャストの型の指定もこの際に外しました。

HTMLにもマイグレートすべきところがあった

Wicketのマイグレート記事に載っていなくてうっかりしたんですが、HTMLにもマイグレート箇所がありました。

<html xmlns="http://www.w3.org/1999/xhtml"
	xmlns:wicket="http://wicket.apache.org/dtds.data/wicket-xhtml1.3-strict.dtd"
	lang="ja" xml:lang="ja">

<html xmlns="http://www.w3.org/1999/xhtml"
	xmlns:wicket="http://wicket.apache.org/dtds.data/wicket-xhtml1.4-strict.dtd"
	lang="ja" xml:lang="ja">

と修正。

便利なコンポーネントが追加されていた

モデルオブジェクトに与えられたEnumの値を元に、プロパティファイルの値を表示するようなConverterを持ったLabelコンポーネントを独自に拡張して作っていたりしたんですが、EnumLabelコンポーネントなどの出現でいらなくなりました。

感想

行った作業は以上です。
工数として2人×7日強ぐらいで、動作テストも含めてマイグレートを完了しました。
Genericsも含めれば作業量は決して少なくはなかったですが、特にロジックを変えるような事や、大々的にクラスやHTMLを書き換えるなんてこともありませんでした。さすがWicket

ただ、私たちのプロジェクトではWicketで特に難しい事はやらず、用意されているコンポーネントを素直に使うシンプルな使い方がほとんどなので、比例して困った箇所も少なかったのかもしれません。

謝辞的なもの

「set(get)defaultModelとGenericsの変更よろしく!想定外の何かがあったら経験値で乗り越えて!」

という曖昧な指示だけでプロジェクトのErrorとWarningをほぼ全て殲滅してくれた@Lament_Grief氏にこの場を借りて感謝を。Error数とWarning数を見た時のあなたの苦い表情が忘れられません*3

最後に、この様な内容と相成りましたが、Twitterで記事をリクエストしていただいた皆様、ありがとうございました。

*1:今回は wicket-1.4.7.jar、 wicket-datetime-1.4.7.jar、 wicket-devutils-1.4.7.jar、 wicket-extensions-1.4.7.jar、 wicket-guice-1.4.7.jar、wicket-ioc-1.4.7.jar、wicket-jmx-1.4.7.jar をコピーしました

*2:今回は wicket-1.3.7.jar、 wicket-datetime-1.3.7.jar、 wicket-extensions-1.3.7.jar、 wicket-guice-1.3.7.jar、 wicket-ioc-1.3.7.jar、 wicket-jmx-1.3.7.jar を削除しました

*3:もしかしたら氏にとっては150個のErrorと5000個のWarningは十分トラウマだったかもしれませんが、怖くて感想は聞いてません