サービスパラメータは、とても強力な仕組みです。HTTPリクエストパラメータに似て、URL中に埋め込まれる文字列を介してクライアントとサーバーで情報をやり取りする機能ですが、HTTPリクエストパラメータが受け渡しできる情報が文字列のみであるのに対して、サービスパラメータはオブジェクトを交換できます。
たとえば以下のようなページがあったとします。
<page-specification class="sample.serviceparam.Home"> <component id="direct" type="DirectLink"> <binding name="listener" expression="listeners.click"/> <binding name="parameters" expression="sparam"/> </component> </page-specification>
この、DirectLinkコンポーネントに設定している、"parameters"プロパティはサービスパラメータが利用されています。このプロパティはObject型ですが、基本的にList型もしくはObject配列が入ってくることを想定して作られています。サービスパラメータはObject配列を取り扱うので、DirectLinkコンポーネント内部でObjrctもしくはListの場合は、Object[]に変換して内部処理に渡しています。
対応するHTMLは以下のとおりです。
<html> <head> <title>test</title> </head> <body> <a href="#" jwcid="direct">click</a> </body> </html>
シンプルにリンクが一つあるだけです。Javaのページオブジェクトは以下のとおりです。
public class Home extends BasePage { public Object getSparam() { Object ret = new Object[2]; ret[0] = new Integer(999); Person person = new Person(); person.setName("masataka"); person.setAge(31); ret[1] = person; return ret; } public void click(IRequestCycle cycle) { Object[] params = cycle.getServiceParameters(); int value = *1; System.out.println("[1].age=" + person.getAge()); } }
getSparam()では、以下のシンプルなBeanを使ってます。
public class Person implements Serializable { private String name; private int age; public int getAge() { return age; } public String getName() { return name; } public void setAge(int age) { this.age = age; } public void setName(String name) { this.name = name ; } }
この出力ページソースは以下のとおりです。
<html> <head> <title>test</title> </head> <body> <a href="(URL+シリアライズされたパラメータ文字列。長いので後述)">click</a> </body> </html>
URL+シリアライズされたパラメータ文字列は以下のとおりです。
/app?service=direct/0/Home/direct&sp=999&sp=OH4sIAAAAAAAAAFvzloG1uIhBpDgxtyAnVa84E0wFpBYV5-cp3LoveoyjQ4CJgcmTgTkxPdWHgSUvMTe1hEHIJyuxLFE_JzEvXT-4pCgzL926ooCBgUG-hIEjN7E4sSQxOxEAnKgp81oAAAA.
見事に、IntegerとPersonがURLの一部になっています。「sp=」が二度URL中に出現していることに注意してみてください。一つ目の「sp=」に続く「999」はIntegerの値、二つ目の「sp=」の後に続くのはPersonオブジェクトのシリアライズ結果です。このように、サービスパラメータはObject配列を文字列化してリンクURLに埋め込む機能を提供しています。クリック後のサーバーの受け取りは文字列からObject配列に自動的に戻され、IRequestCycle#getServiceParameters()によって取得することができます。
この仕組みは、URLに情報をエンコードしてしまうので、完全にServletセッションを使わないで、Servletセッションと同様の機能を提供するものです。既存のコンポーネントではただそれまでの内容ですが、この機能は独自にサービスを実装する場合に活用することができます。(つづく)
*1:Integer)params[0]).intValue(); Person person = (Person)params[1]; System.out.println("[0]=" + value); System.out.println("[1].name=" + person.getName(