| Preface Setup Samples hello.html add.html forEachList.html forEachResult.html ## Preface Using JSP, you just want to check layout of the page but you need to deploy and start the application server. Have you ever had such experiences? Or have you experienced to cooperate with a designer? With S2JSF, you don't need such troubles anymore. The template view of S2JSF is HTML, not JSP, and it makes you free to such irritated things. ｡ ## Setup Same as Seasar2 requirements, JDK1.4 or higher is required. All you need to do is just extract S2JSFVx.x.x.zip and import unzipped s2jsfdirectory to Eclipse workspace(File -> import -> Existing Project into workspace) The samples of S2JSF is prepared separately, so download and extract it. Same as before, import unzipped file to Eclipse workspace. This sample makes the use of Tomcat5 and Tomcat Plugin. If you do not intall these, please install before trying these samples. Starting Tomcat, you can see S2JSF samples as accesing http://localhost:8080/s2jsf-example/ on your browser. ## Samples ### hello.html Let's go to http://localhost:8080/s2jsf-example/hello/hello.html?message=aaa. It must display "Hello aaa" as you see.From this sample, you can get things described below: define the namespace of S2JSF layout function how to use taglib pointing tags by inject attribute how to use title tag how to change page by page with link how to pass parameters when changing pages describe navigation-rule how to print out string using ValueBinding Let's take a look contents of HTML.
    fig1. hello.html01:<html xmlns:m="http://www.seasar.org/maya" m:extends="/WEB-INF/layout/layout.html">
    02:<head>
    03:<meta http-equiv="Content-Type" content="text/html; charset=Windows-31j" />
    04:<title>Hello</title>
    05:</head>
    06:<body>
    07:    <span m:inject="f:param" m:name="layoutTitle" m:value="Hello"/>
    08:    <span m:inject="s:insert" m:name="body">
    09:        Hello <span m:value="#{message}">hoge</span>
    10:    </span>
    11:</body>
    12:</html>
