[jsr-314-open] Partial state saving + tree visiting

Andy Schwartz andy.schwartz at oracle.com
Fri Jan 28 18:23:17 EST 2011


Gang -

I have been spending time looking partial state saving lately - mostly 
trying to understand what Trinidad/ADF Faces need to do to fully support 
this. I have some questions regarding the use of tree visiting to 
save/restore partial state. This touches on implementation, though think 
it is important to have a consistent story, so sending to jsr-314-open.

At the moment our implementations are somewhat mixed in how they handle 
the partial state traversals:

- Mojarra 2.1 performs a tree visit for both the partial state save and 
restore traversals.
- Mojarra 2.0 performs a tree visit for the partial state restore but 
uses a good old facets + children traversal for the save.
- MyFaces 2.0 performs a facets + children traversal for both save and 
restore.

I believe the reason for the inconsistency has to do with the fact that 
we did not have an explicit VisitHint.SKIP_ITERATION in 2.0. (Though, at 
some point last year we agreed to temporarily go with a FacesContext 
property until we could add the new VisitHint to the API.) As a result, 
the implementation teams avoided tree visiting (at least partially) in 
order to avoid unnecessary/incorrect UIData iteration. Now that we've 
got our visit hint in 2.1, in theory this should make the correct 
behavior clearer: we can now use tree visits for both the save and 
restore and specify the SKIP_ITERATION visit hint to avoid iterating 
over rows in iterating components.

However, after thinking this through in more detail, I am not quite sure 
whether the correct behavior is as obvious as I originally thought it was.

Here's why…

One of the main benefits of tree visiting over a traditional facets + 
children traversal is that tree visiting allows components to be visited 
"in context" - ie. ancestor components can override visitTree() to set 
up context on behalf of their children. The most typical case is an 
ancestor setting up context that influences EL evaluation for the 
ancestor's subtree.

We (ADF) have some cases where setting up context can be expensive and 
as such we'll want to avoid this work if not strictly necessary. More 
generally, we don't want to set up any tree visiting-related context 
during state saving/restoring since it is simply not necessary. We have 
never performed context set up/tear down during full state saving (ie. 
processRestoreState()/processSaveState() don't do anything interesting). 
There is no point in introducing this now for partial state saving. 
Doing so would introduce unnecessary overhead, plus result in 
inconsistent behavior between partial and full state saving.

I had been thinking that the way to handle this is to have some way for 
our components to distinguish between visitTree() calls that occur for 
partial state saving/restoring purposes (in which case we don't want to 
set up context) vs. other tree visits (in which case we do want to set 
up context). As of 2.1, we have all of the APIs in place to allow us to 
do just this. In particular:

- We can detect the partial state saving tree visit via the 
StateManager.IS_SAVING_STATE FacesContext property.
- We can detect the partial state restoring tree visit by checking the 
phase id + VisitHint.EXECUTE_LIFECYCLE. (Though implementations will 
need to be sure to set this hint - logged Mojarra issue 1929 for this.)

By examining these properties/hints, a visitTree() implementation can 
make an informed decision about whether it is necessary to set up context.

While it is now possible for visitTree() implementations to do the right 
thing, I worry that this is overly complex and possibly unnecessary. If 
we want to:

- Visit all (non-transient) components, but…
- Skip iteration (for UIData-like cases). And…
- Avoid setting up context.

Is tree visiting even the right tool for the job?

Should we perhaps avoid this complexity altogether by sticking with a 
facets + children traversal (eg. as currently implemented by MyFaces) 
for partial state saving/restoring?

Or are there cases where component implementations do in fact need 
control over the way that this traversal is performed, in which case an 
internal iteration solution (like tree visiting) is necessary?

Andy




More information about the jsr-314-open-mirror mailing list