5
votes

I have a question to the Primefaces Datatable, especially to the Selection Object.

In my following Code I get always Null for the Variable "Selected Question" which is bound to the Datatable with Selection.

The jsf as followed:

    <?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" xml:lang="en" lang="en"
      xmlns:h="http://java.sun.com/jsf/html"
      xmlns:f="http://java.sun.com/jsf/core"
      xmlns:p="http://primefaces.org/ui"
      xmlns:ui="http://java.sun.com/jsf/facelets">

    <ui:composition template="mainTemplate.xhtml">
        <ui:define name="contentTitle">Your Questions</ui:define>
        <ui:define name="content">
            <h:form id="formAllQuestion">
                <p:growl id="allQuestionGrowl" showDetail="true"/>

                <p:dataTable id="allQuestionsTable" var="question" value="#{allQuestionBean.allQuestionDataHelper}" paginator="true" rows="10"
                            selection="#{allQuestionBean.selectedQuestion}" selectionMode="single">

                    <p:ajax event="rowSelect" listener="#{allQuestionBean.onRowSelect}" update=":formAllQuestion:AnswerToQuestionDialogTable :formAllQuestion:allQuestionGrowl"
                            oncomplete="questDialog.show()"/>
                    <p:ajax event="rowUnselect" listener="#{allQuestionBean.onRowUnselect}" update=":formAllQuestion:allQuestionGrowl"/>


                    <f:facet name="header">Select a Row to display your Question Details</f:facet>

                    <p:column headerText="QuestionID">
                        #{question.questionId}
                    </p:column>
                    <p:column headerText="Question Name">
                        #{question.questionName}
                    </p:column>
                    <p:column headerText="Question Description">
                        #{question.questionText}
                    </p:column>
                    <p:column headerText="Question Short Description">
                        #{question.questionShortText}
                    </p:column>
                    <p:column headerText="Author">
                        #{question.professor.profSurename} #{question.professor.profName}
                    </p:column>
                </p:dataTable>


                <p:dialog header="Question Details" widgetVar="questionDialog" resizable="true" id="questDialog"
                          showEffect="fade" hideEffect="fade" modal="true">
                    <p:dataTable id="AnswerToQuestionDialogTable" var="answer" value="#{allQuestionBean.answers}">

                        <f:facet name="header">
                            Hier kommt der QR_Code rein!

                            #{allQuestionBean.selectedQuestion.questionId} - #{allQuestionBean.selectedQuestion.questionName}
                        </f:facet>

                        <p:column headerText="Answer">
                            <h:outputText value="#{answer.answerText}"/>
                        </p:column>
                        <p:column headerText="Counts For this Answer">
                            <h:outputText value="Bis jetz noch nix!"/>
                        </p:column>
                    </p:dataTable>
                </p:dialog>


            </h:form>
        </ui:define>
    </ui:composition>

</html>

