谷本 心 in せろ部屋 このページをアンテナに追加 RSSフィード

2008-03-02

[][]dump.jsとdebug.jsのメモ

Mayaa + S2Strutsで開発していると、

リクエストのたびに、コンソールにリクエストダンプが出るんだけど

誰がダンプを出してるのか、なかなか分からず時間を費やしてしまった・・・のでメモ。


リクエストをダンプしてるのは、dump.js

それを止めるには、debug.jsのdebugをfalseにすること。

S2Strutsのサンプルに最初から入っていて、trueになっているので要注意。

2007-12-26

[]publicフィールド

S2Struts1.3.0-RC2と、S2Container2.4.19の組み合わせで

publicフィールドを試してみた。


この組み合わせでバインドする/しないは以下の通り。

  • ○ : ActionにService
  • ○ : ActionにHttpServletRequest
  • × : ActionにActionForm
  • × : Actionにクエリ文字列のパラメータ
  • ○ : ActionにDxo
  • ○ : ServiceにDxo
  • ○ : ServiceにDao
  • × : ActionFormのフィールド

予想通りの挙動でした。


Action絡みの所は、どうしてもprivate + setter/getterにせざるを得ず、

現時点では、全体をpublicフィールドで統一することは、出来ないようですね。


S2Struts自身がpublicフィールドに対応すれば、

×の所も○になるのでしょうけど、さすがにもうちょっと先になるかな?

2007-12-12

[]Map-backed ActionFormの扱い

StrutsのActionFormは、

Map-backed ActionForm(マップバックドアクションフォーム)とか、

List-backed ActionForm(リストバックドアクションフォーム)とか使えて便利。


http://struts.apache.org/1.3.8/userGuide/building_controller.html#map_action_form_classes

使い方なんかは公式のドキュメントを参照。


で、S2Strutsで、このMap-backed ActionFormを使う場合、

JSP側の記述は、ドキュメント通り

<html:text property="xxx(yyy)" />

という記述でOKだけど、

ActionForm側の記述はドキュメント通りにいかない。

public String getXxx(String key)
{
    return xxxMap.get(key);
}

public void setXxx(String key, String value)
{
    return xxxMap.put(key, value);
}

という形式はダメで

public String getXxx()
{
    return xxxMap;
}

にしないと、値が入らない(というかエラーになる)。

少なくとも、S2Struts-1.3.0-RC1ではそういう状況みたい。

[]ActionにMapは自動バインドされない。

S2StrutsのMap-backed ActionForm絡みでもうひとつ。


クエリ文字列に xxx=yyy という記述を含めておいて、

Action側に setXxx(String str) メソッドを作っておけば

自動的に値がバインドされる。これは便利。


でも、クエリ文字列に xxx(yyy)=zzz という記述を含めて

Action側にsetterやgetterを作っても、値はバインドされない。残念。


これができたら、簡単にMapを画面間で持ちませそうなんですけどね。

(もちろん、いっそうのセキュリティチェックは必要ですが)


たとえば、検索条件をMapに入れておいて、

ページングのリンクにMapをクエリ文字列として入れておく、

みたいな用途に使えるかな、と思いました。


今のところ、

  1. [JSP] 検索条件入力画面で検索条件を入力させる
  2. [Action] 検索条件をMap-backed ActionFormを利用して、ActionFormに保持
  3. [InitAction] 検索実行
  4. [InitAction] 検索条件を、Mapにコピーして(キーを少し変えて)リクエストに保持
  5. [JSP] リンクのクエリ文字列にMapを展開
  6. [JSP] リンクはaction属性を指定して、Action呼び出しを行う
  7. [Action] 自前でリクエストから値を取り出してホゲホゲ

のように対応しています。


もしActionでMapが受けられるようになれば

  1. [JSP] 検索条件入力画面で検索条件を入力させる
  2. [InitAction] 検索条件をMapで受ける
  3. [InitAction] 検索実行
  4. [JSP] リンクのクエリ文字列にMapを展開
  5. [InitAction] 検索条件をMapで受ける

と、少し簡略化できるかな、と思います。


もちろん、

クエリ文字列で渡ってきた値は、

文字列としてリクエストオブジェクトに保持されてるだけで

Mapとして保持されているわけではないのですから、

現状の仕様(実装)でやむなし、とは思いますけどね。

2007-05-24

[]ActionFormの初期化方法

最近使っているのは、S2Struts1.3系。


今まで長らくS2JSFを使ってきたので、

S2StrutsのActionForm辺りの扱いに、ちょっと戸惑ってます。


一番困ったのが、ActionFormに初期値を入れたい場合。


リンクやリダイレクトでHTMLに飛んできた場合、

<s2struts:init>タグで、InitAction#initializeを呼び出しても

InitActionにはActionFormがバインドされません(よね?)


# もちろん、前ページのActionでActionFormを作っておいて、

# フォワードで飛んでくれば、問題なくバインドされますが。


