-Tapestryサービス(4)
サービスコンテキストとサービスパラメータを利用して、画面遷移間の情報送信がカスタマイズできることを説明しました。今日はケーススタディとして、サービスパラメータ付のPageLink/PageServiceを作ってみることにしましょう。同時に、Tapestryのページの状態保全についての考察も行っていきます。まず作成するのは、PageServiceのパラメータ付サービスである、ValuePageServiceと、そのサービスへのリンクをレンダリングするValuePageLinkコンポーネントです。実装自体はシンプルな内容です。サービスを作成するのに、AbstractServiceを継承すると、サービス実装に有用なユーティリティメソッドが用意されているので便利です。
サービスの実装-ValuePageService package sample.valuepagelink; import java.io.IOException; import javax.servlet.ServletException; import org.apache.commons.beanutils.PropertyUtils; import org.apache.tapestry.IComponent; import org.apache.tapestry.IPage; import org.apache.tapestry.IRequestCycle; import org.apache.tapestry.engine.AbstractService; import org.apache.tapestry.engine.IEngineServiceView; import org.apache.tapestry.engine.ILink; import org.apache.tapestry.request.ResponseOutputStream; public class ValuePageService extends AbstractService { public static final String SERVICE_NAME = "valuePage"; public String getName() { return SERVICE_NAME; } public ILink getLink(IRequestCycle cycle, IComponent component, Object parameters) { String context = new String { (String)parameters[0], (String)parameters[1] }; Object values = new Object { parameters[2] }; return constructLink(cycle, SERVICE_NAME, context, values, true); } public void service(IEngineServiceView engine, IRequestCycle cycle, ResponseOutputStream output) throws ServletException, IOException { String context = getServiceContext(cycle.getRequestContext()); Object[] parameters = getParameters(cycle); cycle.activate(context[0]); IPage page = cycle.getPage(context[0]); setPropertyValue(page, context[1], parameters[0]); engine.renderResponse(cycle, output); } private void setPropertyValue(IPage page, String name, Object value) { try { PropertyUtils.setProperty(page, name, value); } catch (Exception e) { throw new ServletException(e); } } }
HTMLリンクが書かれるページにてgetLink()が用いられ、HTMLリンクのクリックによるリクエストに対応するのがservice()です。getLink()は以下のコンポーネントが描画されるときに用いられます。
サービスへのリンクコンポーネントの実装-valuePageLink package sample.valuepagelink; import org.apache.tapestry.IRequestCycle; import org.apache.tapestry.engine.ILink; import org.apache.tapestry.link.AbstractLinkComponent; public abstract class ValuePageLink extends AbstractLinkComponent { public abstract String getTargetPage(); public abstract String getPropertyName(); public abstract Object getPropertyValue(); public ILink getLink(IRequestCycle cycle) { Object[] parameter = new Object[3]; parameter[0] = getTargetPage(); parameter[1] = getPropertyName(); parameter[2] = getPropertyValue(); return getLink(cycle, ValuePageService.SERVICE_NAME, parameter); } }
リンクコンポーネントはその中核の内容をサービスに委譲していますのでとても簡素なつくりとなります。こちらも、AbstractLinkComponentを継承することによって、リンク生成をサービス側に委譲するgetLink(IRequestCycle,String,Object[])メソッドが利用できます。
コンポーネントスペックXML-ValuePageLink.jwc <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE component-specification PUBLIC "-//Apache Software Foundation//Tapestry Specification 3.0//EN" "http://jakarta.apache.org/tapestry/dtd/Tapestry_3_0.dtd"> <component-specification class="sample.valuepagelink.ValuePageLink" allow-body="yes" allow-informal-parameters="yes"> <parameter name="page" type="java.lang.String" required="yes" property-name="targetPage" direction="in"/> <parameter name="name" type="java.lang.String" required="yes" property-name="propertyName" direction="in"/> <parameter name="value" type="java.lang.Object" required="yes" property-name="propertyValue" direction="in"/> <parameter name="disabled" type="boolean" direction="in"/> <parameter name="anchor" type="java.lang.String" direction="in"/> <parameter name="renderer" type="org.apache.tapestry.link.ILinkRenderer" direction="in"/> <reserved-parameter name="href"/> </component-specification>
さらには、アプリケーションスペックXMLにサービスを登録します。
各アプリケーションスペックXML(.application)に記述する内容 <service name="valuePage" class="sample.valuepagelink.ValuePageService"/>
この、<service>エレメントのname属性には、リンクやサービスで用いている文字列を登録します。すなわち、ValuePageService.SERVICE_NAMEの値、「valuePage」となります。では、続いてこのサービスとコンポーネントを用いたサンプルアプリケーションを示します。