Hi,
I subscribed to this Mailing list because M. Riem asked me to propse
any suggestions for improving performance in
FaceletViewHandlingStrategy.buildView() which relate to re-applying
dynamic adds, see issue in subject.
Since the issue has been closed, I guess I have to participate via some
mailing list.
Maybe this is the wrong one.
Nevertheless:
As Manfred indicates in his comment on the issue, one canot completly
suppress re-applying the dynamic adds because of transient components.
I have to admit that I do not understand these Problems in detail.
But I have another suggestions:
Fist, locateComponentByClientId() of FaceletViewHandlingStrategy is
slow, because it always starts to search at UIViewRoot. Issue 2876
addresses the Problem. It even states that the improvement is fixed in
2.1.23. But at least according to the source code I downloaded via
maven for 2.1.28 that is not true.
Also, I tried to speed things up by changing
reapplyDynamicAdd(FacesContext , ComponentStruct) .
For one thing, if children are added dynamically to a parent, one often
adds multiple children to that parent.One can cache the parents in a
Map which is created in reapplyDynamicActions(FacesContext), and put a
parent into that Map if it has been located once. When another
ComponentStruct refers to the same parent, it can be read from that Map
instead of performing locateComponentByClientId() again.
Also, if the child can be located (because it has already been added in
RESTORE_VIEW), I checked if there are any transient siblings. I guess
if there are no transient siblings, there can be no conflicts with a
mixture of transient components and dynamically added coponents in that
parent. Also, I guess there can be no Problems if the dynamically added
component is a facet.
Here is a code snippet with my changes (excluding the refactoring of
locateComponentByClientId() and reapplyDynamicActions():
private void reapplyDynamicAdd(FacesContext context,
ComponentStruct struct,
Map<String,
UIComponent> parents,
Set<UIComponent> parentsWithoutTransientChildren) {
UIComponent parent = parents.get(struct.parentClientId);
if (parent == null)
{
parent = locateComponentByClientId(context,
struct.parentClientId, context.getViewRoot());
if (parent != null)
{
parents.put(struct.parentClientId, parent);
}
}
if (parent != null) {
UIComponent child = locateComponentByClientId(context,
struct.clientId, parent);
StateContext stateContext =
StateContext.getStateContext(context);
if (child == null) {
child =
stateContext.getDynamicComponents().get(struct.clientId);
}
else {
if (struct.facetName == null) {
if
(parentsWithoutTransientChildren.contains(parent)) {
return;
}
boolean anyTransient = false;
for(UIComponent sibling : parent.getChildren())
{
if (sibling.isTransient()) {
anyTransient = true;
break;
}
}
if (anyTransient == false) {
parentsWithoutTransientChildren.add(parent);
return;
}
}
else {
return;
}
}
// the remaing code of the method has not been changed
That change improves performance in about the same degree as my
previous Suggestion (which was refused by Manfred).