JSFのActionメソッドを分けてみる

件の本のJSFの所だけ、サンプルソース使わないで自分で書いて動かして、一通り遊んでみました。面白いなー。

以下、ド初心者のメモなので随分とトンマな事書きます。端折りまくりなので件の本が無いと訳わかめです。押忍!

えー、サンプルではManagedBeanの中にActionメソッドが入ってる訳です。Actionメソッドの中で、自分自身の属性を全部NULL突っ込んでクリアしてる。こんな感じ。

public class ApplyBean implements Serializable {
    
    private String zipCode;
    private String address;
    private String name;
    private String telephone;
    private Date deliveryDate;
    private List mails;
    private List confirmedMails;

(setter、getterは省略)

    public String submit(){
        setZipCode(null);
        setAddress(null);
        setName(null);
        setTelephone(null);
        setDeliveryDate(null);
        setMails(null);
        setConfirmedMails(null);

        return "submit";        
    }
}

ここで、処理とデータを分離してみたくなるのが、S2というかくーすにかぶれた男の道である。勿論、Actionを持つクラスはステートレスにしておきたい。ApplyActionなんてクラスを作って、そっちにsubmitを移動しよう。

public class ApplyAction {

    public String submit(ApplyBean bean){
        bean.setZipCode(null);
        bean.setAddress(null);
        bean.setName(null);
        bean.setTelephone(null);
        bean.setDeliveryDate(null);
        bean.setMails(null);
        bean.setConfirmedMails(null);

        return "submit";
    }
}

と、ここまで書いたのは良いんだけどね、jsp側からActionメソッドに引数送る方法が、何処にも載ってないのよ。えーえー。

しばしwebで調べる。
http://www.wakhok.ac.jp/~tomoharu/jsf2004/text/index_c7.html

Action Methodには、次の3つのルールがあります。

  • publicであること
  • 引数がないこと
  • Stringを返値とすること。この返値がoutcomeになります。

ドガアー。そんなん本に書いてないよー(見落としてるだけやも知れません)。

方針変更。ActionクラスにBeanをプロパティとして持つしきゃにゃーで。

public class ApplyAction {

    private ApplyBean bean;
    
(setter、getter省略)

    public String submit(){
        bean.setZipCode(null);
        bean.setAddress(null);
        bean.setName(null);
        bean.setTelephone(null);
        bean.setDeliveryDate(null);
        bean.setMails(null);
        bean.setConfirmedMails(null);

        return "submit";
    }

ステートレスでなくなったので、こいつのスコープはrequestにせんといかんよな。同期がとれない。それ以前に件の本によると、でかいスコープのオブジェクトから小さいスコープのオブジェクトを参照してると、小さいスコープのオブジェクトが更新されてもちゃんとでかい方に反映されなかったりして不都合らしい。

よって、faces-config.xmlにはこう書いておこう。

    <managed-bean>
        <managed-bean-name>applyBean</managed-bean-name>
        <managed-bean-class>org.ultimania.jsf.ApplyBean</managed-bean-class>
        <managed-bean-scope>session</managed-bean-scope>
    </managed-bean>

    <managed-bean>
        <managed-bean-name>applyAction</managed-bean-name>
        <managed-bean-class>org.ultimania.jsf.ApplyAction</managed-bean-class>
        <managed-bean-scope>request</managed-bean-scope>
        <managed-property>
            <property-name>bean</property-name>
            <value>#{applyBean}</value>
        </managed-property>
    </managed-bean>

いやー動いた動いた。

で、ここで、かつてサンプルざっと見て実行して喜んでおしまいだったS2JSFを再確認すると、同じく、Actionクラスは各Dtoと処理を委譲するLogicクラスをプロパティとして持ってますな。

但し、JSFの場合、プロパティに何をつっこむかはfaces-config.xmlで定義する所を、S2JSFでは当然diconで定義って違いはある。ああJSFはDIなんだねーと云う話はこの事なのかな?今回はApplyBeanって実装クラスをActionクラスに持たせたけど、interface作ってそれを参照すれば考え方は一緒だと、いう、事か。おおー。

ほんじゃdiconファイルのinstance属性はどうなってるかと云うと、employee.diconのemployeeSearchActionを見てみる。

<component name="employeeSearchAction" 
	class="examples.jsf.action.impl.EmployeeSearchActionImpl"
	instance="request">
		<aspect>actionInterceptorChain</aspect>
	</component>

なんつって書いて有りました。初見ではinstance属性がrequestなの、気にはしてみたものの、「まあそういうものなんだな」って事でスルーしちゃいましたが、なるほどなと云う感じじゃよ。

さて、S2本体とJSFを併用する場合ってどうなるんだろう。ActionとBeanの関連はfaces-config.xmlで定義するとして、今度はActionから業務ロジッククラスを分離した場合、業務ロジッククラスもManagedBeanとしてfaces-config.xmlに書かないといけないのか?したらどんどんfaces-config.xmlが大きくなるような。diconに書くとしたら、faces-config.xmlに書かなくてもちゃんと動くのか?

やってみりゃいいのか。そりゃまた今度。

まあ件の本、最終的にはSpring + Hibernateと連携するので、そこまで遊んでみますか。でも既にS2Daoで遊んで感激した身からすると、Hibernateは今更だなあ・・・。