[ 
https://issues.jboss.org/browse/RF-13703?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
 ]

Brian Leathem updated RF-13703:
-------------------------------

    Description: 
I am encountering a reentrancy problem with nested UIDataAdaptor components. 
For instance something like :

{code}
<rich:dataTable id="outer" ...>
    <rich:dataTable id="inner" ...>
        <h:inputText id="myText" ...>
    </rich:dataTable>
</rich:dataTable>
{code}

When a view contains nested UIDataAdaptor components, each UIDataAdaptor 
component has its own internal store for saving the saved state of child 
components (saveChildState/restoreChildState). Since "inputText" is included in 
both tables, each one may save and restore the value of the component in its 
internal store.

For instance, when "outer" is on key 0 and inner is on key "2", both "outer" 
and "inner" may store the state values for myText "outer:0:inner:2:myText" in 
their "childState" property.

I guess that most of the time, only "inner" will actually store useful values, 
because most of calls on "setRowKey" for outer will be done when "inner" has 
its rowkey set to null. Unfortunately, this is not always the case.
For instance, if I decide to visit the component tree while processing an event 
for "myText", outer will perform a setRowKey while inner has its own rowKey to 
a significant value (for instance, 2), the result being that inner's value will 
be erased by 
outer's.

To try and explain with a little more detail... Let's say that we are 
processing an event on "outer:1:inner:0:myText", and we start a (nested) visit 
of the tree :
1) "outer" will at some point perform a setRowKey(0)
2) It will then do a restoreChildState for myText. since "inner" has rowKey set 
to 0, it will restore "outer's" value for "outer:0:inner:0:myText".
3) A bit later on during the visit, inner will do "setRowKey(0)". It will first 
save the current value for "outer:0:inner:0:myText" (which comes from outer's 
backup of it, restored on step 2)

The result of this process is that "outer"'s backup of "outer:0:inner:0:myText" 
overwrites "inner"'s backup for it. This is problematic because this leads, 
sometimes, to an old and obsolete backup
of state taking place of the current value. This may happen several HTTP 
requests later.

I've found a solution for this problem by not storing the saved state in the 
UIDataAdaptor, but in the target component itself. In this manner, there can 
only be one backup of the data. Such a modification is actually hinted at in 
UIDataAdaptor's source code : "// TODO - use local map - children save their 
state themselves using visitors", although my modification is simpler
(it's still UIDataAdaptor that saves the state, in the same manner, only in a 
different place).

This bug is quite complex and extracting a testcase will take some time, but I 
am willing to do so if requested. I can also offer my patch for the problem 
once I have finalized it.

  was:
I am encountering a reentrancy problem with nested UIDataAdaptor components. 
For instance something like :

<rich:dataTable id="outer" ...>
    <rich:dataTable id="inner" ...>
        <h:inputText id="myText" ...>
    </rich:dataTable>
</rich:dataTable>

When a view contains nested UIDataAdaptor components, each UIDataAdaptor 
component has its own internal store for saving the saved state of child 
components (saveChildState/restoreChildState). Since "inputText" is included in 
both tables, each one may save and restore the value of the component in its 
internal store.

For instance, when "outer" is on key 0 and inner is on key "2", both "outer" 
and "inner" may store the state values for myText "outer:0:inner:2:myText" in 
their "childState" property.

I guess that most of the time, only "inner" will actually store useful values, 
because most of calls on "setRowKey" for outer will be done when "inner" has 
its rowkey set to null. Unfortunately, this is not always the case.
For instance, if I decide to visit the component tree while processing an event 
for "myText", outer will perform a setRowKey while inner has its own rowKey to 
a significant value (for instance, 2), the result being that inner's value will 
be erased by 
outer's.

To try and explain with a little more detail... Let's say that we are 
processing an event on "outer:1:inner:0:myText", and we start a (nested) visit 
of the tree :
1) "outer" will at some point perform a setRowKey(0)
2) It will then do a restoreChildState for myText. since "inner" has rowKey set 
to 0, it will restore "outer's" value for "outer:0:inner:0:myText".
3) A bit later on during the visit, inner will do "setRowKey(0)". It will first 
save the current value for "outer:0:inner:0:myText" (which comes from outer's 
backup of it, restored on step 2)

