最新のT2FrameworkでCDIがFormでも有効になるのを確認した

Glassfish V3にて確認した。
問題なし。

問題なく使用できたT2のバージョンは

  • t2-0.6.3-20100202.022748-16.jar

で、ちょっと前の

  • t2-0.6.3-20100201.091209-13.jar

ではダメだった。


ただし、T2のログとNetBeansの相性の悪さでT2の動作が異様に遅いのがちとつらいけど。

Adapter含めてコードは前と同じ。

一応コード全部載せる。

リクエストスコープフォーム格納用。

package t2cdi;

import java.io.Serializable;
import javax.annotation.PreDestroy;
import javax.enterprise.context.RequestScoped;
import javax.inject.Named;

@RequestScoped
@Named("requestData")
public class RequestData implements Serializable{
    String name ;


    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getMessage() {
        if(name == null){
            return "名前を入力してください";
        }
        return "Hello! "+name+" /instance="+this;//インスタンス表示
    }

    @PreDestroy
    void destroy(){
        System.out.println("requestDTO 破棄"+this);
    }
}


ページクラス。シングルトン。

package t2cdi;

import javax.inject.Named;
import javax.inject.Singleton;
import org.t2framework.t2.annotation.core.Default;
import org.t2framework.t2.annotation.core.Form;
import org.t2framework.t2.annotation.core.Page;
import org.t2framework.t2.navigation.Forward;
import org.t2framework.t2.spi.Navigation;


@Singleton
@Named
@Page("/")
public class HelloPage {


    @Default
    public Navigation index(@Form RequestData input){


        return Forward.to("/index.jsp");
    }

}


T2でCDI使うためのアダプタ。

package t2cdi;

import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.enterprise.context.spi.CreationalContext;
import javax.enterprise.inject.spi.Bean;
import javax.enterprise.inject.spi.BeanManager;
import javax.inject.Inject;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import org.t2framework.commons.meta.BeanDesc;
import org.t2framework.commons.meta.BeanDescFactory;
import org.t2framework.commons.util.CollectionsUtil;
import org.t2framework.t2.adapter.AbstractContainerAdapter;
import org.t2framework.t2.handler.ExceptionHandler;
import org.t2framework.t2.handler.GlobalExceptionHandler;
import org.t2framework.t2.handler.impl.GlobalExceptionHandlerImpl;

public class CdiAdapter extends AbstractContainerAdapter<BeanManager> {

    BeanManager beanManager;

    public void init() {
        init("");
    }

    public void init(String string) {
        try {
            beanManager = InitialContext.doLookup("java:comp/BeanManager");

        } catch (NamingException ex) {
            Logger.getLogger(CdiAdapter.class.getName()).log(Level.SEVERE, null, ex);
        }

    }

    public <T> boolean hasComponent(Class<T> type) {
        for (Bean b : beanManager.getBeans(type)) {
            System.out.println(type +"/hasComponent-true");
            return true;
        }

        System.out.println(type+"/hasComponent-false");
        return false;
    }

    public <T> T getComponent(Class<? super T> type) {
        for(Bean b : beanManager.getBeans(type) ){

            CreationalContext cc = beanManager.createCreationalContext(null);

            Object result = beanManager.getReference(b, type, cc);
            if(result == null){
                result =  b.create(cc);
            }else{

            }

            return (T) result;
        }

        System.out.println("生成失敗"+type);
        return null;
    }

    public <T> List<T> getComponents(Class<? super T> type) {
        System.out.println("getComponents/"+type);
        List<T> result = new ArrayList<T>();
        for (Bean<?> b : beanManager.getBeans(type)) {
            System.out.println(b.getName());
            result.add( (T) getComponent(b.getBeanClass()));
        }
        System.out.println(result.size());

        return  (List<T>) result;
    }

    public <T> BeanDesc<T> getBeanDesc(Class<? super T> type) {
        if(hasComponent(type)){
            return (BeanDesc<T>) BeanDescFactory.getBeanDesc(type);
        }
        return null;
    }

    public <T> void register(Class<? extends T> type) {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    public <T> void register(T t) {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    public <T> T injectDependency(T t) {

        for(Bean b : beanManager.getBeans(t.getClass()) ){

            CreationalContext cc = beanManager.createCreationalContext(null);

            beanManager.createAnnotatedType(Inject.class);

            return t;
        }

        return t;
    }

    public void destroy() {
    }

    public BeanManager getContainer() {
        return beanManager;
    }

    public List<ExceptionHandler<Throwable, Exception>> createExceptionHandlers() {
        return CollectionsUtil.emptyList();
    }

    public GlobalExceptionHandler createGlobalExceptionHandler() {
        return new GlobalExceptionHandlerImpl();
    }

}


テンプレートJSP

<%@page contentType="text/html" pageEncoding="UTF-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
   "http://www.w3.org/TR/html4/loose.dtd">

<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
        <title>T2とCDIのすばらしい組み合わせ</title>
    </head>
    <body>
        ${requestData.message}
        <form action="">
            <input type="text" name="name" value="${requestData.name}"/>
            <input type="submit" value="はろー" />
        </form>
    </body>
</html>


シングルトンからRequestスコープにアクセスしても問題ないこと、それがそのままJSPのELで取得していることを見てほしい。request#setAttribute使わなくとも表示用にちゃんとセットされているし、セッションへの格納も@SessionScopedをつけてページクラスに注入して使うだけ。他のDIコンテナではこんな使い方はそのままでは出来ないためT2Frameworkと最も相性がよい可能性もある。


CDIが使える、フォームがコンテナ管理ということは、たとえばJava EE 6で標準化されたBean Validatorが使えるということ。でも、T2にその仕組みをつかうタイミングはあるのだろうか。ErrorInfoのセットをカスタマイズできるタイミングが存在するかということだけれども。

ErrorInfo使わないでプラグインでなんかやればいいのかなーとか。Bean Validatorのいいところは親子関係とかで子の要素についてもバリデーションで切るというところ。テーブルのような入力フォームをまるごとチェックするとかでつかえる・・・のかはわからないけど、いろいろと楽しめるようになるかも。