T2FrameworkとJSF 2.0を組み合わせる変態プログラミング

なんと言う変態的な組み合わせ。


単純に前回書いたようにエスケープが自動なのがすごく便利だなーと思いつきでつっぱしる。つまりJSFをテンプレートとしか見ない。


T2とJSFの橋渡しにCDIを使う。

といってもCDIDTOを用意させてT2のページクラスからJSFフォワードさせるだけだが。


T2のCDIの対応がどうなっているかわからないので擬似的に書いたコードで。本来ならPageクラスをCDIで管理させる、もしくはDTOを注入するのが望ましい。


CDIのコンテナであるBeanManagerを取得するだけのリスナー。この書き方だとJNDI使わなくて良いので便利…かな?servlet 3.0でかいてるのでweb.xmlも記述しなくてよいし。Tomcat 7もRC3まできたのでみんないつでもかけるように準備しといたほうが良いよ。Java EE 6のネガティブキャンペーンやってる暇があったら。

@WebListener
public class BeanManagerListener implements ServletContextListener {

    @Resource
    BeanManager injectBeanManager;

    static BeanManager beanManager;

    public void contextInitialized(ServletContextEvent sce) {
        beanManager = injectBeanManager;
    }

    public void contextDestroyed(ServletContextEvent sce) {
    }

    public static BeanManager getBeanManager(){
        return beanManager;
    }
}


T2のページクラス。

@Page("/t2/index")
public class HogePage {

    @Default
    public Navigation getMessage(){

        BeanManager bm = BeanManagerListener.getBeanManager();

        CreationalContext<Object> cc = bm.createCreationalContext(null);
        Bean<?> bean = bm.getBeans("hoge").iterator().next();
        Hoge hoge = (Hoge) bm.getReference(bean ,  Hoge.class , cc);

        hoge.setMessage("ほげ");


        List<String> list = new ArrayList<String>();
        for(char i='A';i<='C';i++){
            list.add(i+"さん");
        }
        hoge.setList(list);

        return Forward.to("/faces/index.xhtml");
    }
}

本来は@Inject Hoge hoge;とかいて注入させたいところ。


いわゆるDTO

package page;

import java.util.ArrayList;
import java.util.List;
import javax.enterprise.context.RequestScoped;
import javax.inject.Named;


@RequestScoped
@Named
public class Hoge {
    String message;
    List<String> list;

    public void setMessage(String message) {
        this.message = message;
    }

    
    public String getMessage(){
        return "<b>"+message+"</b>";
    }

    public int add(int a,int b){
        return a + b;
    }

    public void setList(List<String> list) {
        this.list = list;
    }

    public List<String> 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:ui="http://java.sun.com/jsf/facelets"
      xmlns:c="http://java.sun.com/jsp/jstl/core">

    <head>
        <title>HOGE</title>
    </head>
    <body>
        #{hoge.message}<br/>

        1 + 2 = #{hoge.add(1,2)}<br/>

        <ul>
            <li jsfc="ui:repeat" value="#{hoge.list}" var="item" >
                #{item}
            </li>
        </ul>
        
        <ul>
            <c:forEach items="#{hoge.list}" var="item">
            <li>
                #{item}
            </li>
            </c:forEach>
        </ul>

    </body>
</html>

コントローラとしてT2、テンプレートとしてJSFを使う利点はIDEが対応してるってことかな。NetBeansはもちろん、Eclipseも対応しているはず。


実行結果。
http://shin.cside.com/diary/2010/0531-01.png

repeatでもJSTLでforeachさせてもどっちでもいい。jsfcつあくほうがデザイナさんにはうけはいいのかな。もちろんエスケープもしなくてよい。ひそかにELメソッド使っています。やっぱりメソッドが使えるのは便利。


tilesのようなテンプレート機能も標準であるし、xhtmlだけで複合カスタムコンポーネント作れるし、jstlで作っても良いし意外といけてる気がしてきた。変態的なネタのわりにはまともすぎてつまらんというか。

やはり橋渡しとしてのCDIはいいな。コンテナが標準化されたというのはよい。おかげでJSF使ってるけど、JSFの管理Beanは一切使っていないわけで。