6 Replies Latest reply on Apr 14, 2008 8:41 PM by Chris Odom

    UIComponentBase returns Facet key as child

    Chris Odom Newbie

      I am currently working on a project where I needed to render a modal panel in which display a progress bar and uses the facet complete to show a scrollable data table. The problem I am having is that for the modal panel there are 2 facets being created a "header" as a output text and a "controls" as an graphic image. The panel also has an child objects that are created and add to the childrens list. After all is rendered and put together the backing bean used for the modal panel looks very complete. What happens though is when the UIComponentBase does its recusive process throgh the restoring states some how the key of the last entered facet for the modal panel becomes a childstate object for the top most child object of the modal panel.

      Example:
      HtmlModalPanel creates two facets
      1. HtmlOutputText added with key "header"
      2. HtmlGraphicImage added wtih key "controls"

      HtmlAjaxOutputPanel as a child of HtmlModalPanel
      when the restoreState is called on the HtmlAjaxOutputPanel it is passed its state first then a second state of type java.land.String with value "controls".

      I have tried this with other child objects and get the same result. I have changed the order of placement for the facets as in first add "controls" then "header" and found that it is always the last key in the FacetsMap get sent as a state object to the first Child UIComponent of the ChildrenList object.

      Any ideas.

      RichFaces 3.2.0
      JSF 1.2
      Seam 2.1.0.GA
      JBossAS 4.2.2

      thanks!

        • 1. Re: UIComponentBase returns Facet key as child
          Maksim Kaszynski Apprentice

          Chris,
          how does that processing order affect your application?
          What problems are you getting?

          • 2. Re: UIComponentBase returns Facet key as child
            Chris Odom Newbie

            What happens is that when the state manager calls to restore the UIComponents on UIComponentBase.processRestoreState() one of the childern ends up being the Facet key so I get a CastClassException trying to cast a String to UIComponent. I did notice that during the processSaveState that the Object array for Facets gets added into the childState.

            • 3. Re: UIComponentBase returns Facet key as child
              Maksim Kaszynski Apprentice

              That's very strange indeed.
              What exact version of JSF 1.2 are you using?
              Are you using JSP or Facelets?

              • 4. Re: UIComponentBase returns Facet key as child
                Chris Odom Newbie

                I am using the default JSF for 4.2.2

                [jboss-faces.jar]
                Manifest-Version: 1.0
                Specification-Title: JBoss
                Created-By: 1.5.0_11-b03 (Sun Microsystems Inc.)
                Ant-Version: Apache Ant 1.6.2
                Implementation-Title: JBoss [Trinity]
                Specification-Vendor: JBoss (http://www.jboss.org/)
                Specification-Version: 4.2.2.GA
                Implementation-Vendor-Id: http://www.jboss.org/
                Implementation-Version: 4.2.2.GA (build: SVNTag=JBoss_4_2_2_GA date=20
                0710221139)
                Implementation-Vendor: JBoss Inc.
                Implementation-URL: http://www.jboss.org/

                [jsf-api.jar]
                Manifest-Version: 1.0
                Specification-Title: JavaServer Faces
                Created-By: 1.5.0_04-b05 (Sun Microsystems Inc.)
                Ant-Version: Apache Ant 1.6.5
                Implementation-Title: Sun Microsystems JavaServer Faces Implementation
                Specification-Vendor: JBoss (http://www.jboss.org/)
                Specification-Version: 1.2MR1
                Implementation-Vendor-Id: com.sun
                Extension-Name: javax.faces
                Implementation-Version: 1.2_04-b16-p02
                Implementation-Vendor: Sun Microsystems, Inc.
                Implementation-URL: http://www.jboss.org/

                [jsf-impl.jar]
                Manifest-Version: 1.0
                Specification-Title: JavaServer Faces
                Created-By: 1.5.0_04-b05 (Sun Microsystems Inc.)
                Ant-Version: Apache Ant 1.6.5
                Implementation-Title: Sun Microsystems JavaServer Faces Implementation
                Specification-Vendor: JBoss (http://www.jboss.org/)
                Specification-Version: 1.2MR1
                Implementation-Vendor-Id: com.sun
                Extension-Name: com.sun.faces
                Implementation-Version: 1.2_04-b16-p02
                Implementation-Vendor: Sun Microsystems, Inc.
                Implementation-URL: http://www.jboss.org/

                I am using Facelets...
                [web.xml]

                <servlet-name>Faces Servlet</servlet-name>
                <servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
                <load-on-startup>1</load-on-startup>


                • 5. Re: UIComponentBase returns Facet key as child
                  Chris Odom Newbie

                  This is the code from UIComponentBase.processSaveState that I was mentioning earlier...

                  // if we have facets, add them to the stateList
                   if (this.getFacetCount() > 0) {
                   Iterator myFacets = getFacets().entrySet().iterator();
                   UIComponent facet;
                   Object facetState;
                   Object[] facetSaveState;
                   Map.Entry entry;
                   while (myFacets.hasNext()) {
                   entry = (Map.Entry) myFacets.next();
                   facet = (UIComponent) entry.getValue();
                   if (!facet.isTransient()) {
                   facetState = facet.processSaveState(context);
                   facetSaveState = new Object[2];
                   facetSaveState[0] = entry.getKey();
                   facetSaveState[1] = facetState;
                   stateList.add(facetSaveState);
                   }
                   }
                   }
                  
                   // finally, capture the stateList and replace the original,
                   // EMPTY_OBJECT_ARRAY Object array
                   childState = stateList.toArray();
                   }
                  


                  What I noticed was that the facetSaveState[0] = entry.getKey() which is the actual named key for the facet. Later down you see that both the facetState and facet key get entered into the stateList. I am not sure if the Object[] being parsed in processRestorState takes into account that facet objects are an array of the Key and State.

                  • 6. Re: UIComponentBase returns Facet key as child
                    Chris Odom Newbie

                    From my research this is what I have been able to gather.

                    example component with children and facets. These 2 methods are used to create the Children and Facets for a HtmlModalPanel class.

                    public void createFacets() {
                    
                     HtmlOutputText text = new HtmlOutputText();
                     text.setValue("Test Run");
                     text.setId("header");
                    
                     getFacets().put("header", text);
                    
                     HtmlGraphicImage image = new HtmlGraphicImage();
                     image.setStyle("cursor:pointer;");
                     image.setOnclick("Richfaces.hideModalPanel('TestModalPanel');");
                     image.setId("close");
                     image.setValue("/img/icons/delete2.gif");
                     image.setId("image");
                    
                     getFacets().put("controls", image);
                     }
                    
                    public void createChildren() {
                    
                     HtmlAjaxOutputPanel panel = new HtmlAjaxOutputPanel();
                     panel.setId("progressPanel");
                    
                     progressBar = new ProgressBarBean();
                    
                     progressBar.setReRenderAfterComplete("progressPanel");
                     progressBar.setMinValue(0);
                     progressBar.setMaxValue(100);
                     progressBar.setEnabled(false);
                     progressBar.setRendered(true);
                     progressBar.setAjaxSingle(false);
                     progressBar.setValue(5);
                     progressBar.setMode("ajax");
                     progressBar.setInterval(1000);
                     progressBar.setDualColoredLabel(false);
                     progressBar.setIgnoreDupResponses(false);
                    
                     HtmlOutputText initial = new HtmlOutputText();
                     initial.setValue("Test not started");
                     initial.setId("initial");
                    
                     progressBar.getFacets().put("initial", initial);
                    
                     dataTable = new TestScrollableDataTableBean();
                     dataTable.setId("complete");
                    
                     progressBar.getFacets().put("complete", dataTable);
                    
                     panel.getChildren().add(progressBar);
                    
                     getChildren().add(panel);
                     }
                    


                    During the UIComponentBase.processSaveState()... it works on the UIComponents FacetMap saving the state of each Facets UIComponent.
                     public Object processSaveState(FacesContext context) {
                    
                     if (context == null) {
                     throw new NullPointerException();
                     }
                     if (this.isTransient()) {
                     return null;
                     }
                     Object [] stateStruct = new Object[2];
                     Object [] childState = EMPTY_ARRAY;
                    
                     // Process this component itself
                     stateStruct[MY_STATE] = saveState(context);
                    
                     // determine if we have any children to store
                     int count = this.getChildCount() + this.getFacetCount();
                     if (count > 0) {
                    
                     // this arraylist will store state
                     List<Object> stateList = new ArrayList<Object>(count);
                    
                     // if we have children, add them to the stateList
                     if (this.getChildCount() > 0) {
                     Iterator kids = getChildren().iterator();
                     UIComponent kid;
                     while (kids.hasNext()) {
                     kid = (UIComponent) kids.next();
                     if (!kid.isTransient()) {
                     stateList.add(kid.processSaveState(context));
                     }
                     }
                     }
                    
                     // if we have facets, add them to the stateList
                     if (this.getFacetCount() > 0) {
                     Iterator myFacets = getFacets().entrySet().iterator();
                     UIComponent facet;
                     Object facetState;
                     Object[] facetSaveState;
                     Map.Entry entry;
                     while (myFacets.hasNext()) {
                     entry = (Map.Entry) myFacets.next();
                     facet = (UIComponent) entry.getValue();
                     if (!facet.isTransient()) {
                     facetState = facet.processSaveState(context);
                     facetSaveState = new Object[2];
                     facetSaveState[0] = entry.getKey();
                     facetSaveState[1] = facetState;
                     stateList.add(facetSaveState);
                     }
                     }
                     }
                    
                     // finally, capture the stateList and replace the original,
                     // EMPTY_OBJECT_ARRAY Object array
                     childState = stateList.toArray();
                     }
                    
                     stateStruct[CHILD_STATE] = childState;
                     return stateStruct;
                     }
                    


                    It then proceeds to create and Object[] using both the Key and savedState from the UIComponent Facet. This Object[] is then set to the childState. When the UIComponentBase.processRestoreState() is called my parent HtmlModalPanel which utilized the 2 methods above now has:

                    1. HtmlAjaxOutputPanel
                    --HtmlProgressBar [Facet] key = initial
                    --HtmlScrollableDataTable [Facet] key = complete
                    2. HtmlOutputText [Facet] key = header
                    3. HtmlGraphicImage [Facet] key = controls

                    What I see during the processRestoreSate method is that I an Object that has all the UIComponents in it for the HtmlAjaxOutputPanel and 2 other Object[] which have a Object and Object. Because of this the processRestoreState recursivly calls the UIComponent's Overridden restoreSate methods so when it reaches the String object I get:

                    17:49:30,493 ERROR [ExceptionFilter] exception root cause
                    java.lang.reflect.InvocationTargetException
                     at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
                     at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
                     at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
                     at java.lang.reflect.Method.invoke(Method.java:585)
                     at javassist.util.proxy.RuntimeSupport$DefaultMethodHandler.invoke(RuntimeSupport.java:37)
                     at com.newsstand.dam.model.TestModalPanelBean_$$_javassist_6.processRestoreState(TestModalPanelBean_$$_javassist_6.java)
                     at javax.faces.component.UIComponentBase.processRestoreState(UIComponentBase.java:1157)
                     at javax.faces.component.UIComponentBase.processRestoreState(UIComponentBase.java:1157)
                     at javax.faces.component.UIComponentBase.processRestoreState(UIComponentBase.java:1157)
                     at javax.faces.component.UIComponentBase.processRestoreState(UIComponentBase.java:1157)
                     at javax.faces.component.UIComponentBase.processRestoreState(UIComponentBase.java:1157)
                     at javax.faces.component.UIComponentBase.processRestoreState(UIComponentBase.java:1157)
                     at javax.faces.component.UIComponentBase.processRestoreState(UIComponentBase.java:1157)
                     at org.ajax4jsf.application.AjaxStateManager.restoreView(AjaxStateManager.java:235)
                     at com.sun.faces.application.ViewHandlerImpl.restoreView(ViewHandlerImpl.java:290)
                     at org.jboss.seam.jsf.SeamViewHandler.restoreView(SeamViewHandler.java:93)
                     at org.ajax4jsf.application.ViewHandlerWrapper.restoreView(ViewHandlerWrapper.java:116)
                     at org.ajax4jsf.application.AjaxViewHandler.restoreView(AjaxViewHandler.java:131)
                     at com.sun.facelets.FaceletViewHandler.restoreView(FaceletViewHandler.java:316)
                     at org.ajax4jsf.application.ViewHandlerWrapper.restoreView(ViewHandlerWrapper.java:116)
                     at org.ajax4jsf.application.AjaxViewHandler.restoreView(AjaxViewHandler.java:131)
                     at com.sun.faces.lifecycle.RestoreViewPhase.execute(RestoreViewPhase.java:141)
                     at com.sun.faces.lifecycle.LifecycleImpl.phase(LifecycleImpl.java:251)
                     at com.sun.faces.lifecycle.LifecycleImpl.execute(LifecycleImpl.java:117)
                     at javax.faces.webapp.FacesServlet.service(FacesServlet.java:244)
                     at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290)
                     at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
                     at org.jboss.seam.servlet.SeamFilter$FilterChainImpl.doFilter(SeamFilter.java:83)
                     at org.jboss.seam.debug.hot.HotDeployFilter.doFilter(HotDeployFilter.java:68)
                     at org.jboss.seam.servlet.SeamFilter$FilterChainImpl.doFilter(SeamFilter.java:69)
                     at org.jboss.seam.web.MultipartFilter.doFilter(MultipartFilter.java:85)
                     at org.jboss.seam.servlet.SeamFilter$FilterChainImpl.doFilter(SeamFilter.java:69)
                     at org.jboss.seam.web.ExceptionFilter.doFilter(ExceptionFilter.java:64)
                     at org.jboss.seam.servlet.SeamFilter$FilterChainImpl.doFilter(SeamFilter.java:69)
                     at org.jboss.seam.web.RedirectFilter.doFilter(RedirectFilter.java:45)
                     at org.jboss.seam.servlet.SeamFilter$FilterChainImpl.doFilter(SeamFilter.java:69)
                     at org.ajax4jsf.webapp.BaseXMLFilter.doXmlFilter(BaseXMLFilter.java:147)
                     at org.ajax4jsf.webapp.BaseFilter.doFilter(BaseFilter.java:276)
                     at org.ajax4jsf.Filter.doFilter(Filter.java:175)
                     at org.jboss.seam.web.Ajax4jsfFilter.doFilter(Ajax4jsfFilter.java:60)
                     at org.jboss.seam.servlet.SeamFilter$FilterChainImpl.doFilter(SeamFilter.java:69)
                     at org.jboss.seam.web.LoggingFilter.doFilter(LoggingFilter.java:58)
                     at org.jboss.seam.servlet.SeamFilter$FilterChainImpl.doFilter(SeamFilter.java:69)
                     at org.jboss.seam.servlet.SeamFilter.doFilter(SeamFilter.java:158)
                     at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
                     at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
                     at org.jboss.web.tomcat.filters.ReplyHeaderFilter.doFilter(ReplyHeaderFilter.java:96)
                     at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
                     at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
                     at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:230)
                     at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:175)
                     at org.jboss.web.tomcat.security.SecurityAssociationValve.invoke(SecurityAssociationValve.java:179)
                     at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:432)
                     at org.jboss.web.tomcat.security.JaccContextValve.invoke(JaccContextValve.java:84)
                     at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:127)
                     at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
                     at org.jboss.web.tomcat.service.jca.CachedConnectionValve.invoke(CachedConnectionValve.java:157)
                     at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
                     at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:262)
                     at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:844)
                     at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:583)
                     at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:446)
                     at java.lang.Thread.run(Thread.java:595)
                    Caused by: java.lang.ClassCastException: java.lang.String
                     at org.ajax4jsf.component.html.HtmlAjaxOutputPanel.restoreState(HtmlAjaxOutputPanel.java:642)
                     at javax.faces.component.UIComponentBase.processRestoreState(UIComponentBase.java:1141)
                     at javax.faces.component.UIComponentBase.processRestoreState(UIComponentBase.java:1157)
                     at com.newsstand.dam.model.TestModalPanelBean_$$_javassist_6._d142processRestoreState(TestModalPanelBean_$$_javassist_6.java)
                     ... 63 more
                    


                    So bascially the new @Override method for restoreState with in the org.ajax4jsf.component.html Classes does not to take into consideration Object[] that have the Key and Value...or maybe its something else all together. I hope this helps out. Should there be a JIRA entry for this?