コンポーネント型Java WebフレームーワークZKをSpring Bootと一緒に試すメモ

ZKという、コンポーネント型のWebフレームワークがあって、ちょっと面白そうなので試してみた。
https://www.zkoss.org/

コンポーネント型なのでJSFが近い。
とりあえず始め方がここにいろいろある。
https://www.zkoss.org/wiki/ZK_Installation_Guide

プロジェクト作成

まあ、結局Spring Bootと一緒に使うことになるだろうから、Spring Bootで始めるやつを見る。
https://www.zkoss.org/wiki/ZK_Installation_Guide/Quick_Start/Create_and_Run_Your_First_ZK_Application_with_Spring_Boot

まずSprig Bootのプロジェクトを作る。
https://start.spring.io/

Dependencyは何もいらないということなので、そのまま。

Spring MVCなどはZKの依存ライブラリとして入ることになる。

で、pom.xmlにrepositoryの追加。

 <repositories>
        <repository>
            <id>ZK CE</id>
            <name>ZK CE Repository</name>
            <url>https://mavensync.zkoss.org/maven2</url>
        </repository>
    </repositories>

あと、dependencyを追加。

     <dependency>
            <groupId>org.zkoss.zkspringboot</groupId>
            <artifactId>zkspringboot-starter</artifactId>
            <type>pom</type>
            <version>3.2.3</version>
        </dependency>

ドキュメントには、${zkspringboot.version}の部分はmavenレポジトリを確認してくれと書いてあったので、ここにある最新っぽい3.2.3を指定。
http://mavensync.zkoss.org/maven2/org/zkoss/zkspringboot/zkspringboot-starter/

最初の画面を作る

ではZKのコードを書いてみる。zulという拡張子でXMLを書くらしい。
ドキュメントをそのままコピペ。してsrc/main/resources/web/hello.zulに保存

<zk>
    <window title="Hello ZK - Spring Boot!" border="normal">
        You are using ZK version <label value="${session.webApp.version}"/>
    </window>
</zk>

あと、src/main/resources/application.properties ファイルに設定を一行追加

zk.homepage=hello

で実行やーと思ったらorg.zkoss.zk.ui.http.HttpSessionListenerがないというClassNotFoundが・・・。

zkspringboot-starter.3.2.3のPOMを見るとzkbindがprovidedになってるのでプロジェクトに含まれない。provideされてないし。

ということで、自分のpom.xmlにzkbindも追加。zkspringboot-starterにあるものからscopeを取り除いただけ。

     <dependency>
            <groupId>org.zkoss.zk</groupId>
            <artifactId>zkbind</artifactId>
            <version>10.0.0-jakarta</version>
            <exclusions>
                <exclusion>
                    <groupId>org.slf4j</groupId>
                    <artifactId>slf4j-jdk14</artifactId>
                </exclusion>
            </exclusions>
        </dependency> 

改めて起動したらlocalhost:8080にアクセスしたら動いた!

独自のファイルを追加する

では独自のファイルをsrc/main/resources/web/world.zul に置いてみる。

<zk>
    <window title="My Page" border="normal">
        It works!!
    </window>
</zk>

で、localhost:8080/worldとかにアクセスしてもNot Found。
どうやってアクセスすればいいのか全然わからなかったのだけど、サンプルコードとか見てたらコントローラーかかないといけないっぽい。

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;

@Controller
public class HelloController {
    @GetMapping("/helloworld")
    public String hello() {
        return "world";
    }
}

なんかダサいな。パスをそのまま返すコントローラを作ることになりそう。
ドキュメントさがしたら、ここにあった。
https://github.com/zkoss/zkspringboot/blob/master/README.md

改めてコントローラのパスにアクセスしたら見れた。

Javaコードと結び付ける

じゃあ、ボタン押したらなにかJavaのコードを呼び出すっていうのをやろう。
それっぽいタグを書いてコンポーネントを置いてみる。idをちゃんと指定しておけばどうにかなる。

<zk>
  <window title="My Page" border="normal"
      apply="com.example.demo.HelloComposer">
    It works!!
    <vlayout>
      <hlayout>
        <textbox id="input"/>
        <button id="exec" label="Go"/>
      </hlayout>
      <label id="output" value="hello"/>
    </vlayout>
  </window>
</zk>

コンポーネントはこのリファレンスに。
https://www.zkoss.org/wiki/ZK_Component_Reference

そしたら対応するJavaコードを書く。クラス名をwindowタグのapplyに指定している。このクラスはSelectorComposer<Component>を継承する必要がある。

package com.example.demo;

import org.zkoss.zk.ui.Component;
import org.zkoss.zk.ui.select.SelectorComposer;
import org.zkoss.zk.ui.select.annotation.Listen;
import org.zkoss.zk.ui.select.annotation.Wire;
import org.zkoss.zul.Label;
import org.zkoss.zul.Textbox;

public class HelloComposer extends SelectorComposer<Component>{
    @Wire
    private Label output;
    @Wire
    private Textbox input;
    
    @Listen("onClick = #exec")
    public void go() {
        output.setValue(input.getValue());
    }
}

あとは、コンポーネントに対応するフィールドを定義して@Wireアノテーションを貼る。フィールド名はたぶんIDと同じ名前にする必要がある。違う場合はアノテーションに指定すればいいのかもしれないけど試してない。
イベントハンドラには@ListenをつけてonClickにボタンのIDを指定する。

実行したら動いた!

Spring Bootとの組み合わせはJSFよりもやりやすい。
結構よさそうなんだけど、コンポーネントベースのフレームワークを使いたいのは企業の社内システムで、そうするとJEEアプリケーションサーバーをたててそうだし、いろいろ考えるとJSFがいいかなぁ。