[Seasar-user:6820] [Teeda]Gridの幅調整スクリプトが出力されない

Asarima [E-MAIL ADDRESS DELETED]
2007年 3月 22日 (木) 20:04:18 JST


Asarimaです。

 弊社の開発メンバーが以下の記事の通り困っています。
 私のほうで何とか原因を突き止め、ソースを修正することで対処できました
(とはいえ、まだ確認中ですが)のでお知らせします。
 しかし本当にこの変更でよいのかが心配です。このような変更に問題がない
か、ご意見を頂戴したく思います。よろしくお願いします。

■[Teeda] Gridの幅を調整するするスクリプトが出力されない?
http://d.hatena.ne.jp/kazita/20070319/1174287422

【不具合の内容】

 Teeda 1.0.4を使用しています。
 複数のGridを表示する画面があるとします。
 複数のクライアントからその画面に対して同時にリクエストを実行すると、
HTMLの最後に出力されるGridの幅調整用のスクリプトが、一部出力されなか
ったり、余分に出力される不具合が発生します。

【原因の発見と対処】

 Eclipseのデバッグモードを活用しました。

1.THtmlGridRendererのencodeHtmlGridBeginメソッドに入ったところで
ブレークポイントを仕掛け、2つのクライアントから同時にリクエストを
実行します。2つのスレッドがブレークポイントで止まるので、交互に再開
していくと、不具合が確実に再現しました。

2.この状態でTBodyRendererのaddRendererListenerメソッドにブレーク
ポイントを仕掛けると、2つのスレッドで、2つ目のGridからlistenersが
同じインスタンスを指しました。

3.listenersを保持している各UIBodyのAttributesの本体である
UIComponentBaseのフィールドattributesMapが、2つのスレッドで同じ
インスタンスを指しました。

4.UIComponentBaseのrestoreAttributeMapメソッドで、2つのスレッドで
同じstateインスタンスの参照がComponentAttributeMapのコンストラクタに
渡されました。

5.TeedaStateManagerImplのrestoreComponentStateFromServerメソッド
で、2つのスレッドで同じSerializedViewインスタンスのstateがViewRootに
復元されます。

6.私は4.に着目し、stateを復元するときにstateのシャローコピーを
渡せばAttributesが同じインスタンスを指さなくなると考え、UIComponentBase
のソースを以下のように変更しました。

---
private void restoreAttributeMap(Object state) {
    if (state != null) {
//↓
//        attributesMap = new ComponentAttributesMap(this, (Map) state);
          HashMap map = new HashMap();
          map.putAll((Map)state);
          attributesMap = new ComponentAttributesMap(this, map);
//↑
    } else {
        clearAttributeMap();
    }
}
---

 これでこの問題は発生しなくなりました。

【考察】

 複数のクライアントから同じ画面に対する要求が同時に起こった場合、コン
ポーネントツリーにSerializedViewの状態が復元されるようですが、復元される
オブジェクトのうちAttributeMapについては参照がコピーされます。
 これでBODYコンポーネントのAttributeMapに対してRenderListenerが同時に
登録されると、後から登録した方で上書きされるため、上記の不具合が起こると
考えます。これはGridに限らないとも思われます。

 以上です。よろしくお願いいたします。




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