POJOのFormをSessionスコープで利用する(再送)

またまた、チャレンジ。
今度はアドバイスをもらって、AOPとして提供することが目標。


思いつかなかったけど、いい方法だなーっと思った。
一時的にAOPでパッチを当てて、正常になったらはずす。
うーん。しっくりくる。いい感じだ。


で、どこにアスペクトするかだけど・・・
やっぱり、S2RequestProcessorかなー。
もしかしたら、publicに変更してもらわないといけないかも。
ちょっと調査


S2RequestProcessor#processActionForm()がよさそう。
しかもpublic。



テストクラスは・・・思いつかないから、作らない・・・まずいかな




ま、ちょうどs2struts-exampleをさわってたからこれを利用しよーっと。
まずは、sessionスコープに格納されていないことを確認。


・・・きちんと動く
あれ?
直接JSPを表示してるからだ。
Actionを呼んだときにsessionに格納されているPOJOのFormを再利用しない。
だから単純にJSPを表示するときでもきちんとAction経由にするとうまくいかないはず。


うむ。期待通り。やっぱりsessionからPOJOのFormを取得できてなかった。

やっと、Interceptorの作成


まずは、もしPOJOのFormだったら、特別な処理にすればOKだから、FormBeanConfigをとってくればどうにかりそう。


っていうかModuleConfigってどうやってとるんだろう。
S2RequestProcessor#processActionForm()の引数ってrequest、response、ActionMappingの3つだし。


S2RequestProcessorのフィールドとして持ってるけど、どうやれば取れるんだろう・・・


MethodInvocation#getThis()ってなんかよさそうな気が・・・
ちょっとサンプルを作って動かしてみたら、アスペクトしたメソッドのオブジェクトが取れてそう。ちょっと勉強になった。
これでどうにかなりそう。

public class POJOFormInterceptor extends AbstractInterceptor {

	public Object invoke(MethodInvocation invocation) throws Throwable {
		ActionMapping mapping = getMapping(invocation);
		ModuleConfig moduleConfig = getModuleConfig(invocation);

		if (isPojoForm(mapping, moduleConfig)) {
			HttpServletRequest request = getRequest(invocation);
			ActionServlet servlet = getServlet(invocation);
			return createPojoForm(request, mapping, moduleConfig, servlet);
		} else {
			return invocation.proceed();
		}
	}

	private boolean isPojoForm(ActionMapping mapping, ModuleConfig moduleConfig)
			throws Throwable {

		FormBeanConfig formConfig = moduleConfig.findFormBeanConfig(mapping
				.getName());
		Class fromClass = RequestUtils.applicationClass(formConfig.getType());

		return !ActionForm.class.isAssignableFrom(fromClass);
	}

	private ActionForm createPojoForm(HttpServletRequest request,
			ActionMapping mapping, ModuleConfig moduleConfig,
			ActionServlet servlet) {

		String attribute = mapping.getAttribute();
		if (attribute == null) {
			return (null);
		}

		String name = mapping.getName();
		FormBeanConfig config = moduleConfig.findFormBeanConfig(name);
		if (config == null) {
			return (null);
		}

		ActionForm instance = lookupPojoForm(request, attribute, mapping
				.getScope());

		if (instance != null) {
			return (instance);
		}

		return RequestUtils.createActionForm(config, servlet);
	}

	private ActionForm lookupPojoForm(HttpServletRequest request,
			String attribute, String scope) {
		ActionForm instance = null;
		HttpSession session = null;
		if ("request".equals(scope)) {
			instance = (ActionForm) request.getAttribute(attribute);
		} else {
			session = request.getSession();
			instance = (ActionForm) session.getAttribute(attribute);
		}

		return (instance);
	}

	//
	//
	//

	private HttpServletRequest getRequest(MethodInvocation invocation) {
		return (HttpServletRequest) invocation.getArguments()[0];
	}

	private HttpServletResponse getResponse(MethodInvocation invocation) {
		return (HttpServletResponse) invocation.getArguments()[1];
	}

	private ActionMapping getMapping(MethodInvocation invocation) {
		return (ActionMapping) invocation.getArguments()[2];
	}

	private ModuleConfig getModuleConfig(MethodInvocation invocation) {
		S2RequestProcessor processor = (S2RequestProcessor) invocation
				.getThis();
		return processor.getModuleConfig();
	}

	private ActionServlet getServlet(MethodInvocation invocation) {
		S2RequestProcessor processor = (S2RequestProcessor) invocation
				.getThis();
		return processor.getActionServlet();
	}

}

こんな感じになった。


これでs2struts-exampleのs2struts.diconを修正してTomcat起動。
そして確認。


ダメだ。
アスペクトできてない?もしかして。
うーん。printlnデバッグをしてみるか・・・


やっぱりダメだ。


困った。
って思ったら、RequestProcessor.diconってのがあった!!
そういえば、コンソールに処理時間が出力されてて不思議に思ってたんだよねー


RequestProcessor.diconを修正してTomcat起動。
うまくいった。

これでOKかな。