S2StrutsとJSF 2.0を比較する

S2Strutsのブランクを元に一からNetBeansプロジェクトを作ってみるも玉砕。

サンプルプロジェクトから適当にファイルをコピーしたりして動いた。

セッターインジェクションは動くけど、フィールドインジェクションが動かないけど、これはどこで設定すればいいんだろ。

足し算のサンプルに引き算を追加したものを作ってみた。ほとんどサンプルそのままになってしまったのでおいしくはないけど。


実行結果は以下の通り。ボタンの判別が簡単にできるかどうかが重要。
http://shin.cside.com/diary/2009/1023-01.png


触っていて思ったけどJSFに似ているかもね。そこで比較してみる。

S2Struts

テンプレート

<%@page contentType="text/html" pageEncoding="UTF-8"%>

<%@taglib prefix="s2struts" uri="http://www.seasar.org/tags-s2struts" %>
<%@taglib prefix="html" uri="http://struts.apache.org/tags-html" %>
<%@taglib prefix="bean" uri="http://struts.apache.org/tags-bean" %>
<!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>JSP Page</title>
    </head>
    <body>
        <html:form action="/hoge" >
            <html:text property="param1"  /> 
            <s2struts:submit action="@{hogeAction.add}" value="+"/>
            <s2struts:submit action="@{hogeAction.sub}" value="-"/>
            <html:text property="param2"  /> =
            <bean:define id="f" name="hogeForm" />
            <bean:write name="f" property="result"/>
        </html:form>
    </body>
</html>


アクションフォーム

package hoge.web;

import java.io.Serializable;
import org.seasar.struts.annotation.tiger.StrutsActionForm;


@StrutsActionForm
public class HogeForm implements Serializable{
    String param1;
    String param2;
    String result;

    public String getParam1() {
        return param1;
    }

    public void setParam1(String param1) {
        this.param1 = param1;
    }

    public String getParam2() {
        return param2;
    }

    public void setParam2(String param2) {
        this.param2 = param2;
    }

    public String getResult() {
        return result;
    }

    public void setResult(String result) {
        this.result = result;
    }
    
}


アクション

package hoge.web;

import org.seasar.struts.annotation.tiger.StrutsAction;
import org.seasar.struts.annotation.tiger.StrutsActionForward;

@StrutsAction(input=HogeAction.VIEW)
public class HogeAction {

    @StrutsActionForward
    public static final String VIEW = "/WEB-INF/view/hoge/hoge.jsp";

    private HogeForm hogeForm;

    public void setHogeForm(HogeForm hogeForm) {
        this.hogeForm = hogeForm;
    }

    public String add(){
        int p1 = Integer.parseInt(hogeForm.getParam1());
        int p2 = Integer.parseInt(hogeForm.getParam2());

        int result = p1 + p2;

        hogeForm.setResult( Integer.toString(result) );

        return VIEW;
    }

    public String sub(){
        int p1 = Integer.parseInt(hogeForm.getParam1());
        int p2 = Integer.parseInt(hogeForm.getParam2());

        int result = p1 - p2;

        hogeForm.setResult( Integer.toString(result) );

        return VIEW;
    }
}

カスタムタグ全開なのが今の時代はつらいかな。

JSF 2.0

テンプレート

<?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://java.sun.com/jsf/html">
    <body>
        <form jsfc="h:form">
            <input type="text" jsfc="h:inputText" value="#{hoge.param1}"/>
            <input type="submit" value="+" jsfc="h:commandButton" action="#{hoge.add}"/>
            <input type="submit" value="−" jsfc="h:commandButton" action="#{hoge.sub}"/>
            <input type="text" jsfc="h:inputText" value="#{hoge.param2}"/><span jsfc="h:outputText" value="#{hoge.result}"/>
        </form>
    </body>
</html>

管理Bean

package jsf;

import java.io.Serializable;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;

@ViewScoped
@ManagedBean
public class Hoge implements Serializable{

    private Integer param1;
    private Integer param2;
    private Integer result;

    public Integer getParam1() {
        return param1;
    }

    public void setParam1(Integer param1) {
        this.param1= param1;
    }

    public Integer getParam2() {
        return param2;
    }

    public void setParam2(Integer param2) {
        this.param2= param2;
    }

    public Integer getResult() {
        return result;
    }

    public void setResult(Integer result) {
        this.result = result;
    }

    public String add() {
        result = param1 + param2;
        return null;
    }

    public String sub() {
        result = param1 - param2;
        return null;
    }
}

ここまでやってwicketと比べたのとまったく同じサンプルなのに気がついた。orz

JSF 2.0は設定ファイルはまったく必要ないのでセットアップがはるかに楽。jarファイルを2つlibフォルダにおいてweb.xmlサーブレット指定するだけ。


コードも数値型と文字列型の変換も必要ないし、テンプレートは通常のXHTMLとして表示できるのが強み。Strutsのようにアクションとフォームを分けることも自由にできる。たとえば入力だけのフォームと出力だけのフォームとかも自由にできるし、入力エリアごとに入出力とアクションを分離ということも可能。


それをするとこんな感じになる。

@ManagedBean
public class InputForm implements Serializable{
    Integer param1;
    Integer param2;
//セッターゲッター省略
}

@ManagedBean
public class OutputForm implements Serializable{
    Integer result;
//セッターゲッター省略
}
<form jsfc="h:form">
    <input type="text" jsfc="h:inputText" value="#{inputForm.param1}"/>
    <input type="submit" value="+" jsfc="h:commandButton" action="#{hoge.add}"/>
    <input type="submit" value="−" jsfc="h:commandButton" action="#{hoge.sub}"/>
    <input type="text" jsfc="h:inputText" value="#{inputForm.param2}"/><span jsfc="h:outputText" value="#{outputForm.result}"/>
</form>

つまり、テンプレート側からコードが呼び出されるというのがはっきりわかる。Tiles見たいなのが標準みたいな。ここから一部のみ抜き出して他のページでレンダリングもできるので楽チン。

このまますぐにAjax対応もできるし、やっぱり新しいだけあってかなり楽になってるのがわかるね。