The first line in the fig.1, xmlns:m="http://www.seasar.org/maya" specifies namespace. This URL(http://www.seasar.org/maya) must be fixed.The prefix, which is "m" in the sample, you can use anything you want to use, "m" is used in the custom. The next attribute, m:extends, points out extending layout. To provide consistent look & feel, the layout of pages are constructed by header, menu, body, and footer. This is very usual need.For corresponding such needs, S2JSF provides function that defining layout of the page in the based page, and in the each individual pages extends the base page and overwrites specific parts of its page. So, let's see layout.html.
    fig2. layout.html01:<html xmlns:m="http://www.seasar.org/maya">
    02:<head>
    03:<meta http-equiv="Content-Type" content="text/html; charset=Windows-31j" />
    04:<link m:inject="s:link" rel="stylesheet" type="text/css" href="/css/global.css"/>
    05:<title m:value="#{layoutTitle}"/>
    06:</head>
    07:<body>
    08:<table border="0" cellspacing="5">
    09:<tr>
    10:  <td colspan="2"><span m:inject="s:insert" m:src="/WEB-INF/layout/header.html"/></td>
    11:</tr>
    12:<tr>
    13:  <td width="140" valign="top">
    14:    <span m:inject="s:insert" m:src="/WEB-INF/layout/menu.html"/>
    15:  </td>
    16:  <td valign="top" align="left">
    17:    <span m:inject="s:insert" m:name="body"/>
    18:  </td>
    19:</tr>
    20:<tr>
    21:  <td colspan="2">
    22:    <hr/>
    23:  </td>
    24:</tr>
    25:<tr>
    26: <td colspan="2">
    27:    <span m:inject="s:insert" m:src="/WEB-INF/layout/footer.html"/>
    28:  </td>
    29:</tr>
    30:</table>
    31:</body>
    32:</html>
See the link tag at line 4.By inject attribute, s:link is specifeid. How to specify this tag is same as the case of JSP. Prefix of this tas, "s", is described in WEB-INF/classes/jsf.dicon(or WEB-INF/src) In jsf.dicon, a relevant part is as follows.
    fig3. jsf.dicon(not all)<component class="org.seasar.jsf.runtime.JsfConfigImpl">
        <initMethod name="addTaglibUri">
            <arg>"h"</arg>
            <arg>"http://java.sun.com/jsf/html"</arg>
        <initMethod>
        <initMethod name="addTaglibUri">
            <arg>"f"</arg>
            <arg>"http://java.sun.com/jsf/core"</arg>
        <initMethod>
        <initMethod name="addTaglibUri">
            <arg>"s"</arg>
            <arg>"http://www.seasar.org/jsf"</arg>
        </initMethod>
    </component>
Specifing inject attribute, arbitrary HTML tags is converted to JSP tag, which is needed for JSF. Existing taglibs for JSF can be reused easily. In the line 5, title is specified. The actual value of layoutTitle should be described at extended page of this layout. In the line ten, src attribute of the insert tag inserts the page for header. The page for header is as follows.
    fig4. header.html<html xmlns:m="http://www.seasar.org/maya">
    <body>
        <span m:inject="s:insert">
            <img m:inject="h:graphicImage" m:url="/images/seasar.gif"/>
        </span>
    </body>
    </html>
In the inserted page, the content that is to be inserted in the insert tag without the name attribute is described. In other way, you can write a tag for preview outside of insert tag. In such situation, the outside of insert tag is ignored at the runtime. For next, let's see menu.html.
    fig5. menu.html<html xmlns:m="http://www.seasar.org/maya">
    ...
    <body>
        <span m:inject="s:insert">
            <form>
                <ul>
                    <li>
                        <a m:action="hello">Hello
                            <span m:inject="f:param" m:name="message" m:value="World"/>
                        </a>
                    </li>
                    <li>
                        <a m:action="add">Add</a>
                    </li>
                    ...
                </ul>
            </form>
        </span>
    </body>
    </html>
Page changing name is specified when the link is clicked by the action attribute of the anchor tag. There are two ways to use action attribute. One is to type ${parameter_name.method.name} to call JavaBeans method. The other is simply to describe string.This way is for changing the specific page. This page that is named hello is configured at WEB-INF/faces-config.xml. We are goint to see as follwing part.
    fig6. faces-config.xml<navigation-rule>
        <navigation-case>
            <from-outcome>hello</from-outcome>
            <to-view-id>/hello/hello.html</to-view-id>
            <redirect/>
        </navigation-case>
    </navigation-rule>
By using from-outcome tag, you can specify the page changing name. Actual path is spcified by to-view-id tag. If describing redirect tag, the page is redirected.If not, it is forwarded. Let's back to menu.html. The child tag of anchor should be specified f:param for giving parameter to changing page. Let's back to layout.html. At the line 17 of layout.html, <span m:inject="s:insert" m:name="body"/> defines the body part. Giving a name by name attribute like this, the page that extended this layout overwrite the contents by defining <span m:inject="s:insert" m:name="body">...,</span> again. Take a look at the line 7 of hello.html.You see <span m:inject="f:param" m:name="layoutTitle" m:value="Hello"/>. It puts the value to layoutTitle, which is defined at layout.html. To give parameters to parent page, f:param tag is put as the child of body tag. Between the line 8 to 10 of hello.html, <span m:inject="s:insert" m:name="body"> overwrite the parent page's contents. To output string to HTML, <span></span> should be used.For example, it should be like <span m:value="#{message}">hoge</span> at the line9 of hello.html. We call #{...} as ValueBinding, and we use it when value should be dynamically arranged. When defining like #{foo}, S2JSF retrieves by the order of request, parameter, session, S2Container and the first found one is set as value.For example, output should be the content of message parameter at the line 8 and 9 of figure.1, and "hoge" text of body tag, which is dummy for just checking layout, is ignored at that time. When coding like #{foo.property}, S2JSF retrieves #{foo} as we described before, and then put property. When you need dynamically changed texts at HTML, value attribute of span tag is needed in this way. ### add.html This sample shows you these folows: how input value works with JavaBean property. how to call JavaBeans' method when button is clicked. how to auto-bind an object of request, session, S2Container in a way of coding setter method at Action Let's see add.html.
    fig07.add.html01:<html xmlns:m="http://www.seasar.org/maya" m:extends="/WEB-INF/layout/layout.html">
    02:<head>
    03:<meta http-equiv="Content-Type" content="text/html; charset=Windows-31j" />
    04:<title>Add</title>
    05:</head>
    06:<body>
    07:  <span m:inject="f:param" m:name="layoutTitle" m:value="Add"/>
    08:  <span m:inject="s:insert" m:name="body">
    09:    <form>
    10:      <span m:inject="h:messages" m:globalOnly="false" m:showDetail="true"/>
    11:      <input type="text" m:value="#{addDto.arg1}"/> +
    12:      <input type="text" m:value="#{addDto.arg2}"/> =
    13:      <span m:value="#{addDto.result}"/>
    14:      <input type="submit" value="calculate" m:action="#{addAction.calculate}"/>
    15:    </form>
    16:  </span>
    17:</body>
    18:</html>
Head tag is ignored when runtime.It is only for preview on browser. <span m:inject="h:messages" m:globalOnly="false" m:showDetail="true"/> at the line.10, it is a preparation for output messages when occuring errors. While globalOnly attribute is true, only global error message, which is not specific input related, should be displayed.In other way, all error messages are out when globalOnly attribute is false. <input type="text" m:value="#{addDto.arg1}"/> at line 11 means that input/output tag works with JavaBeans property. Input value is stored to JavaBeans property if validation is OK. If NG, input value remains the page.Such input/output well-management is the benefit of using JSF. With Struts, we need to use String type to store value tempolary at ActionForm. With JSF, we don't need to do this. Where do we describe addDto?addDto is described in examples/jsf/dicon/add.dicon as follows:
    fig08.add.dicon(partial)<component name="addDto" class="examples.jsf.dto.AddDto" instance="request"/>
addDto is managed in request scope if instance attribute of component tag is true as wee see in add.dicon. And add.dicon is included by app.dicon, which is the parent configuration file.
    fig09.app.dicon(partial)<include path="examples/jsf/dicon/add.dicon"/>
Back to fig07, add.html, <input type="submit" value="calculate" m:action="#{addAction.calculate}"/> at line14 works as calling JavaBeans method(addAction.calculate) when button is clicked. These features, such as describing as #{varname.methodname} at action attribute of button or link tag, are called MethodBinding. Methods called by MethodBinding should not have arguments and it's return value should be String. So, where addAction at line14 is defined? addAction defines at add.dicon as follows.
    fig10.add.dicon(partial)<component name="addAction" class="examples.jsf.action.impl.AddActionImpl" instance="request"/>
Actionクラスは、入力された内容をプロパティ経由で受け取ることになるので、instance属性をrequestにします。それでは、 AddActionインターフェース、AddActionImplクラスを見てみましょう｡インターフェースと実装を必ず分離しなければならないというこ とはないのですが、このように分離したほうが、仕様が明確に伝わり易いと思います｡
    package examples.jsf.action;

    public interface AddAction {

        public String calculate();
    }
    package examples.jsf.action.impl;

    import examples.jsf.action.AddAction;
    import examples.jsf.dto.AddDto;
    import examples.jsf.logic.AddLogic;

    public class AddActionImpl implements AddAction {

        private AddDto addDto;
        private AddLogic addLogic;

        public void setAddDto(AddDto addDto) {
            this.addDto = addDto;
        }

        public void setAddLogic(AddLogic addLogic) {
            this.addLogic = addLogic;
        }

        public String calculate() {
            int result = addLogic.calculate(addDto);
            addDto.setResult(result);
            return null;
        }
    }
入力された値を受け取るために、addDtoというプロパティのsetterメソッドを定義しています｡S2JSFは、MethodBinding で指定したメソッドを呼び出す直前にsetterメソッドの定義されているプロパティがないか調べ、もしある場合は、プロパティ名と同様の変数が、リクエ ストの属性、パラメータ、セッションの属性、S2Containerに存在するか調べ、もし存在する場合には、自動的にsetterメソッドを呼び出し、 その変数を設定します｡ addLogicという変数は、どこにも定義されていないのですが、プロパティの型がインターフェースの場合、S2Containerによって、そ のインターフェースを実装したクラスが自動的に設定されます｡AddLogicを実装したクラスは、add.diconで次のように定義されています｡
    <component class="examples.jsf.logic.impl.AddLogicImpl"/>
MethodBindingで呼び出したメソッドの戻り値がnullの場合は、自分自身に遷移することになります｡ ### forEachList.html このサンプルでは、次のことを学びます｡ forEachタグによる繰り返し。 anchorタグでプレビュー時にページ遷移させる方法。 buttonrタグでプレビュー時にページ遷移させる方法。 それでは、HTMLの一部を見てみましょう｡
    01:<form>
    02:    <table border="1">
    03:        <tr bgcolor="#7777FF">
    04:            <th>Key</th>
    05:            <th>Name</th>
    06:            <th colspan="2">to ResultPage</th>
    07:        </tr>
    08:        <span m:inject="s:forEach" m:items="#{forEachDtoList}"
    09:            m:var="e" m:varIndex="i">
    10:        <tr>
    11:            <td><span m:value="#{e.key}">111</span></td>
    12:            <td><span m:value="#{e.name}">aaa</span></td>
    13:            <td><a href="forEachResult.html" m:action="forEachResult">to ResultPage
    14:                    <span m:inject="f:param" m:name="index" m:value="#{i}"/>
    15:                </a>
    16:            </td>
    17:            <td>
    18:                <input type="button" m:action="forEachResult" value="to ResultPage"
    19:                    onclick="location.href='forEachResult.html'">
    20:                    <span m:inject="f:param" m:name="index" m:value="#{i}"/>
    21:                </input>
    22:            </td>
    23:        </tr>
    24:        </span>
    25:    </table>
    26:</form>
8行目のforEachタグで繰り返しを指定します｡items属性で繰り返す対象を、var属性で繰り返す際に個々の要素にアクセスするときの名前を、varIndex属性で繰り返す際にインデックスにアクセスするときの名前を指定します｡ 11行目のようにvar属性でつけた名前.プロパティという形でアクセスすることが出来ます｡ 13行目のanchorタグでhref属性とaction属性を両方指定しています｡このように両方指定した場合、hrefは実行時には無視されま す｡ブラウザで直接プレビューしたときに、ページを遷移させるために記述しているのです｡子タグのparamタグでページ遷移のときのパラメータを指定す ることができます｡ 18行目のbuttonタグもaction属性とonclick属性を指定しています｡onclick属性のlocation.href= 'forEachResult.html'の部分は実行時には無視されます｡ブラウザで直接プレビューしたときに、ページを遷移させるために記述している のです｡子タグのparamタグでページ遷移のときのパラメータを指定することができます｡ ### forEachResult.html このサンプルでは、次のことを学びます｡ ページの初期処理。 Actionにgetterメソッドを定義してプロパティをリクエストやセッションに自動設定する方法。 それでは、HTMLを見てみましょう｡
    01:<html xmlns:m="http://www.seasar.org/maya"
    02:    m:action="#{forEachResultInitAction.initialize}"
    03:    m:extends="/WEB-INF/layout/layout.html">
    04:<head>
    05:<meta http-equiv="Content-Type" content="text/html; charset=Windows-31j" />
    06:<title>ForEach</title>
    07:</head>
    08:<body>
    09:<span m:inject="f:param" m:name="layoutTitle" m:value="ForEach"/>
    10:<span m:inject="s:insert" m:name="body">
    11:     Key:<span m:value="#{forEachDto.key}">111</span>
    12:     Name:<span m:value="#{forEachDto.name}">aaa</span><br />
    13:     <a href="forEachList.html">previous</a>
    14:</span>
    15:</body>
    16:</html>
2行目のhtmlタグのaction属性で、ページを初期化するメソッドを指定しています｡それでは、Actionクラスを見てみましょう｡
    package examples.jsf.action.impl;

    import java.util.List;

    import examples.jsf.action.ForEachResultInitAction;
    import examples.jsf.dto.ForEachDto;

    public class ForEachResultInitActionImpl implements ForEachResultInitAction {

        private int index;

        private List forEachDtoList;

        private ForEachDto forEachDto;

        public void setIndex(int index) {
            this.index = index;
        }

        public void setForEachDtoList(List forEachDtoList) {
            this.forEachDtoList = forEachDtoList;
        }

        public ForEachDto getForEachDto() {
            return forEachDto;
        }

        public String initialize() {
            forEachDto = (ForEachDto) forEachDtoList.get(index);
            return null;
        }
    }
前のページで、anchorタグやbuttonタグのパラメータでindexを渡していたことを思い出してください｡setIndex()メソッド を定義しておけば、S2JSFが自動的にパラメータの値を設定してくれます｡また、setForEachDtoList()メソッドを定義しておくこと で、examples/jsf/dicon/foreach.diconに定義されているforEachDtoListを参照できます｡ initMethodタグを使えば、任意のメソッドを呼び出せるので、自由自在にオブジェクトを組み立てることが出来ます｡
    <component name="forEachDtoList" class="java.util.ArrayList" instance="session">
        <initMethod name="add" >
            <arg>
                <component class="examples.jsf.dto.ForEachDto" >
                    <property name="key">"111"</property>
                    <property name="name">"aaa"</property>
                </component>
            </arg>
        </initMethod>
        <initMethod name="add" >
            <arg>
                <component class="examples.jsf.dto.ForEachDto" >
                    <property name="key">"222"</property>
                    <property name="name">"bbb"</property>
                </component>
            </arg>
        </initMethod>
    </component>
initialize()メソッドで指定されたインデックスに基づくオブジェクトをforEachDtoプロパティに設定しています｡ forEachDtoプロパティには、getterメソッドが定義されているので、initialize()メソッドが実行された後、S2JSFによっ て、forEachDtoプロパティの値が自動的にリクエストの属性(forEachDto)に設定されます｡public static final String プロパティ名_EXPORT = "session";のように定数を宣言することで、リクエストではなくセッションの属性に設定することも出来ます｡ |
| © Copyright The Seasar Foundation and the others 2004, all rights reserved. |