Hi!

I hope its not wrong to post this to the developer list at first, but I think there is a technical problem with the aliasbean.

Our jsf looks like this (for sure, we use include for the dataTable):

<x:aliasBeansScope>
   <x:aliasBean alias="#{coTopicEdit}" value="#{coAddressEdit}" />
   <h:dataTable var="topic" value="#{coTopicEdit.topics}"
               binding="#{coTopicEdit.genericTopicTable}" >
....
   </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)
       {
           processAliases(facesContext, root);
       }
       return root;
   }

   protected void processAliases(FacesContext context, UIComponent root)
   {
       if (root == null)
       {
           return;
       }

       for (Iterator it = root.getFacetsAndChildren(); it.hasNext(); )
       {
           UIComponent component = (UIComponent)it.next();

           if (component instanceof AliasBean)
           {
               AliasBean alias = (AliasBean) component;
               try
               {
Method makeAliasMethod = alias.getClass().getDeclaredMethod("makeAlias", FacesContext.class);
                   makeAliasMethod.setAccessible(true);
                   makeAliasMethod.invoke(alias, context);
               }
               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);
       }
   }


---
Mario

Reply via email to