JSONRpcClientを作ってみた。
Tapestryとのコンボをやってみた。もっとうまい方法があるかも知れんけど。
使い方はこんな感じで。
<script jwcid="@brownie:JSONRpcClient" registerObjects="ognl: jsonObjects" />
registerObjectsは、クライアント側からアクセスするサーバー側のオブジェクトと名前のMapオブジェクトを指定します(名前がkeyでオブジェクトがvalueね)。
んで、例えば何かのボタンが押されたときにサーバー側にメッセージを送るとすると、
<script language="JavaScript" > function onclick_btnGetXXXXXX( btn ) { var key = document.Form0.field_key.value; var value = jsonrpc.serverObjeName.getXXXXXX( key ); document.Form0.field_value.value = value } </script>
この場合、上のJSONRpcClientのregisterObjectsには、getXXXXXメソッドを持つオブジェクトをkeyを"serverObjeName"としてMapにputする必要があります。
で実装の方はどうなっているかってーと、component-specificationはこんな感じ。
<?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="org.asyrinx.brownie.tapestry.components.jsonrpc.JSONRpcClient" allow-body="no" allow-informal-parameters="no"> <description> JSON-RPC-Java client component </description> <parameter name="servletMappingUrl" type="java.lang.String" direction="in" default-value='"/JSON-RPC"'> <description>the mapping URL for JSONRPCServlet</description> </parameter> <parameter name="clientName" type="java.lang.String" direction="in" default-value='"jsonrpc"'> <description>variable name of JSONRpcClient object in JavaScript</description> </parameter> <parameter name="registerObjects" type="java.util.Map" direction="in" required="yes"/> </component-specification>
登録したオブジェクトをJavaScript側から使うための名前は、Mapで指定するregisterObjectsのkeyが使われます。
んで、本体のJavaクラス。
package org.asyrinx.brownie.tapestry.components.jsonrpc; import java.util.Iterator; import java.util.Map; import org.apache.tapestry.AbstractComponent; import org.apache.tapestry.IMarkupWriter; import org.apache.tapestry.IRequestCycle; import org.asyrinx.brownie.tapestry.script.IScriptUser; import org.asyrinx.brownie.tapestry.script.ScriptUsage; import org.asyrinx.brownie.tapestry.script.ScriptWriter; import org.asyrinx.brownie.tapestry.util.Scope; import com.metaparadigm.jsonrpc.JSONRPCBridge; /** * @author takeshi */ public abstract class JSONRpcClient extends AbstractComponent implements IScriptUser { private final ScriptWriter scriptWriter; public JSONRpcClient() { super(); this.scriptWriter = new ScriptWriter(this, "JSONRpcClient.script"); this.scriptWriter.setUsage(ScriptUsage.ONCE_BY_OBJECT); } public void prepareScriptSymbols(Map symbols, IRequestCycle cycle) { symbols.put("clientName", getClientName()); symbols.put("contextPath", cycle.getRequestContext().getRequest() .getContextPath()); symbols.put("servletMappingUrl", getServletMappingUrl()); } protected void renderComponent(IMarkupWriter writer, IRequestCycle cycle) { if (cycle.isRewinding()) return; prepareBridge(cycle); scriptWriter.execute(cycle); } private static final String KEY_BRIDGE_ON_SESSION = "JSONRPCBridge"; protected JSONRPCBridge prepareBridge(IRequestCycle cycle) { //final String key = this.getClass().getName() + "." + getClientName(); final String key = KEY_BRIDGE_ON_SESSION; JSONRPCBridge result = (JSONRPCBridge) getScopeObject().getAttribute( cycle, key); if (result == null) { result = new JSONRPCBridge(); getScopeObject().setAttribute(cycle, key, result); } for (Iterator i = getRegisterObjects().entrySet().iterator(); i .hasNext();) { final Map.Entry entry = (Map.Entry) i.next(); result.registerObject(entry.getKey(), entry.getValue()); } return result; } private Scope getScopeObject() { return Scope.SESSION; } public abstract String getServletMappingUrl(); /** * request, session, application * * @return */ //public abstract String getScope(); public abstract Map getRegisterObjects(); public abstract String getClientName(); }
JSONRPCBridgeオブジェクトに登録するときには、sessionを使うしかないのね。それで問題はないんだけど、applicationで登録できてもいいなーと思ったり。
<?xml version="1.0"?> <!-- $Id: DateValidator.script,v 1.3 2003/06/01 05:05:12 hlship Exp $ --> <!DOCTYPE script PUBLIC "-//Apache Software Foundation//Tapestry Script Specification 3.0//EN" "http://jakarta.apache.org/tapestry/dtd/Script_3_0.dtd"> <script> <include-script resource-path="/org/asyrinx/brownie/tapestry/components/jsonrpc/jsonrpc.js"/> <input-symbol key="clientName" class="java.lang.String" required="yes"/> <input-symbol key="contextPath" class="java.lang.String" required="yes"/> <input-symbol key="servletMappingUrl" class="java.lang.String" required="yes"/> <body> var ${clientName} = null; </body> <initialization> ${clientName} = new JSONRpcClient("${contextPath}${servletMappingUrl}"); </initialization> </script>
JavaScript側で使うJSONRpcClientオブジェクトを生成するだけです。
jsonrpc.jsもコピーしておく必要があります。
この実装はbrownie-tapestry-1.2.0でリリースする予定です。