And the associated Bean Class (AllQuestionBean.class):

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


    private static final long serialVersionUID = 7038894302985973905L;

    @ManagedProperty(value = "#{questionDAO}")
    private QuestionDAO questionDAO;

    @ManagedProperty(value = "#{profSession.professor}")
    private Professor professor;

    @ManagedProperty(value = "#{answerDAO}")
    private AnswerDAO answerDAO;

    @ManagedProperty(value = "#{answeredDAO}")
    private AnsweredDAO answeredDAO;


    private List<Question> questions;
    private Question selectedQuestion;
    private List<Answer> answers;
    private AllQuestionDataHelper allQuestionDataHelper;


    public AllQuestionBean(){
        System.out.println("Starting Bean: "+this.getClass().getName());
    }

    @PostConstruct
    public void initVariables(){
        questions = questionDAO.readByProfessor(professor);
    }

    public void onRowSelect(SelectEvent event) {



        FacesMessage msg = new FacesMessage("Question Selected", selectedQuestion.getQuestionId()+" -- "+selectedQuestion.getQuestionName());

        FacesContext.getCurrentInstance().addMessage(null, msg);
    }

    public void onRowUnselect(UnselectEvent event) {

        FacesMessage msg = new FacesMessage("Question Selected", selectedQuestion.getQuestionId()+" -- "+selectedQuestion.getQuestionName());

        FacesContext.getCurrentInstance().addMessage(null, msg);
    }


    //---GETTER and SETTER

    public AllQuestionDataHelper getAllQuestionDataHelper() {
        allQuestionDataHelper = new AllQuestionDataHelper(questions);
        return allQuestionDataHelper;
    }


    public void setAllQuestionDataHelper(AllQuestionDataHelper allQuestionDataHelper) {
        this.allQuestionDataHelper = allQuestionDataHelper;
    }



    public QuestionDAO getQuestionDAO() {
        return questionDAO;
    }

    public void setQuestionDAO(QuestionDAO questionDAO) {
        this.questionDAO = questionDAO;
    }

    public Professor getProfessor() {
        return professor;
    }

    public void setProfessor(Professor professor) {
        this.professor = professor;
    }

    public AnswerDAO getAnswerDAO() {
        return answerDAO;
    }

    public void setAnswerDAO(AnswerDAO answerDAO) {
        this.answerDAO = answerDAO;
    }

    public AnsweredDAO getAnsweredDAO() {
        return answeredDAO;
    }

    public void setAnsweredDAO(AnsweredDAO answeredDAO) {
        this.answeredDAO = answeredDAO;
    }

    public List<Question> getQuestions() {
        return questions;
    }

    public void setQuestions(List<Question> questions) {
        this.questions = questions;
    }

    public Question getSelectedQuestion() {
        System.out.println("getSelectedQuestion");
        return selectedQuestion;
    }

    public void setSelectedQuestion(Question selectedQuestion) {
        System.out.println("Set selected Question: "+selectedQuestion);
        this.selectedQuestion = selectedQuestion;
    }

    public List<Answer> getAnswers() {
        answers = answerDAO.getAllAnswersForQuestion(selectedQuestion);
        return answers;
    }

    public void setAnswers(List<Answer> answers) {
        this.answers = answers;
    }
    }

The Data Modell:

public class AllQuestionDataHelper extends ListDataModel<Question> implements SelectableDataModel<Question> {


    public AllQuestionDataHelper() {
    }

    public AllQuestionDataHelper(List<Question> list) {
        super(list);
    }

    @Override
    public Object getRowKey(Question question) {
        if(!(question == null)){
        System.out.println("Your Questions --> Getting RowKey");
        System.out.println("RowKey: "+question);
        System.out.println("RowKey: "+question.getQuestionId());
        }else{
            System.out.println("Warning Row Key is null");
        }
        return question.getQuestionId();
    }

    @Override
    public Question getRowData(String rowKey) {
        System.out.println("Your Questions --> Getting RowData");
        System.out.println("RowData: "+rowKey);

        List<Question> questionList = (List<Question>) getWrappedData();

        for(Question q : questionList){
            if(rowKey.equals(q.getQuestionId())){
                System.out.println("Returning "+q.getQuestionId());
                return q;
            }
        }
        return null;
    }
}

I debugged a few runs and mentioned that the Variable "selectedQuestion" in AllQuestionBean.class is never set. Will say, the event Variable in "onRowSelect" holds a NULL-Object. As you can see there are two Datatables in the *.xhtml. The first one will load normally, no problems. The onClick-Method of the Bean should launch a Dialog with the Second Datatable, but will quit with a Nullpointer.

For the Datatable I followed the Tutorial at Primefaces (http://www.primefaces.org/showcase-labs/ui/datatableRowSelectionInstant.jsf)

1
Do you not need a rowKey for the datatable you are selecting from?JamesB
I thought the rowKey comes from the Data Model. One Moment, I will update the Question, with the Model Sources.Chris
Ok, I solved the Problem with the Nullpointer. It was the getRowData()-Method in the DataModel Class. I tried to equal a String with an Integer, that happens at this Time :) Ok, the Table wont throw an Nullpointer now, but facing another Problem. I can only Click ONE Time at the Table. Every other Click has no Impact on the Table. Can there be a Problem with the Scope or with Ajax??Chris

1 Answers

2
votes

Use rowKey attribute on p:dataTable.

rowKey is a unique Identifier that helps Primefaces engine to return the selected Object based on selection.

Usually the value you supply to the rowKey attribute is the unique property of the POJO that you are populating in to p:dataTable.

If you don't have any such unique fields in your POJO. Then its always useful to make one, for example: int rowId;, which you might increment and put in to POJO while you adding them to the List.