DtoにgetInstanceってメソッドを作るとS2Dxoで無限ループに

心を入れ替えたつもりがCEOから「徹夜も辞さずがんばりたまえ」とのお達しを受けて大変なことに・・・・。眠い。

で、S2Struts + Mayaa で、 とかその他

<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の中身とかで困るんだなあ。最初のやり方で都度対応した方がよさそうかなあと思った。