Details
-
Improvement
-
Status: Closed
-
Major
-
Resolution: Fixed
-
None
-
None
Description
Mutable attributes are not state saved when using partial state saving. Let's start with partial state saving basics
How does full state saving work? Two things are saved,
1. the structure of the component tree - as in parent/child/facet relationships
2. the state of the components - there is a state object for each component, this object might hold all the attribute values.
Partial state saving is based on the fact that Facelets tag handlers can be re-executed during restore view in order to re-create the initial state of the component tree so that the structure of the component tree does not need to be state saved. Note that this means the tags are now executed during restore view, which does not happen in full state saving.
Because the tags are re-executed with partial state saving, only attribute changes made after the tags have been executed need to be state saved. This is accomplished by calling markInitialState on the components after the tags have been executed, so that only changes applied after markInitialState has been called are state saved.
What is actually saved in partial state saving? The differences for partial state saving are:
1. the structure of the page - not saved, the tags are re-executed to create the structure
2. the state of the page - still a tree of state objects, but the state object is only a map of the deltas and is therefore usually empty.
Now let's look at the mutable attribute case. The mutable attribute case is a case where the app dev is getting a local attribute off the component and mutating it, for example get a local value of a date and mutate it (mutable attributes are a fairly rare case, because normally attributes are either EL bound or immutable (boolan, string, etc)). In partial state saving only the deltas are saved, and deltas are generated by sets on component attributes, without a set getting called an attribute will not be in the delta list, and therefore won't be state saved, so if an attribute is mutated from outside the component the changes would not be state saved.
Proposal to fix this is only do partial state saving on attributes that tell us the type is immutable, since most attributes are String, booleans, and other immutable types this means most attributes are still doing partial state saving.
1 enhance org.apache.myfaces.trinidad.bean.PropertyKey api to add a new capability that indicates that the attribute is mutable, defaults to false. There would be a new constant CAP_MUTABLE, and a new method isMutable().
2. enhance metadata in build files to set this on the applicable property keys, add <mfp:mutable>true</mfp:mutable> under <property-extension>
3. enhance build tool to look for the metadata and create the appropriate capability
4. when state saving in org.apache.myfaces.trinidad.bean.util.PropertyHashMap.saveState() go through the keys and check the propertyKey for CAP_MUTABLE, if it's mutable put the value in the deltas map
New API: Enhance org.apache.myfaces.trinidad.bean.PropertyKey api to add a new capability that indicates that the attribute is mutable, defaults to false. Add
1. new constant CAP_MUTABLE
2. new method isMutable().