-Tapestryサービス(5)

作成したValuePageService/Linkの利用例を示します。まずアプリケーションスペックXMLにサービスを登録します。

アプリケーションスペックXML
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE application
  PUBLIC "-//Apache Software Foundation//Tapestry Specification 3.0//EN"
  "http://jakarta.apache.org/tapestry/dtd/Tapestry_3_0.dtd">
<application name="ValuePageLink" engine-class="org.apache.tapestry.engine.BaseEngine" >
  <page name="Home" specification-path="Home.page"/>
  <page name="Next" specification-path="Next.page"/>
  <service name="valuePage" class="sample.valuepagelink.ValuePageService"/>
</application>

ページの登録は必須ではないですが、HomeとNextの2ページを定義しています。次に、Homeページです。

HomeページスペックXML
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE page-specification
  PUBLIC "-//Apache Software Foundation//Tapestry Specification 3.0//EN"
  "http://jakarta.apache.org/tapestry/dtd/Tapestry_3_0.dtd">
<page-specification class="sample.valuepagelink.Home">
  <component id="valuePageLink" type="ValuePageLink">
    <static-binding name="page" value="Next"/>
    <static-binding name="name" value="person"/>
    <binding name="value" expression="person"/>
  </component>
</page-specification>

valuePageLinkコンポーネントのnameパラメータがstatic-bindingなのに対し、valueパラメータがbindingなのに注意してください。nameのパラメータ値は文字列で、valueのパラメータ値はプロパティ名です。

HomeページHTMLテンプレート
<html>
  <body>
    <a jwcid="valuePageLink">click!</a>
  </body>
</html>
Homeページオブジェクト
package sample.valuepagelink;
import org.apache.tapestry.html.BasePage;
public class Home extends BasePage {
  public Person getPerson() {
    return new Person("Masataka", 31);
  }
}

HomeページオブジェクトのgetPerson()の結果がvaluePageLinkコンポーネントのvalueパラメータにセットされます。これで、ValuePageLinkが生成するリンクの値が決定しました。このページの実行結果は次のとおりです。

<html>
  <body>
    <a href="/app?service=valuePage/Next/person&
      sp=OH4sIAAAAAAAAAFvzloG1uIhBujgxtyAnVa8sMac0tSAxPTUnMy9
         bLyC1qDg_796ixFsOe9mimBiYPBmYgXI-DCx5ibmpJQxCPlmJZYn
         6OYl56frBJUWZeenWFQUMDAzyJQwcvonFiSWJ2YkAru8CKWEAAAA.">
      click!
    </a>
  </body>
</html>

実際はこのようにインデントがきちんとはされませんが、見やすいように適宜改行をいれてインデントしてあります。リンクは、サービスコンテキストが「/Next/person」となり、一番目が遷移先ページ名、二番目が遷移先でサービスパラメータを設定するプロパティ名としています。「&sp=OH4sIAAAAAAAAAFv...」というのがPersonオブジェクトをシリアライズした結果です。Personオブジェクトは以下のとおりです。

サービスパラメータとするPersonオブジェクト
package sample.valuepagelink;
import java.io.Serializable;
public class Person implements Serializable {
  private String name;
  private int age;
  public Person(String name, int age) {
    this.name = name;
    this.age = age;
  }
  public String getName() {
    return name;
  }
  public int getAge() {
    return age;
  }
}

特に変わったところのないPersonオブジェクトですが、java.io.Serializableを実装しています。これは、内部のDataSqueezeと呼ばれる機構が、Serializableなオブジェクトに関してObjectOutputStream/ObjectInputStreamでリンク文字列とインスタンスとを自動的に変換する仕組みが用意されているためです。後々に、このDataSqueezeのもっと効率のよいドライバの開発についても触れることとします。
一方、遷移先のNextページは以下のとおりです。

NextページスペックXML
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE page-specification
  PUBLIC "-//Apache Software Foundation//Tapestry Specification 3.0//EN"
  "http://jakarta.apache.org/tapestry/dtd/Tapestry_3_0.dtd">
<page-specification class="sample.valuepagelink.Next">
  <component id="personName" type="Insert">
    <binding name="value" expression="personName"/>
  </component>
  <component id="personAge" type="Insert">
    <binding name="value" expression="personAge"/>
  </component>
</page-specification>
NextページHTMLテンプレート
<html>
  <body>
    <span jwcid="personName">Someone</span>
    (<span jwcid="personAge">20</span>)
  </body>
</html>
Nextページオブジェクト
package sample.valuepagelink;
import org.apache.tapestry.html.BasePage;
public class Next extends BasePage {
  private Person person;
  protected void initialize() {
    person = null;
  }
  public void setPerson(Person person) {
    this.person = person;
  }
  public String getPersonName() {
    return person != null ? person.getName() : "NG";
  }
  public int getPersonAge() {
    return person != null ? person.getAge() : -1;
  }
}

結果は以下のとおりです。

Masataka(31)

HomeページのgetPerson()から、NextページのsetPerson()へと、ページをまたがってプロパティの取得・設定を行っているところがポイントです。URLに直接情報をエンコードしているので、セッションもCookieも使っていません。