[mayaa-user:878] Re: JavaBeanのプロパティへのアクセスについて(要望)

suga [E-MAIL ADDRESS DELETED]
2010年 1月 6日 (水) 21:57:37 JST


suga です。

2010/1/6 しましま <[E-MAIL ADDRESS DELETED]>:
> こんばんは、しましまです。
> いろいろ説明不足なところがあって申し訳ありません。
> で、その後調べを進めた結果新たに分かった事もあるので、合わせて説明します。
>
> まず、不具合が発生する条件は、Scala形式のgetterが実装されていることのようです。
> public class MyBean {
>     private String name = "hoge";
>     public String name() { return name; }
> }
> このように、フィールドがprivateで、フィールドと同じ名前のpublicなメソッドが実装されていた場合、これをmayaaから
> <m:write m:id="boke" value="${bean.name}"/>
> このようにしてアクセスすると、
>
> function name() {/*<br />java.lang.String name()<br />*/}<br />
>
> 上記のように、JavaScriptの断片のような文字列が返ってきます。
> また、条件によっては、ただの空文字になることもある見たいです。
> この場合、Java形式のgetterがあっても、無視されるようです。
> また、Scala形式のgetterがあっても、フィールドがpublicなら、問題は発生しません。

これは Rhino の仕様で、bean.name は name というメソッドそのものを指します。
bean.name() とすればメソッドが実行されて結果が返るでしょう。

要素を見る順が public フィールド→メソッド→アクセサ となるので、
public * name があればこれを、
次に name() があればこれを、
最後に getName() があればこれを name と見なして返します。

これは特別に扱うもの以外を Rhino 任せるため、現状の Mayaa の実装の仕様でもあります。


> このように、scalaのクラスは、必ずscala.ScalaObjectをimplementsしています。

すみません、ちょっと思慮が足りませんでしたが、Mayaa 本体が scala に依存することは
避けたいので、次の対応を試してみてください。

org.seasar.mayaa.impl.cycle.script.rhino.WrapFactoryImpl を参考にして
* Scala対応の WrapFactory を作る
  * 中で使われている org.seasar.mayaa.impl.cycle.script.rhino.NativeDynaBean と同様に
    NativeScalaObject を作る
    org.mozilla.javascript.NativeJavaObject や
    org.seasar.mayaa.impl.cycle.script.rhino.NativeAttributeScope なども参考に。
  * scala.ScalaObject を実装したクラスであれば NativeScalaObject でラップして返すようにする
* org.seasar.mayaa.provider.ServiceProvider ファイルに次のように設定する
    <scriptEnvironment>
        <parameter name="wrapFactory" value="自作したWrapFactory"/>
    </scriptEnvironment>
    参考: http://mayaa.seasar.org/documentation/engine_settings.html


これにより、Rhino から Java のオブジェクトにアクセスする際に、自作した
NativeScalaObject 経由でアクセスする形となります。

あとは NativeScalaObject の has, get, put の実装で scala 形式のアクセサ
経由で操作するようにすれば良いでしょう。
これら3つ以外は親クラスの org.mozilla.javascript.NativeJavaObject に任せて
問題ないと思います。

Scala の実装はわからないので外から使えるものかどうかわかりませんが、
Scala 内部で利用しているクラスを使えばリフレクション周りのキャッシュなどが
楽に実装できるかもしれません。(scala.reflect.ScalaBeanInfo とか?)

-- 
suga ( [E-MAIL ADDRESS DELETED] )


mayaa-user メーリングリストの案内