[richfaces-issues] [JBoss JIRA] (RF-13703) Nested UIDataAdaptor restoring stale data because of reentrancy problem
Yannick Valot (JIRA)
issues at jboss.org
Thu Jun 26 11:15:26 EDT 2014
Yannick Valot created RF-13703:
----------------------------------
Summary: 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 :
<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.
--
This message was sent by Atlassian JIRA
(v6.2.6#6264)
More information about the richfaces-issues
mailing list