これは Mayaa Advent Calendar 2015 の19日目です。昨日は「Mayaaに慣れた僕がThymeleafを試してみる」でした。
さて、一昨日、昨日と、MayaaのライバルとみなされるJava HTMLテンプレート、Mixer2とThymeleafを試してみました。思えば2年前、JJUGのLT大会で、テンプレートエンジンネタでぶつけてきたときを思い出します。
1 yusuke テンプレートエンジンを制する者が世界を制す
2 nabedge 進撃のMixer2 – 立体機動テンプレートエンジン
3 eiryu Thymeleafでハマったこと
4 susumuis from JSP to Design-friendly Template Endine / JSPからMayaaに移行した本当の話
5 smilelx_xl(+susumuis) テンプレートエンジンを利用したプログラマーとデザイナーの共同開発で大切なこと(仮)
:
:
実際にためしてみると、あながち競合する技術ではないのかなと印象を持ちました。
そういえば、忘れてました!Java EE本家、JSFのFacelets書式はXHTML形式なので、これも、検討対象となりそうです。今日はこれで、デザインーとの協業が可能か、いしがみメソッドは適用可能かを、見てみたいと思います。
Java EEといったら、NetBeans
僕は普段、Eclipseを使い、Androidの時はAndroid Studioを使いますが、Java EEの時はNetBeansを使います。
詳しくは、Introduction to JavaServer Faces 2.x というドキュメントが分かりやすいです。今回はもっとシンプルに作ってみます。
Hello World
NetBeansで[新規プロジェクト] - [Java Web]を選び、フレームワークに「JavaSever Faces」を選んで、ライブラリにJSF2.2を選べば雛形が作られます。
WEB-INF/index.xhtmlを次のように作成します。
<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://xmlns.jcp.org/jsf/html">
<h:head>
<title>Facelet Title</title>
</h:head>
<h:body>
<h:outputText value="#{helloBean.hello}"/>
</h:body>
</html>
タグ名にh:
が付いている時点で、Mayaa、Mixer2、Thymeleafとは毛色が違います。
デザインエディットするときはサーバーを立ち上げるか、開発環境のエディタを使う必要があります。デザイナーが作成したHTMLを元にプログラマーが埋め込む方式であれば、いいかもしれません。
ループはどうするか?
ループするときはこんな感じになります。
例えばこんな感じのItemクラスを作って
public class Item {
private String name;
public Item(String name) {
this.name = name;
}
public String getName() {
return name;
}
}
管理ビーンのプロパティにリストとして登録してみます。
@Named(value = "helloBean")
@Dependent
public class HelloBean {
private String hello = "Hello World";
private List<Item> list = new ArrayList<>();
public HelloBean() {
list.add(new Item("りんご"));
list.add(new Item("ばなな"));
list.add(new Item("みかん"));
}
public String getHello() {
return hello;
}
public List<Item> getList() {
return list;
}
}
テンプレートは
<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://xmlns.jcp.org/jsf/html"
xmlns:ui="http://xmlns.jcp.org/jsf/facelets">
<h:head>
<title>Facelet Title</title>
</h:head>
<h:body>
<h1>sample</h1>
<h:outputText value="#{helloBean.hello}"/>
<ui:repeat var="row" value="#{helloBean.list}">
<div><h:outputText value="#{row.name}"/></div>
</ui:repeat>
</h:body>
</html>
結果
<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"><head id="j_idt2">
<title>Facelet Title</title></head><body>
<h1>sample</h1>Hello World
<div>りんご</div>
<div>ばなな</div>
<div>みかん</div></body>
</html>
ふむふむ。大体分かってきました。
JSFは基本的にはPrimeFacesを使ったコンポーネント指向の開発しかできないイメージでしたが、テンプレート主体の開発もできそうです。
いしがみメソッド検証
JSFをテンプレート主義で使った想定で検証してみます。
m:id含め、プログラム都合の識別子は常に大文字を使う
Mayaaで言うところのm:id、Thymeleafに言うところのth:ifなどの独自属性は、JSFでは独自タグになります。
m:idのする仕事を4種類に限定する
-出力: h:outputText
-分岐: c:if
-繰り返し: ui-repeat
-属性: pt:属性名
4種類の実装方法はルールに従う
このルールに対応するとしたら、「使うタグはある程度限定する」といったところになると思います。
h:inputTextのようなコンポーネントは便利ですが、どこまで使うかはプロジェクトごとのポリシーとして、決めてから使うのが良いと思います。
LOOP系のm:idはindexには長い名前を使い、maxを十分に
ui:repeatに変数名を取れるので、ここではiとかjとかは使わず適度な長さの名前をつければ良いと思います。
Mayaaで長い名前をつけるべきとしたのは、名前がMayaaファイル内に隠蔽されているためなので、Thymeleaf同様、表に出てくる場合はそれほど神経質になる必要はありません。
writeプロセッサーでエスケープを解除するときは全部する
エスケープしないテキストは escape="false" という属性をつけるだけです。
tableタグだけは特別に扱う
uiなどの独自タグが使えるので、Mayaa、Mixer2のようなHTMLにこだわったテンプレートエンジンほどここは問題にならないと思います。
m:idをパラメータ対応にする
Thymeleafと同様、式を直接書けてしまうので、m:idを減らすためのパラメータという要求は発生しないと思います。
PathAdjusterを効果的に使う
"/"で始まっていないパスは相対パスと想定されて動作するようです。その時の調整ロジックをフックできるかについては、すみません、よくわかりませんでした。
ヘッダー・フッター・共通部品はiframeタグをうまく使う
直接テンプレートを開くことはあまり得意ではなさそうなので、これは諦めるしかなさそうです。
テンプレート上のコメントは、ソース表示時に見えないようにする
<ui:remove> </ui:remove>
を使うのが良いそうです。
単語はなるべくテンプレート側に書く
これはできそうです。
nekoHTMLパーサーをいじる
もちろん、そんな必要はありません。
まとめ
JSFというと、結構複雑なコンポーネント指向の仕組みだと思いましたが、テンプレート指向でもけっこう行けることがわかりました。
プロジェクト内で、使うタグのルールを定めることで、デザイナーとの連携も可能かもしれません。