[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