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

Asarima [E-MAIL ADDRESS DELETED]
2007年 4月 3日 (火) 09:46:12 JST


Asarimaです。

 下記の件、どなたかお分かりになる方はいらっしゃいませんか。

 同一ページのSerializedViewからUIBodyに復元されるAttributesMapが同一
インスタンスではないか、それがUIBodyのAttributesMapの分離性を欠いてい
ないでしょうか。

 複数のGridをもつ同一ページに対し、複数クライアントから同時にリクエス
トを処理したとき、UIBodyのencodeBegin〜encodeEndまでの処理が重なると、
RenderListenerが保持するListenerの数がおかしくなることはデバッグで確認
しています。

例:3つのGridを持つページへの2つの同時リクエストを処理するスレッドA,
  Bが、UIBodyのメソッドを以下の順番で呼び出したとすると、先のリクエ
  ストに対してスクリプトが5つ、後に対して1つ出力される。
  (本来は3つずつ出力されなければならない)

 (A)encodeBegin
 (A)addRenderListener → RenderListenerの数: 1
 (B)encodeBegin
 (A)addRenderListener → RenderListenerの数: 2
 (B)addRenderListener → RenderListenerの数: 3
 (A)addRenderListener → RenderListenerの数: 4
 (B)addRenderListener → RenderListenerの数: 5
 (A)encodeEnd         → A出力 → RenderListenerの数: 0
 (B)addRenderListener → RenderListenerの数: 1
 (B)encodeEnd         → B出力

 それで、AttributeMapのシャローコピーを復元するようにしたら問題が回避
されることを確認したのですが、この変更で他の問題が発生しないでしょうか。

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

>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 メーリングリストの案内