3
votes

I have a problem with a binding p:commandButton to a property in a backing bean. I've tried to simplify my code to show general idea.

ExampleBean is a backing bean

public class ExampleBean {

    public String title;        
    List<ExampleWrapper> list;

    // Getters and setters

}

ExampleWrapper is a POJO

public class Wrapper {

    public String name;
    public String description;

    public CommandButton button;

    // Listener which changes button state

    // Getters and setters
}

index.xhtml is a main page:

<h:form>
    <h:outputText value="Title" />
    <p:inpurText value="#{exampleBean.title}"

    <ui:include src="list.xhtml">
        <ui:param name="bean" value="#{exampleBean}">
    </ui:include>
</h:form>

list.xhtml is a fragment I want to be reused in a few places:

<ui:composition ...>
    <ui:repeat id="list" var="exampleWrapper" value="#{bean.list}">
        <h:outputText value="#{exampleWrapper.name}"/>
        <h:outputTextarea value="#{exampleWrapper.description}"/>
        <p:commandButton id="button" binding="#{exampleWrapper.button}" 
            value="Button" />
</ui:composition>

So, I get exception: javax.el.PropertyNotFoundException: /list.xhtml ... binding="#{exampleWrapper.button}": Target Unreachable, identifier 'exampleWrapper' resolved to null

Without binding attribute everything works and displays fine

Could you explain why and how can I bind button to this POJO property? Any help will be appreciated

I'm using JSF 2.0.2 with Primefaces 3.0.1

1

1 Answers

6
votes

The binding (and id) attribute of a JSF UI component is resolved during view build time. The #{exampleWrapper} instance is not available during the view build time. The view build time is that moment when the XHTML file is parsed into a JSF component tree. The #{exampleWrapper} is only available during the view render time. The view render time is the moment when the JSF component tree generates HTML output.

Basically, there's only one <p:commandButton> in the component tree which generates its HTML output multiple times as many as the <ui:repeat> iterates. You need to bind it to the #{bean} instead, or to use JSTL <c:forEach> instead of <ui:repeat>. The JSTL tags runs namely during view build time and the <c:forEach> will thus produce physically multiple JSF UI components. But, more than often, binding components to backing beans is unnecessary in JSF 2.x. Whatever functional requirement you've had in mind for which you thought that this is the solution, it can definitely be solved in a better way.