tags:

views:

420

answers:

1

Hello, I am using datatable on page and using binding attribute to bind it to my backing bean. This is my code :-

<?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"&gt;
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:h="http://java.sun.com/jsf/html"
      xmlns:p="http://primefaces.prime.com.tr/ui"&gt;
    <h:head>
        <title>Facelet Title</title>
    </h:head>
    <h:body>
            <h:form prependId="false">

                <h:dataTable var="item" value="#{testBean.stringCollection}" binding="#{testBean.dataTable}">
                    <h:column>
                        <h:outputText value="#{item}"/>
                    </h:column>
                    <h:column>
                        <h:commandButton value="Click" actionListener="#{testBean.action}"/>
                    </h:column>
                </h:dataTable>

            </h:form>

    </h:body>
</html>

This is my bean :-

package managedBeans;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import javax.annotation.PostConstruct;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;
import javax.faces.component.html.HtmlDataTable;

@ManagedBean(name="testBean")
@ViewScoped
public class testBean implements Serializable {

    private List<String> stringCollection;

    public List<String> getStringCollection() {
        return stringCollection;
    }

    public void setStringCollection(List<String> stringCollection) {
        this.stringCollection = stringCollection;
    }

    private HtmlDataTable dataTable;

    public HtmlDataTable getDataTable() {
        return dataTable;
    }

    public void setDataTable(HtmlDataTable dataTable) {
        this.dataTable = dataTable;
    }

    @PostConstruct
    public void init(){
        System.out.println("Post Construct fired!!");
        stringCollection = new ArrayList<String>();
        stringCollection.add("a");
        stringCollection.add("b");
        stringCollection.add("c");

    }

    public void action(){
        System.out.println("Clicked!!");

    }
}

Please tell me why is the @PostConstruct firing each and every time i click on button? It should fire only once as long as i am on same page beacause my bean is @ViewScoped. Further, if i remove the binding attribute then everything works fine and @PostConstruct callback fires only once. Then why every time when i use binding attribute? I need binding attribute and want to perform initialisation tasks like fetching data from webservice, etc only once. What should i do? Where should i write my initialisation task?

+3  A: 

Interesting, when you're using component binding, the view scope fails.

I am not sure if that is a bug in JSF2, I would have to read the entire JSF2 specification first. As far now your best bet is to drop the component binding for now and use <f:setPropertyActionListener> DataModel#getRowData() instead to get hold of the iterated item in the bean. Also see this article.

BalusC
wow you mean a beginner like me found a bug in JSF? Hip Hip Hurrey. I feel so proud :). How come nobody experienced this till now?Ok BalusC, i will do as you said, but another alternative is to use other managed bean which can be specially used for binding components only and no real logic in it(backing beans). Is this approach also correct?
Ankit Rathod
The JSF spec doesn't say any word about this. I've filed [an issue](https://javaserverfaces.dev.java.net/issues/show_bug.cgi?id=1658). By the way I could now reproduce your problem that only the 1st item was returned everytime. I made a mistake in my environment, the same bean was namely already declared as request scoped in faces-config.xml, which has overridden the annotations.
BalusC
Hmm! :) so is that too a bug? about datatable?
Ankit Rathod
See the updated answer, `DataModel#getRowData()` is a better choice.
BalusC
fine! i am seeing.
Ankit Rathod
Hey thanks, you mentioned the questions to my links too :)
Ankit Rathod
Created an account and voted for the issue.
Ankit Rathod
You're welcome. Actually, *thank you* for blogging inspiration :)
BalusC
Hi BalusC, I read your article about ViewScoped as well as reading this posts. I have two questions for you. First: why would people binding a table to the managed bean. In this example, I think he mention of binding the dataTable to initialize its value, but you can just initialize a list of object in @PostConstruct, and display them in dataTable. Would that not accomplish the same result? Secondly: in your project, u used DataModel, so if u wrap the list of object, that u want to display in dataTable, in a DataModel, then whichever row the user selected, u will know if u call getRowData()?
Harry Pham
1) It's a leftover from JSF 1.x. 2) Yes. Just `getRowData()` in action method will give you the row where action is been invoked.
BalusC
Sweet buddy :D Thank you
Harry Pham