DtoにgetInstanceってメソッドを作るとS2Dxoで無限ループに
心を入れ替えたつもりがCEOから「徹夜も辞さずがんばりたまえ」とのお達しを受けて大変なことに・・・・。眠い。
<m:write id="hoge" value="${fooDto.hoge}" />
なんて値を取りたい時に、Actionクラスを経由するとS2StrutsでBeanをラップしているのでMayaa側で上手く取得出来ない事があります。
なんちゃらInitActionの中でnewしたBeanはOK、validationがらみなのかな。あと、strutsのカスタムタグだとOK。
で、これの解決方法は既にid:kanagさんに教わって、ラップする側のクラスのinstanceプロパティでラップされたBeanが取得出来るので
<m:write id="hoge" value="${fooDto.instance.hoge}" />
とやると取れるますよ、と。
但し何時もinstanceプロパティがある訳じゃないので(いつもラップされる訳じゃないので)、
<m:with id="hoge"> <m:if test="${fooDto.instance != null}"> <m:exec script="${ request.setAttribute('fooDto', fooDto.instance); }"/> </m:if> <m:write value="${fooDto.hoge}" /> </m:with>
って感じでクッションかますとOKですよ、との事で事無きを得ました。
その後同じ質問がseasar-user MLにあって、回答された方がBeanの方に
public FooDto getInstance(){ return this; }
とやって一律
<m:write id="hoge" value="${fooDto.instance.hoge}" />
で回避中と書かれていてこれはナイスだ、と。
しばらくそれでやってたんですが、S2Dxoを使った時に無限ループになりました。
Foo convert(FooDto src);
ってメソッドを定義した所、FooにあってFooDtoにないプロパティが見つかると、org.seasar.dxo.converter.impl.BeanConverterの getValue() の
for (int i = 0; i < beanDesc.getPropertyDescSize(); i++) { (中略) if (sourcePropertyDesc.getPropertyName().equalsIgnoreCase(propertyName)) { return sourcePropertyDesc.getValue(source); } }
のところで再帰的にこのgetValue()が呼ばれてる模様。
sourcePropertyDescを調べると、propertyNameが「instance」となっていて(当たり前だけど)、確かに何やらまずそうなプロパティ名ですなあと。
getInstanceメソッドが必要なのは画面Dto側な訳で、この問題はDto→Entityの変換、つまりは更新系って事になるのかな。
うーん、m:writeはあまり使わないけど、m:forEachのitemsの中身とかで困るんだなあ。最初のやり方で都度対応した方がよさそうかなあと思った。