8 Replies Latest reply on Mar 30, 2012 2:12 PM by a.zhemoytuk

    RF4/rich:tabPanel: adding tabs dynamically --> NPE

    ovesper

      Hi folks,

       

      I am using a rich:tabPanel with switchType="server" where the rich:tab elements are dynamic - meaning they are backed by a bean. The XHTML looks like this:

       

       

      {code:xml}<h:form id="majorForm" prependId="true">

           <rich:tabPanel id="majorTabPanel" width="40%" headerAlignment="left" switchType="server">

                <c:forEach items="#{tabService.dynamicTabs}" var="tab">

                     <rich:tab header="foo">

                          <h:outputText value="bar"/>

                     </rich:tab>

                </c:forEach>                   

           </rich:tabPanel>

      </h:form>{code}

       


      Somewhere else on the page I've got a link which adds further tabs to the tabPanel:

       

      {code:xml}<h:commandLink>

           <h:graphicImage value="images/foo.png" />

           <a4j:ajax event="click" render=":majorForm:majorTabPanel" listener="#{tabService.addTab()}"/>

      </h:commandLink>{code}

       

      Clicking on the link causes the tabService to add another item to its list "dynamicTabs". Afterwards the tab-panel is rendered and a new tab shows up. It is possible to switch to the new tab. So far everything works fine.

       

      Now I switch back to any another tab (or even re-selecting this currently shown new tab) and it results in a NullPointerException:

       

       

      java.lang.NullPointerException

      at org.richfaces.component.AbstractTabPanel.getActiveItem(AbstractTabPanel.java:64)
      at org.richfaces.component.AbstractTogglePanel.getActiveItemValue(AbstractTogglePanel.java:477)
      at org.richfaces.component.AbstractTogglePanel.processDecodes(AbstractTogglePanel.java:210)
      at javax.faces.component.UIForm.processDecodes(UIForm.java:212)
      at javax.faces.component.UIComponentBase.processDecodes(UIComponentBase.java:1043)
      at javax.faces.component.UIComponentBase.processDecodes(UIComponentBase.java:1043)
      at javax.faces.component.UIViewRoot.processDecodes(UIViewRoot.java:920)
      at com.sun.faces.lifecycle.ApplyRequestValuesPhase.execute(ApplyRequestValuesPhase.java:74)
      at com.sun.faces.lifecycle.Phase.doPhase(Phase.java:97)
      at com.sun.faces.lifecycle.LifecycleImpl.execute(LifecycleImpl.java:114)
      at javax.faces.webapp.FacesServlet.service(FacesServlet.java:308)
      at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:324)
      at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:242)
      at org.jboss.weld.servlet.ConversationPropagationFilter.doFilter(ConversationPropagationFilter.java:67)
      at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:274)
      at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:242)
      at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:275)
      at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191)
      at org.jboss.web.tomcat.security.SecurityAssociationValve.invoke(SecurityAssociationValve.java:181)
      at org.jboss.modcluster.catalina.CatalinaContext$RequestListenerValve.event(CatalinaContext.java:285)
      at org.jboss.modcluster.catalina.CatalinaContext$RequestListenerValve.invoke(CatalinaContext.java:261)
      at org.jboss.web.tomcat.security.JaccContextValve.invoke(JaccContextValve.java:88)
      at org.jboss.web.tomcat.security.SecurityContextEstablishmentValve.invoke(SecurityContextEstablishmentValve.java:100)
      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:158)
      at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
      at org.jboss.web.tomcat.service.request.ActiveRequestResponseCacheValve.invoke(ActiveRequestResponseCacheValve.java:53)
      at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:362)
      at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:877)
      at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:654)
      at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:951)
      at java.lang.Thread.run(Thread.java:662)

       

      Any idea what is going wrong?

       

      Thanks in advance for your support,

      Oliver

       

      p.s. for the sake of completeness:

      - my backing bean is annotated with @ViewScoped

      - my app is running on JBoss AS 6.0 using Mojarra 2.0.3-b05

        • 1. RF4/rich:tabPanel: adding tabs dynamically --> NPE
          ovesper

          Hi,

           

          changing the scope of the tab-bean (the one which holds the dynamic list of tabs to be displayed) from @ViewScoped to @SessionScoped makes my scenario work. This is very interesting because AFAIK a bean annotated with @ViewScoped should persist as long as one stays on the same JSF page - which is the case... I'm just re-rendering the tab-panel. Am I missing something?

           

          -Oliver

          • 2. Re: RF4/rich:tabPanel: adding tabs dynamically --> NPE
            lfryc

            Hi Oliver,

             

            could you provide us the code of the your backing bean?

             

            Alternatively could you provide minimalistic sample application?

            • 3. Re: RF4/rich:tabPanel: adding tabs dynamically --> NPE
              ovesper

              Hi Lukas,

               

              here's the code of my backing bean and also of the used tab-item class (everything is already stripped down as much as possible):

               

               

              {code}@ManagedBean(name = "tabService")

              @ViewScoped

              public class TabBean implements Serializable {

               

                  private static final long serialVersionUID = 1L;

                  private static int instanceCounter = 0;

               

                  private final List<MyTabItem> dynamicTabs = new ArrayList<MyTabItem>();

                  private final int count;

               

                  public TabBean() {

                      synchronized (TabBean.class) {

                          this.count = ++instanceCounter;

                      }

                      this.dynamicTabs.add(new MyTabItem());

                  }

               

                  public List<MyTabItem> getDynamicTabs() {

                      System.out.println("TabBean::getDynamicTabs count=" + this.count);

                      return this.dynamicTabs;

               

                  }

               

                  public void addTab() {

                      System.out.println("TabBean::addTab count=" + this.count);

                      this.dynamicTabs.add(new MyTabItem());

               

                  }

              }

               

              public class MyTabItem implements Serializable {

                  private static final long serialVersionUID = 1L;

              }{code}

               

              And here's the complete content of my single xhtml page:

               

              {code:xml}

              <?xml version="1.0" encoding="UTF-8"?>

              <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

              <html xmlns="http://www.w3.org/1999/xhtml"

                    xmlns:a4j="http://richfaces.org/a4j"

                    xmlns:rich="http://richfaces.org/rich"

                    xmlns:h="http://java.sun.com/jsf/html"

                    xmlns:c="http://java.sun.com/jsp/jstl/core">

                  <h:head>

                      <title>Tab test</title>

                      <meta http-equiv="content-type" content="text/html; charset=UTF-8" />

                  </h:head>

                  <h:body>

                      <h:form>

                          <h:commandLink>

                               <h:graphicImage value="images/foo.png" />

                               <a4j:ajax event="click" render=":majorForm:majorTabPanel" listener="#{tabService.addTab()}"/>

                          </h:commandLink>

                      </h:form>

                      <h:form id="majorForm" prependId="true">

                           <rich:tabPanel id="majorTabPanel" width="40%" headerAlignment="left" switchType="server">

                                <c:forEach items="#{tabService.dynamicTabs}" var="tab">

                                     <rich:tab header="foo">

                                          <h:outputText value="bar"/>

                                     </rich:tab>

                                </c:forEach>                   

                           </rich:tabPanel>

                      </h:form>

                  </h:body>

              </html>{code}

               

              As mentioned before putting the backing bean into session scope works fine - @ViewScoped results in the NPE. I added two SYSOUT log messages and it is very interesting to see that the newly created tab-items are all added to the same backing bean -  but for some reason a new instance of TabBean is being created when switching from one tab to another (or re-selecting the same one). Here is the log-output from the console:

               

              {code}[STDOUT] TabBean::getDynamicTabs count=1

              [STDOUT] TabBean::getDynamicTabs count=2

              [STDOUT] TabBean::addTab count=1

              [STDOUT] TabBean::getDynamicTabs count=1

              [STDOUT] TabBean::getDynamicTabs count=3

              [STDOUT] TabBean::addTab count=1

              [STDOUT] TabBean::getDynamicTabs count=1

              [STDOUT] TabBean::getDynamicTabs count=4

              [STDOUT] TabBean::addTab count=1

              [STDOUT] TabBean::getDynamicTabs count=1

              [STDOUT] TabBean::getDynamicTabs count=5

              [STDOUT] TabBean::getDynamicTabs count=1

              [STDOUT] TabBean::getDynamicTabs count=6{code}

               

              Maybe the problem is related to the use of the c:forEach?

               

              -Oliver

              • 4. RF4/rich:tabPanel: adding tabs dynamically --> NPE
                ovesper

                Anybody got an idea about this issue? Does it indicate a bug so I should file it to jira instead?

                 

                -Oliver

                • 5. RF4/rich:tabPanel: adding tabs dynamically --> NPE
                  ilya_shaikovsky

                  see "Related Issues" on top of that thread.

                  And b.t.w. easy workaround would be to bind activeItem to bean and define some default tab there. I used that while created dynamic tabs for richfaces-showcase.

                   

                  Hope it helps.

                  • 6. RF4/rich:tabPanel: adding tabs dynamically --> NPE
                    ilya_shaikovsky

                    sorry misunderstood the problem.

                     

                    if you able to create just small kick-start sample just report it to jira as I do not find more related to that one.

                    • 7. Re: RF4/rich:tabPanel: adding tabs dynamically --> NPE
                      anubondada

                      Hi,

                       

                      We are using above approach to generate (foreach on tabPanal and Using Backing Bean) the dynamic tabs and we are able generate the dynamic tabs. When we click on particular tab, we are showing corresponding page dynamically.

                       

                      Example User Clicks on

                       

                      Tab1  > Page1

                      Tab2  > Page2  …. Etc.

                       

                      We are using the activeItem to highlight the selected tab.

                       

                      In the JSF page(Which is loaded when we click on Tab), styles are not loading properly and also If we have rich popup in the page, data is not loading properly in the popup.

                       

                      Can anyone help us why the styles are not applying and the data is not loading in the pop up?

                       

                      Thanks in advance.

                      • 8. Re: RF4/rich:tabPanel: adding tabs dynamically --> NPE
                        a.zhemoytuk

                        The issue is reproducible also for 'static' tabs when rendered condition resolved to false for all tabs, for example:

                        <rich:tabPanel>

                          <rich:tab rendered="#{bean.somethingMaybeFalse}"> </rich:tab>

                        </rich:tabPanel>

                         

                        Or just for case with no tabs: <rich:tabPanel/>

                         

                        As of 4.2.0.Final - NPE is thrown

                        3.3.x - whole tab panel was not rendered if no tabs to render.