Search code examples
jsfclasscastexceptioncomposite-componentuirepeat

Composite component in ui:repeat vs c:forEach using ajax calls


I have a composite component, which represents an item that will be stored in a list. I would like to display these items using <ui:repeat>, but I have problems making ajax calls. The thing is that for <f:ajax> render attribute, I want to give the id of my component through

#{cc.clientId}

However this raises error when I use it with <ui:repeat>, because of the reasons that are explained in this document https://rogerkeays.com/jsf-c-foreach-vs-ui-repeat.

<cc:implementation>
    <div id="#{cc.clientId}">
          <h:form>
                <h:commandLink styleClass="btn btn-info" value="Click me">
                    <f:ajax execute="@form"
                            render=":#{cc.clientId}"/>
                </h:commandLink>
            </h:form>
    </div>
</cc:implementation>

Is there a way to make the above component work using <ui:repeat> (for example is there a component which can replace the <f:ajax> tag handler, or are we stuck to <c:forEach> construct)?

<ui:repeat id="myComponent" value="#{backingBean.myComponentItem}" var="item" varStatus="itemIndex">
    <components:exampleComponent id="myComponent"/>
</ui:repeat>

So I start using <c:forEach> instead of <ui:repeat>, and I was able to use the id of my component in the render attribute of <f:ajax>. But this time when I make pagination, if the size of the list decreases I start having empty components in my page. For solving this I started doing pagination through ajax calls and this solved the empty component problem.

Just I thought everything was solved I encountered another problem: lets say I have a page listing 10 components, and I went to another page, and from that page I came to the component displaying page again, but for some reason lets say this time I retrieved only 3 items from database, and I just want to display these 3 items through my components but nothing else.. Unfortunately in this scenario, 3 items are displayed correctly, but the page also contains 7 empty components too. For overcoming this I need to redirect to this page one-more time. So I just gave up at this point. Apart from this I also eventually get the exception below, when the number of the components on the page changes.

java.lang.ClassCastException: [Ljava.lang.Object; cannot be cast to com.sun.faces.application.view.StateHolderSaver

I tried using the suggestion explained in the post Jsf Error : java.lang.ClassCastException, but it didn't work for me, I started getting another error which is similar to above exception.

<context-param>
    <param-name>javax.faces.FULL_STATE_SAVING_VIEW_IDS</param-name>
    <param-value>/pagename.xhtml</param-value>
</context-param> 

So after these long explanations I would just like to learn what is the best approach for creating composite components which are ajax-enabled, who are fully responsible of their own-states and independent of other components, and that can be displayed in the page more than once and the number of components may vary during the page life-cycle (through pagination, navigation etc).


Solution

  • So far the best solution I came up with is, to check number of components in the page and when that number changes through an ajax call or because of a navigation from another page, redirect to the destination page one more time, this refreshes the empty components in the page without creating much disturbance to users. If you come up with any better solution please let us know.