Details
-
Bug
-
Status: Closed
-
Major
-
Resolution: Fixed
-
1.0.9m9
-
None
-
None
-
None
Description
Myfaces fails to restore a view it it uses aliases in bindings.
Our jsf looks like this (for sure, we use include for the dataTable):
<x:aliasBeansScope>
<x:aliasBean alias="#
" value="#
{coAddressEdit}" />
<h:dataTable var="topic" value="#
"
binding="#
....
</h:dataTable>
<h:commandLink value="xx"/>
</x:aliasBeansScope>
The page renders correctly for the first time, but if you press the commandLink myfaces fails in the restoreView phase.
The reason is simple:
During LifecycleImpl.restoreView myfaces tries to attach each component to the backing bean (in recursivelyHandleComponentReferencesAndSetValid - "binding.setValue").
Now if it comes to the binding of the dataTable the alias bean havent had the chance to reassign its alias and thus the ValueBinding for "#{coTopicEdit.genericTopicTable}
" fails.
To workaround it I create my own ViewHandler (code follows).
I hooked into restoreView - process the view recursivley and call "makeAlias" on each alias bean using reflection (the method is package private).
This IS a hack and (I think) it breaks the scope of the alias , but for now I am happy with it.
Any ideas how to solve it correctly?
And now the code in case someone else needs it too:
public UIViewRoot restoreView(FacesContext facesContext, String viewId)
{
UIViewRoot root = super.restoreView(facesContext, viewId);
if (root != null)
return root;
}
protected void processAliases(FacesContext context, UIComponent root)
{
if (root == null)
for (Iterator it = root.getFacetsAndChildren(); it.hasNext(); )
{
UIComponent component = (UIComponent)it.next();
if (component instanceof AliasBean)
{
AliasBean alias = (AliasBean) component;
try
catch (NoSuchMethodException e)
{ log.warn(e.getLocalizedMessage(), e); }catch (IllegalAccessException e)
{ log.warn(e.getLocalizedMessage(), e); }
catch (InvocationTargetException e)
{ log.warn(e.getLocalizedMessage(), e); }}
processAliases(context, component);
}
}