ActionFormのクラス名前をXxxDtoとして、

AutoRegisterでS2コンテナに登録しておけば

InitActionにDtoはバインドされますが、ここでDtoに値を設定しても

描画されるHTMLには反映されませんでした。


どうやら、画面描画時には

改めてActionFormとしてDtoのインスタンスが作り直される模様。


どうしようもないのかなー、と思ったのですが、

苦肉の策で、こんな事をしてみました。


まずはMayaa側。

<m:doRender id="appBody" name="content">
	<s2struts:init action="#{xxxEditAction.initialize}" />
	<m:doBody/>
</m:doRender>

<html:form m:id="xxxForm" action="/xxxEdit" method="POST">
	<m:exec script="${ xxxEditAction.initForm(xxxForm.instance); }" />
	<html:hidden name="xxxForm" property="xxxId" />
	<s2struts:page />
	<m:doBody/>
</html:form>

このように、initializeとformの初期化メソッドを分けて記述します。


そしてAction側。

public void initialize()
{
	// 初期化処理
}

public void initForm(XxxForm xxxForm)
{
	xxxForm.setXxxId(111);
}

こちらも、それぞれメソッドを作っておきます。


こうすれば、一応、初期化に成功して、

HTML側に <input type="hidden" name="xxxId" value="111"> が書き出されました。


# もちろん実際は、initFormの中で、初期化が必要な状況かどうかの

# 判定をしてから、値の代入を行いますが。


でも、ホントにこんな風に書かなきゃいけないのでしょうか?

何か記述ミスがあって、initializeのタイミングでActionFormが

バインドされないだけじゃないかなー、とも思っています。


どなたか、もっとスッキリと書ける方法があれば、教えてください m(_ _)m


2007/5/28追記
InitActionクラスにActionFormのsetter/getterを書いておいて、
initializeメソッドの中でActionFormがnullならnewして初期化処理を行なう、
という方法を教えて頂きました。

Actionのgetterを記述しておくと、
 1. ActionFormの場合は、ActionFormとしてStrutsがに管理される。
 2. ActionFormでない場合は、適宜、request/sessionに保持される。
という処理になるようです。

kanagさん、ありがとうございました。

2007-05-06

[]リスト入力画面を作る方法

連休は、家族サービスとか、後輩の教育とかしつつ、

S2StrutsでWebアプリ作成。

いやー、実はWebアプリを作るのは久々で、割とはまる (^^;


さて、FAQの一つだと思うんですが、

テーブル内にテキストボックスを並べて、

リスト入力する (Listで値を受け取る) ような画面の作り方。

ググってもうまく見つけられなかったので、メモ代わりに残しておきます。


最初は <logic:iterate> と <html:text indexed="true"> で作ったんですが

これだと、HTMLテンプレートに書いたタグを、

Mayaaファイル側で丸々上書きしてしまうので、よろしくない。

2007/5/9追記
ボディの解釈の仕方を勘違いしていました。
Mayaaファイル側でタグを記述しても、Mayaaファイル側のタグにボディ部分を記述しなければ
HTMLテンプレートに書いたタグのボディ部分は有効になります。

例えば、HTMLテンプレート側にデザイン改修が入って

class属性が書き換わったら、Mayaaファイルの書き換えも必要になります。

それでは美しくないので、m:forで出来ないか試してみました。


xxxFormが、xxxListという可変のリストを属性として持っていて、

その値 (value属性) をリストで受け取るという例で作りました。


HTMLテンプレートの記述

<tbody id="xxxList">
	<tr>
		<td class="label">○○○</td>
		<td><input type="text" id="input" /></td>
	</tr>
</tbody>

Before - logic:iterateを使う場合 (Mayaaファイルの記述)

<logic:iterate m:id="xxxList" id="xxx" name="xxxForm" property="xxxList" indexId="index">
	<tr>
		<td class="label">○○○</td>
		<td><html:text indexed="true" name="xxx" property="value" /></td>
	</tr>
</logic:iterate>

After - m:forを使う場合 (Mayaaファイルの記述)

<m:for m:id="xxxList"
		init="${ var i = 0 }"
		test="${ i < xxxForm.instance.getXxxList().size() }"
		after="${ i++ }">
	<m:exec script="${ request.setAttribute(xxx, xxxForm.instance.getXxxList()); }"/>
	<m:doBody/>
</m:for>

<html:text m:id="input" property="xxx[${i}].value" />

これでOK。

propertyの中で ${} を使ってループ変数にアクセスできました。


ActionとかActionForm側の実装は、

調べればいくらでも出てくるので割愛します。


One More After - そもそもボディの解釈の仕方を誤解していました(コメント欄参照)

<logic:iterate m:id="xxxList" id="xxx" name="xxxForm" property="xxxList" />
<html:text m:id="input" name="xxx" property="value" indexed="true" />

こんな書き方で問題ありませんでした。


sugaさん、ありがとうございます。