Apache Wicket 8 の代表的な変更点は結局どうなったか

## はじめに

あれやこれやで1年ぐらいプロダクトの開発・保守の実働から離れておりまして、その間にめでたく [Apache Wicket 8.0.0 がリリース](https://wicket.apache.org/news/2018/05/22/wicket-8-released.html)されていました。

[8.0.0_M3の頃に代表的な変更点の記事](https://qiita.com/gishi_yama/items/59fae7f2a56df31c5749)を書いたのが2016年冬、リリースが2018年5月ということで、今回も長い助走期間だったようです。

本稿では、**M3の頃の記事の中で正式リリース時に変わってしまった部分**をまとめておきます。変わっていない部分はM3の記事へのリンクを張っておきます。全ての変更点や[migration guide](https://cwiki.apache.org/confluence/display/WICKET/Migration+to+Wicket+8.0)を網羅するものではありませんのであしからず。

## Modelの変更点

M3の記事から大きく変更は無いようです。

- `LambdaModel`　が使える
- コンポーネントにLambda式やメソッド参照を渡せばModelにラップしてくれる
- `LoadableDetachacbleModel` の`of`メソッドにLambda式やメソッド参照を渡せる
- `AbstractReadOnlyModel` は非推奨になる（`IModel#getModel` を使う）

過去の記事：https://qiita.com/gishi_yama/items/59fae7f2a56df31c5749#modelの変更点


## コンポーネントの変更点

### Link, Buttonでのlambda式の利用

**標準ライブラリでの対応はとりやめになりました**。

たとえば

```java:M3の頃にできてたやり方
Link<Void> foo = Link.onClick("toHogePage", (l) -> setResponsePage(new toHogePage(model)));
```
のような**Lambda式&ファクトリっぽい書き方は、8へのアップグレードだけでは出来ない**ようになっています。

これはM5のリリース時に決断されており、不可逆な影響がある（後から付け足せるけど後からは止められない）こと、全てのコンポーネントを対象にオーバーライド可能なメソッドをlambda化することの是非、Ajaxコンポーネントのメタ情報の保持しずらさなどが理由となったようです。

- [Proposal: Remove all component lambda-based factory methods before 8.0.0 final](http://apache-wicket.1842946.n4.nabble.com/Proposal-Remove-all-component-lambda-based-factory-methods-before-8-0-0-final-td4677009.html)
- [new lambda handler component proposal](http://apache-wicket.1842946.n4.nabble.com/new-lambda-handler-component-proposal-td4677155.html#none)

ただ、コンポーネントの中で一切Lambda式が使えなくなったかというとそうではないです。

### Wicketstuff Lambda Components

Wicketは拡張コンポーネントなどを WicketStuff というプロジェクトにまとめており、ライブラリの追加で使えるようになっています。上記の代わりに、こちらでLambda式が使えるコンポーネントのファクトリが用意されました。

```xml:pom.xml
    <dependency>
      <groupId>org.wicketstuff</groupId>
      <artifactId>wicketstuff-lambda-components</artifactId>
      <version>8.0.0</version>
    </dependency>
```

でライブラリを追加して、

```java:ComponentFactoryの例
// Wicket 7 まで ------------
Link<Void> link = new Link<Void>("toFooPage") {
  private static final long serialVersionUID = 3391006051307639762L;

  @Override
  public void onClick() {
    // 諸々の処理
    setResponsePage(new FooPage(model));
  }
};


// Wicket　8　＆ Wicketstuff Lambda Components の ファクトリ例 ------------
// 第2引数のlinｋは宣言されたLinkインスタンス自身の参照
Link<Void> link = ComponentFactory.link("toFooPage", (link) -> {
  // 諸々の処理
  setResponsePage(new FooPage(model));
});

// ページ移動だけなら1行にできる
Link<Void> link = ComponentFactory.link("toFooPage", (link) -> setResponsePage(new FooPage(model)));


```

のように、ファクトリメソッドを使うことが出来ます。 

`ComponentFactory` を static import してしまえば、

```java
Link<Void> foo = link("toListPage", (link) -> setResponsePage(new FooPage(model)));
```

と書け、よりすっきりしますね。

`ComponentFactory` にファクトリメソッドが用意されているコンポーネントは

- AjaxLink
- AjaxButton
- AjaxCheckBox
- AjaxSubmitLink
- Link

の5種類です。個人的に `Button` は欲しかった所ですが、無いです...（プルリク送ればいいのかもしれませんが）。

## Behavior

M3の記事から大きく変更は無いようです。こちらは当初のとおり、Lambda式を使って宣言できます。

過去の記事：https://qiita.com/gishi_yama/items/59fae7f2a56df31c5749#behavior

あと、Wicket8からは `AjaxEventBehavior` などに渡す**JSのイベント名が `click` `blur` の様なon接頭語ないもののみ対応**しています（接頭語ありはWicket6で非推奨化）。ここはマイグレーションするときに一括チェックしておいた方が良いでしょう。

## 終わりに

Lambdaがどのくらい入ってくるのかは個人的に注目していた点ですが、ドラスティックな変更を避けた形でリリースされています。基本が変わらないので、マイグレーションや保守の観点ではアップグレードは楽になっているのかもしれません。

他にも変更点はありますので、アップグレードされる方は [migration guide](https://cwiki.apache.org/confluence/display/WICKET/Migration+to+Wicket+8.0) を参考にしてください。（そのうち保守でハマった件が出てくれば追記したいなと思います）

なお、本稿の内容の反映後のコード例は[こちら](https://github.com/gishi-yama/wicket8_demo)です。