6
votes

I am trying to make two composite componenets play well together by nesting one as a child. The setup consists of a lightbox and a input both with an attribute called "Value". This works fine, until i introduce a dynamic number of inputs, and therefore have to use a ui:repeat.

bugTest.xhtml

<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:h="http://java.sun.com/jsf/html"
      xmlns:ui="http://java.sun.com/jsf/facelets"
      xmlns:pw="http://java.sun.com/jsf/composite/components">

    <h:head></h:head>
    <h:body>
        <pw:lightBox value="Header">
            <h:form>
                <ui:repeat var="input" value="#{BugTestBean.inputs}">
                    <pw:bugTestInput value="#{input}" />
                </ui:repeat>
            </h:form>
        </pw:lightBox>
    </h:body>
</html>

The ui:repeat seems to get the value attribute of the two components mixed up, and the following exception occurs.

Caused by: javax.el.PropertyNotFoundException: /resources/components/bugTestInput.xhtml @15,62 value="#{cc.attrs.value.text}": The class 'java.lang.String' does not have the property 'text'.
at com.sun.faces.facelets.el.TagValueExpression.getValue(TagValueExpression.java:111)
at javax.faces.component.ComponentStateHelper.eval(ComponentStateHelper.java:194)
at javax.faces.component.ComponentStateHelper.eval(ComponentStateHelper.java:182)
at javax.faces.component.UIOutput.getValue(UIOutput.java:170)
at javax.faces.component.UIInput.getValue(UIInput.java:284)
at com.sun.faces.facelets.component.UIRepeat$SavedState.populate(UIRepeat.java:879)
at com.sun.faces.facelets.component.UIRepeat.saveChildState(UIRepeat.java:396)
at com.sun.faces.facelets.component.UIRepeat.saveChildState(UIRepeat.java:402)
at com.sun.faces.facelets.component.UIRepeat.saveChildState(UIRepeat.java:402)
at com.sun.faces.facelets.component.UIRepeat.saveChildState(UIRepeat.java:356)
at com.sun.faces.facelets.component.UIRepeat.setIndex(UIRepeat.java:470)
at com.sun.faces.facelets.component.UIRepeat.process(UIRepeat.java:586)
at com.sun.faces.facelets.component.UIRepeat.encodeChildren(UIRepeat.java:1042)
at javax.faces.component.UIComponent.encodeAll(UIComponent.java:1819)
at javax.faces.render.Renderer.encodeChildren(Renderer.java:168)
at javax.faces.component.UIComponentBase.encodeChildren(UIComponentBase.java:847)
at com.sun.faces.renderkit.html_basic.HtmlBasicRenderer.encodeRecursive(HtmlBasicRenderer.java:304)
at com.sun.faces.renderkit.html_basic.GroupRenderer.encodeChildren(GroupRenderer.java:105)
at javax.faces.component.UIComponentBase.encodeChildren(UIComponentBase.java:847)
at com.sun.faces.renderkit.html_basic.HtmlBasicRenderer.encodeRecursive(HtmlBasicRenderer.java:304)
at com.sun.faces.renderkit.html_basic.GroupRenderer.encodeChildren(GroupRenderer.java:105)
at javax.faces.component.UIComponentBase.encodeChildren(UIComponentBase.java:847)
at javax.faces.component.UIComponent.encodeAll(UIComponent.java:1819)
at com.sun.faces.renderkit.html_basic.CompositeRenderer.encodeChildren(CompositeRenderer.java:78)
at javax.faces.component.UIComponentBase.encodeChildren(UIComponentBase.java:847)
at javax.faces.component.UIComponent.encodeAll(UIComponent.java:1819)
at javax.faces.component.UIComponent.encodeAll(UIComponent.java:1822)
at javax.faces.component.UIComponent.encodeAll(UIComponent.java:1822)
at com.sun.faces.application.view.FaceletViewHandlingStrategy.renderView(FaceletViewHandlingStrategy.java:447)
at com.sun.faces.application.view.MultiViewHandler.renderView(MultiViewHandler.java:125)
at com.ocpsoft.pretty.faces.application.PrettyViewHandler.renderView(PrettyViewHandler.java:159)
at com.sun.faces.lifecycle.RenderResponsePhase.execute(RenderResponsePhase.java:120)
at com.sun.faces.lifecycle.Phase.doPhase(Phase.java:101)
at com.sun.faces.lifecycle.LifecycleImpl.render(LifecycleImpl.java:139)
at javax.faces.webapp.FacesServlet.service(FacesServlet.java:594)
... 33 more
  1. It seems like the value of the lightbox is being passed to the inputs.

  2. have boiled the example down to a minimum to produce the error.

  3. I have tried on Mojarra 2.1.26, and 2.2.4.

BugTestBean.java

@ManagedBean(name="BugTestBean")
@ViewScoped
public class BugTestBean {
    private List<BugTestInput> inputs;

    public BugTestBean() {
        inputs = new ArrayList<BugTestInput>();
        inputs.add(new BugTestInput("Test1"));
        inputs.add(new BugTestInput("Test2"));
        inputs.add(new BugTestInput("Test3"));
        inputs.add(new BugTestInput("Test4"));
    }

    public List<BugTestInput> getInputs() {
        return inputs;
    }
}

bugTestInput.xhtml

<cc:interface>
    <cc:attribute name="value" />
</cc:interface>
<cc:implementation>
    <div id="#{cc.clientId}">
        <h:inputText id="input" value="#{cc.attrs.value.text}" />
    </div>
</cc:implementation>

BugTestInput.java

public class BugTestInput {
    private String text;

    public BugTestInput(String text) {
        this.text = text;
    }

    public String getText() {
        return text;
    }

    public void setText(String text) {
        this.text = text;
    }
}

lightbox.xhtml

<cc:interface>
    <cc:attribute name="value" />
</cc:interface>
<cc:implementation>
    <div id="#{cc.clientId}">
        <h:outputText value="#{cc.attrs.value}" />
        <h:panelGroup>
            <cc:insertChildren />
        </h:panelGroup>
    </div>
</cc:implementation>

Current Solutions

  1. Renaming the attribute value to something else on the lightbox fixes this problem.

  2. Leaving the attribute value empty on the lightbox also works.

  3. Not using the ui:repeat will also fix the problem, but this isn't solid.

Currently i am using 2 attributes on the lightbox and leaving the value empty when needed

<h:outputText value="#{cc.attrs.value}#{cc.attrs.title}" />

Follow up Regardless of what the attribute name is, if they are the same on both components it will fail. Is this a bug in JSF, i have searched the bug trackers and most new patch notes without result.

1
+1 for providing a well explained and clear SSCCE. Well done for your first question!Xtreme Biker

1 Answers

0
votes

Have you tried using <c:forEach> tag under JSTL, instead of <ui:repeat>? I have always faces issues with the <ui:repeat> tag.

<c:forEach> should work if you do not re-render the component using ajax calls.