0

I want to pass selectedExamId from chooseexam page to exam page, what is the good way to do that? is it a good practice to use two baking bean for single jsf page?

One more thing is I am getting same Question list each time?

I have following jsf page

chooseExam.xhtml
<?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 lang="en"
      xmlns="http://www.w3.org/1999/xhtml"
      xmlns:h="http://java.sun.com/jsf/html"
      xmlns:ui="http://java.sun.com/jsf/facelets"
      xmlns:f="http://java.sun.com/jsf/core">
<h:head>

</h:head>
<h:body>
    <ui:composition template="/templates/admin/template.xhtml">
        <ui:define name="content">
            <h:selectOneRadio value="#{examBean.selectedExamId}">
                <f:selectItems value="#{chooseExamBean.exams}" var="exam" itemValue="#{exam.examId}" itemLabel="#{exam.examName}"/>
            </h:selectOneRadio>
            <h:commandButton value="Submit" action="/user/exam?faces-redirect=true"/>
        </ui:define>
    </ui:composition>
</h:body>

</html>

and

exam.xhtml
<?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 lang="en"
      xmlns="http://www.w3.org/1999/xhtml"
      xmlns:h="http://java.sun.com/jsf/html"
      xmlns:ui="http://java.sun.com/jsf/facelets"
      xmlns:f="http://java.sun.com/jsf/core">
<h:head>

</h:head>
<h:body>
    <ui:composition template="/templates/admin/template.xhtml">
        <ui:define name="content">
            <ui:repeat value="#{examBean.questions}" var="question">
                <h:outputLabel value="#{question.question}"/>
                <h:selectOneRadio value="#{examBean.questionAnswerMap[question]}">
                    <f:selectItem itemValue="#{question.choice1}" itemLabel="#{question.choice1}"/>
                    <f:selectItem itemValue="#{question.choice2}" itemLabel="#{question.choice2}"/>
                    <f:selectItem itemValue="#{question.choice3}" itemLabel="#{question.choice3}"/>
                    <f:selectItem itemValue="#{question.choice4}" itemLabel="#{question.choice4}"/>
                </h:selectOneRadio>
            </ui:repeat>
            <h:commandButton value="Submit" action="#{examBean.calculate}"/>
        </ui:define>
    </ui:composition>
</h:body>

</html>

following are the backing beans

ChooseExamBean.java
@Component
@ManagedBean
public class ChooseExamBean {
    List<Exam> exams;
    @Autowired
    private ExamService examService;

    @PostConstruct
    public void init(){
        exams = examService.getAllExams();
    }

    public List<Exam> getExams() {
        return exams;
    }

    public void setExams(List<Exam> exams) {
        this.exams = exams;
    }
}

and

ExamBean.java
@Component
@ManagedBean
public class ExamBean {
    private List<Question> questions;
    private Map<Question, String> questionAnswerMap = new HashMap<>();
    private int score;
    private Long selectedExamId;

    @Autowired
    private QuestionService questionService;

    @PostConstruct
    public void init() {
        if(selectedExamId != null)
            questions = questionService.getQuestionsForExam(selectedExamId);
    }


    public Map<Question, String> getQuestionAnswerMap() {
        return questionAnswerMap;
    }

    public void setQuestionAnswerMap(Map<Question, String> questionAnswerMap) {
        this.questionAnswerMap = questionAnswerMap;
    }

    public List<Question> getQuestions() {
        if(questions == null)
            questions = questionService.getQuestionsForExam(selectedExamId);
        return questions;
    }

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

    public int getScore() {
        return score;
    }

    public void setScore(int score) {
        this.score = score;
    }

    public Long getSelectedExamId() {
        return selectedExamId;
    }

    public void setSelectedExamId(Long selectedExamId) {
        this.selectedExamId = selectedExamId;
    }

    public String calculate() {
        score = questionAnswerMap.size();
        return "result?faces-redirect=true";
    }
}
eatSleepCode
  • 4,427
  • 7
  • 44
  • 93

1 Answers1

1

Since you are using a RequestScope Beans for the (ExamBean and the ChooseExamBean) you cant keep the values after the response , so you should user the viewParam tag to pass the value from the first page to the second page.

you should make something like the following :

1- the ChooseExam.jsf , you have your radioButtons that will save its value in the chooseExamBean :

<f:view xmlns:f="http://java.sun.com/jsf/core" xmlns:h="http://java.sun.com/jsf/html">
    <html xmlns="http://www.w3.org/1999/xhtml">
        <h:head></h:head>
        <h:body>
            <h:form>
                <h:selectOneRadio label="examType" value="#{chooseExamBean.examNumber}">
                    <f:selectItem itemLabel="exam1" itemValue="1"/>
                    <f:selectItem itemLabel="exam2" itemValue="2"/>
                </h:selectOneRadio>
                <h:commandButton value="commandButton1" action="#{chooseExamBean.navigateToExamPage}" />
            </h:form>
        </h:body>
    </html>
</f:view>

2- in the action of the commandButton you will call a method in the bean to navigate , before navigation you will append a param to the url like the following in the navigateToExamPage method :

@ManagedBean(name = "chooseExamBean")
@RequestScoped
public class ChooseExamBean {
    public ChooseExamBean() {
        super();
    }

    private String examNumber;

    public void setExamNumber(String examNumber) {
        this.examNumber = examNumber;
    }

    public String getExamNumber() {
        return examNumber;
    }


    public Object navigateToExamPage() {
        return "exam?faces-redirect=true&examId="+getExamNumber();
    }
}

3- in the exam.jsf page , you have to get the value of the parameter , here you will use the tag like the following :

<f:view xmlns:f="http://java.sun.com/jsf/core" xmlns:h="http://java.sun.com/jsf/html">
    <html xmlns="http://www.w3.org/1999/xhtml">
        <h:head></h:head>
        <h:body>
            <h:form>
                <f:metadata>
                    <f:viewParam name="examId" value="#{examBean.examNumber}"/>
                    <f:event type="preRenderView" listener="#{examBean.onLoad}" />
                </f:metadata>
                <h:outputText value="#{examBean.examNumber}"/>
            </h:form>
        </h:body>
    </html>
</f:view>

the view param have to attributes :

1- name :which is the name of the parameter that you want to get from the url.

2- value :which is where you want to set the value of the parameter.

so in our case the name is "examId" and we want to set the value in "examBean.examNumber" .

here you will find a problem if you didnt use tag , because you want to get the examId onPage Load in the postConstrct method , but the f:param will be called after the postConstruct , so we have to use the like the following :

<f:event type="preRenderView" listener="#{examBean.onLoad}" />

this will help us to perform custom task before a JSF page is displayed.

4- in you examBean :

@ManagedBean(name = "examBean")
@RequestScoped
public class ExamBean {
    public ExamBean() {
        super();
    }

    private String examNumber;

    public void setExamNumber(String examNumber) {
        this.examNumber = examNumber;
    }

    public String getExamNumber() {
        return examNumber;
    }

    public void onLoad () {
        System.out.println("onLoad = "+getExamNumber());
    }


}

Please use this with your requirements and everything will go smooth.

Please refer to the following answer here, here and here .

Hope that Helps.

Community
  • 1
  • 1