Maya(http://maya.sandbox.seasar.org/)をWebWork2で使うMayaResultを書いてみました(バージョン=webwork2:2.1.7、maya:0.9.9)。MayaServlet使ってServletDispatcherResultとかでも良いんですが、専用のResultを使うほうがWebWork2(XWork)らしいかと。
MayaResult
xwork.xmlでlocationが指定された場合はリクエストパスを偽装してMayaが読み込むテンプレートを指定します。locationが指定されない場合はリクエストURLがそのままMayaに渡ります。
package ww2.examples.maya; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequestWrapper; import org.seasar.maya.engine.Engine; import org.seasar.maya.provider.ServiceProvider; import org.seasar.maya.provider.factory.ProviderFactory; import com.opensymphony.webwork.ServletActionContext; import com.opensymphony.webwork.dispatcher.WebWorkResultSupport; import com.opensymphony.xwork.ActionInvocation; public class MayaResult extends WebWorkResultSupport { protected void doExecute(String location, ActionInvocation actionInvocation) throws Exception { ServiceProvider provider = ProviderFactory.getServiceProvider(); if (location == null) { provider.initialize(ServletActionContext.getRequest(), ServletActionContext.getResponse()); } else { provider.initialize(new MayaResultRequest(ServletActionContext .getRequest(), location), ServletActionContext .getResponse()); } Engine engine = provider.getEngine(); engine.doService(); } public static class MayaResultRequest extends HttpServletRequestWrapper { private String location; public MayaResultRequest(HttpServletRequest request, String location) { super(request); this.location = location; } public String getPathInfo() { return location; } public String getServletPath() { return ""; } } }
web.xml
MayaServletのload-on-startupは忘れずに。
Mayaを直で呼びたい場合は*.htmlにMayaServletをマッピングして、ServletDispatcherは別のURLにマッピングする必要があります。*.htmlにマッピングしないとロケーション指定なしMayaResultの恩恵があまり受けられませんが。
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" "http://java.sun.com/dtd/web-app_2_3.dtd"> <web-app> <servlet> <servlet-name>webwork</servlet-name> <servlet-class> com.opensymphony.webwork.dispatcher.ServletDispatcher </servlet-class> <load-on-startup>1</load-on-startup> </servlet> <servlet> <servlet-name>MayaServlet</servlet-name> <servlet-class>org.seasar.maya.impl.MayaServlet</servlet-class> <load-on-startup>2</load-on-startup> </servlet> <servlet-mapping> <servlet-name>webwork</servlet-name> <url-pattern>*.html</url-pattern> </servlet-mapping> <welcome-file-list> <welcome-file>index.html</welcome-file> </welcome-file-list> </web-app>
xwork.xml
ロケーション指定ありを呼ぶと、locationパラメータで指定したテンプレート(test.html)が使用され、ロケーション指定なしを呼ぶと呼び出されたURL(ここの場合はtest.html)がテンプレートとして使用されます。
<result-types> <result-type class="ww2.examples.maya.MayaResult" name="maya"></result-type> </result-types> <!-- ロケーション指定あり --> <action name="mayaTest" class="ww2.examples.event.MayaTestAction"> <result name="success" type="maya"> <param name="location">test.html</param> </result> </action> <!-- ロケーション指定なし --> <action name="test" class="ww2.examples.event.MayaTestAction"> <result name="success" type="maya" /> </action>
以下のようにしておけば、successの時はURLで指定しているテンプレートが使用されるので、一々actionごとに書く必要がなくなります。(chainとかstreamとか別のresultを使いたい場合は個々に設定)
<global-results> <result name="success" type="maya" /> </global-results>
.htmlをWebWork2に任せられないのであれば、Mayaに渡すURLを「action名+".html"」とかに偽装するResultを作っても良いかも。
WebworkValueStackScriptResolver
ついでにValueStackから値を取得するScriptResolver
package ww2.examples.maya; import org.seasar.maya.cycle.AttributeScope; import org.seasar.maya.cycle.script.resolver.ScriptResolver; import org.seasar.maya.impl.provider.UnsupportedParameterException; import com.opensymphony.xwork.ActionContext; import com.opensymphony.xwork.util.OgnlValueStack; public class WebworkValueStackScriptResolver implements ScriptResolver { public Object getVariable(String property) { OgnlValueStack valueStack = ActionContext.getContext().getValueStack(); if (property != null) { Object value = valueStack.findValue(property.toString()); if (value != null) { return value; } } return AttributeScope.UNDEFINED; } public void setParameter(String name, String value) { throw new UnsupportedParameterException(name); } public boolean setVariable(String name, Object value) { OgnlValueStack valueStack = ActionContext.getContext().getValueStack(); valueStack.setValue(name, value); return true; } }
maya.provider
mayaのjarからmaya.providerを取ってきて、WEB-INFに置いて、以下の内容をscriptタグ内に追加すればWebworkValueStackScriptResolverが使えるようになります。
(これデフォルトのmaya.providerに設定を追加する方法は無いんでしょうか?)
<resolver class="ww2.examples.maya.WebworkValueStackScriptResolver"/>