The result of this process is that "outer"'s backup of "outer:0:inner:0:myText" 
overwrites "inner"'s backup for it. This is problematic because this leads, 
sometimes, to an old and obsolete backup
of state taking place of the current value. This may happen several HTTP 
requests later.

I've found a solution for this problem by not storing the saved state in the 
UIDataAdaptor, but in the target component itself. In this manner, there can 
only be one backup of the data. Such a modification is actually hinted at in 
UIDataAdaptor's source code : "// TODO - use local map - children save their 
state themselves using visitors", although my modification is simpler
(it's still UIDataAdaptor that saves the state, in the same manner, only in a 
different place).

This bug is quite complex and extracting a testcase will take some time, but I 
am willing to do so if requested. I can also offer my patch for the problem 
once I have finalized it.



> Nested UIDataAdaptor restoring stale data because of reentrancy problem
> -----------------------------------------------------------------------
>
>                 Key: RF-13703
>                 URL: https://issues.jboss.org/browse/RF-13703
>             Project: RichFaces
>          Issue Type: Bug
>      Security Level: Public(Everyone can see) 
>    Affects Versions: 4.3.1
>         Environment: (Windows 7. Java 6. Jetty 7.6.9 or Tomcat 6.0.37)
>            Reporter: Yannick Valot
>
> I am encountering a reentrancy problem with nested UIDataAdaptor components. 
> For instance something like :
> {code}
> <rich:dataTable id="outer" ...>
>     <rich:dataTable id="inner" ...>
>         <h:inputText id="myText" ...>
>     </rich:dataTable>
> </rich:dataTable>
> {code}
> When a view contains nested UIDataAdaptor components, each UIDataAdaptor 
> component has its own internal store for saving the saved state of child 
> components (saveChildState/restoreChildState). Since "inputText" is included 
> in both tables, each one may save and restore the value of the component in 
> its internal store.
> For instance, when "outer" is on key 0 and inner is on key "2", both "outer" 
> and "inner" may store the state values for myText "outer:0:inner:2:myText" in 
> their "childState" property.
> I guess that most of the time, only "inner" will actually store useful 
> values, because most of calls on "setRowKey" for outer will be done when 
> "inner" has its rowkey set to null. Unfortunately, this is not always the 
> case.
> For instance, if I decide to visit the component tree while processing an 
> event for "myText", outer will perform a setRowKey while inner has its own 
> rowKey to a significant value (for instance, 2), the result being that 
> inner's value will be erased by 
> outer's.
> To try and explain with a little more detail... Let's say that we are 
> processing an event on "outer:1:inner:0:myText", and we start a (nested) 
> visit of the tree :
> 1) "outer" will at some point perform a setRowKey(0)
> 2) It will then do a restoreChildState for myText. since "inner" has rowKey 
> set to 0, it will restore "outer's" value for "outer:0:inner:0:myText".
> 3) A bit later on during the visit, inner will do "setRowKey(0)". It will 
> first save the current value for "outer:0:inner:0:myText" (which comes from 
> outer's backup of it, restored on step 2)
> The result of this process is that "outer"'s backup of 
> "outer:0:inner:0:myText" overwrites "inner"'s backup for it. This is 
> problematic because this leads, sometimes, to an old and obsolete backup
> of state taking place of the current value. This may happen several HTTP 
> requests later.
> I've found a solution for this problem by not storing the saved state in the 
> UIDataAdaptor, but in the target component itself. In this manner, there can 
> only be one backup of the data. Such a modification is actually hinted at in 
> UIDataAdaptor's source code : "// TODO - use local map - children save their 
> state themselves using visitors", although my modification is simpler
> (it's still UIDataAdaptor that saves the state, in the same manner, only in a 
> different place).
> This bug is quite complex and extracting a testcase will take some time, but 
> I am willing to do so if requested. I can also offer my patch for the problem 
> once I have finalized it.



--
This message was sent by Atlassian JIRA
(v6.2.6#6264)
_______________________________________________
richfaces-issues mailing list
richfaces-issues@lists.jboss.org
https://lists.jboss.org/mailman/listinfo/richfaces-issues

Reply via email to