- S2Tapestry
- セットアップ
- 使い方

## S2Tapestry

S2Tapestryを使うと、S2とTapestryが簡単に連動するようになります。ページクラスにサービスコンポーネントが自動的に設定されるので、ページクラスの役割は適切なサービスコンポーネントを呼び出すだけになり、プレゼンテーション層とサービス層の役割分担も明確になります。

## セットアップ

S2と同様にJDK1.4以上が必要です。サンプルは、Tomcat、Tomcat Plugin、Spindleを使うことを前提にしています。あらかじめインストールして置いてください。S2TapestryVx.x.x.jarを解凍してできたs2tapestryディレクトリをEclipseのJavaプロジェクトとして丸ごとインポートしてください。.classpathを上書きするか聞かれるので、すべてはいのボタンをクリックして、すべてを取り込みます。 これで、私と全く同じ環境になります。サンプルはS2TapestryExamleVx.x.x.jarとして別途用意されているので、ダウンロードして解凍してください。Eclipseでs2tapestry-exampleという名前でJavaプロジェクトを作成します。Tomcatプロジェクトではないので気をつけてください。解凍してできたs2tapestry-exampleディレクトリを丸ごとインポートしてください。.classpathを上書きするか聞かれるので、すべてはいのボタンをクリックして、すべてを取り込みます。s2tapestry-exampleプロジェクトを右クリックしてプロパティ->Tomcatを選びます。Tomcatプロジェクトであるをチェックし、アプリケーションURIを/s2tapestry-exampleとします。これで、Tomcatを再起動して、ブラウザからhttp://localhost:8080/s2tapestry-example/appにアクセスすると足し算のサンプルを見ることができます。

## 使い方

S2Containerを起動するためにS2ContainerServletをweb.xmlに登録します。。

### web.xml

    <web-app>
        <display-name>s2tapestry-example</display-name>
        <servlet>
              <servlet-name>s2container</servlet-name>
              <servlet-class>org.seasar.framework.container.servlet.S2ContainerServlet</servlet-class>
              <load-on-startup/>
        </servlet>
        <servlet>
            <servlet-name>s2tapestry-example</servlet-name>
            <servlet-class>org.apache.tapestry.ApplicationServlet</servlet-class>
            <load-on-startup>1</load-on-startup>
        </servlet>
        <servlet-mapping>
            <servlet-name>s2container</servlet-name>
            <url-pattern>/s2container</url-pattern>
        </servlet-mapping>
        <servlet-mapping>
            <servlet-name>s2tapestry-example</servlet-name>
            <url-pattern>/app</url-pattern>
        </servlet-mapping>
    </web-app>

S2とTapestryを連動させるためには、S2用のEngineをアプリケーション仕様書に登録する必要があります。

### s2tapestry-example.application

    <application name="s2tapestry-example" engine-class="org.seasar.tapestry.S2Engine" >
        <page name="Home" specification-path="Home.page"/>
    </application>

必要なコンポーネントをコンポーネント定義に登録します。ページコンポーネントはTapestryが管理するので、登録する必要はありません。また、この定義ファイルは、アプリケーション全体の定義であるapp.diconに登録する必要があります。

### Add.dicon

    <components>
        <component name="addService" class="examples.tapestry.AddServiceImpl"/>
    </components>

### app.dicon

    <components>
        <include path="examples/tapestry/Add.dicon"/>
    </components>

サービスコンポーネントを受け取るためにページ仕様にプロパティ仕様を定義します。TapestryからS2のコンポーネントを参照するには、global.コンポーネント名、あるいは名前空間が指定されている場合には、global.名前空間.コンポーネント名で参照します。

### Home.page

    <page-specification class="examples.tapestry.Home">
        <component id="arg1" type="TextField">
            <binding name="value" expression="arg1"/>
        </component>

        <component id="arg2" type="TextField">
            <binding name="value" expression="arg2"/>
        </component>

        <property-specification name="addService"
            type="examples.tapestry.AddService">
            global.addService
        </property-specification>
    </page-specification>

### Home.html

    <form jwcid="@Form" listener="ognl:listeners.calculate">
    <input jwcid="arg1" type="text"/> +
    <input jwcid="arg2" type="text"/>
    <input type="submit" value="calculate"/>
    </form>

Pageクラスはコンポーネントを受け取るためのプロパティを定義しておきます。このクラスに対してSetterInjectionを行います。

プレゼンテーション層は、サービス層に処理を依頼し、プレゼンテーション層本来の役割に徹していることが分かると思います。

### Home.java

    package examples.tapestry;

    import org.apache.tapestry.IRequestCycle;
    import org.apache.tapestry.html.BasePage;

    public class Home extends BasePage {

        private Integer arg1_;
        private Integer arg2_;
        private AddService addService_;

        public Integer getArg1() {
            return arg1_;
        }

        public void setArg1(Integer arg1) {
            arg1_ = arg1;
        }

        public Integer getArg2() {
            return arg1_;
        }

        public void setArg2(Integer arg2) {
            arg2_ = arg2;
        }

        public AddService getAddService() {
            return addService_;
        }

        public void setAddService(AddService addService) {//SetterInjectionの対象となる
            addService_ = addService;
        }

        public void calculate(IRequestCycle cycle) {
            int result = addService_.add(arg1_.intValue(), arg2_.intValue());
            AddResult next = (AddResult) cycle.getPage("AddResult");
            next.setResult(new Integer(result));
            cycle.activate(next);
        }
    }